Update thirdparty libs

This commit is contained in:
halx99 2023-02-04 15:03:54 +08:00
parent 09b32e26d5
commit c44c84a1ca
281 changed files with 10186 additions and 8458 deletions

20
thirdparty/README.md vendored
View File

@ -6,7 +6,7 @@
## astc ## astc
- [![Upstream](https://img.shields.io/github/v/release/ARM-software/astc-encoder?label=Upstream)](https://github.com/ARM-software/astc-encoder) - [![Upstream](https://img.shields.io/github/v/release/ARM-software/astc-encoder?label=Upstream)](https://github.com/ARM-software/astc-encoder)
- Version: 4.3.0 - Version: 4.3.1
- License: Apache-2.0 - License: Apache-2.0
## Box2D ## Box2D
@ -21,13 +21,13 @@
## Bullet ## Bullet
- [![Upstream](https://img.shields.io/github/v/release/bulletphysics/bullet3?label=Upstream)](https://github.com/bulletphysics/bullet3) - [![Upstream](https://img.shields.io/github/v/release/bulletphysics/bullet3?label=Upstream)](https://github.com/bulletphysics/bullet3)
- Version: 3.24 - Version: 3.25
- License: zlib - License: zlib
- Update method: Compare `axmol/thirdparty/bullet` with `bullet3/src` - Update method: Compare `axmol/thirdparty/bullet` with `bullet3/src`
## c-ares ## c-ares
- [![Upstream](https://img.shields.io/github/v/release/c-ares/c-ares?label=Upstream)](https://github.com/c-ares/c-ares) - [![Upstream](https://img.shields.io/github/v/release/c-ares/c-ares?label=Upstream)](https://github.com/c-ares/c-ares)
- Version: git 1.18.1-c25d4eb (2138) - Version: git 1.19.0-bb8f5bb (2184)
- License: MIT - License: MIT
## Chipmunk2D ## Chipmunk2D
@ -161,7 +161,7 @@
## OpenAL Soft ## OpenAL Soft
- [![Upstream](https://img.shields.io/github/v/tag/kcat/openal-soft?label=Upstream)](https://github.com/kcat/openal-soft) - [![Upstream](https://img.shields.io/github/v/tag/kcat/openal-soft?label=Upstream)](https://github.com/kcat/openal-soft)
- Version: 1.22.2 - Version: 1.23.0
- License: LGPL-2.1 - License: LGPL-2.1
## OpenSSL ## OpenSSL
@ -180,8 +180,10 @@
- License: BSD-3-Clause - License: BSD-3-Clause
## pugixml ## pugixml
- [![Upstream](https://img.shields.io/github/v/tag/zeux/pugixml?label=Upstream)](https://github.com/zeux/pugixml) - [![Upstream](https://img.shields.io/github/v/tag/halx99/pugixml?label=Upstream)](https://github.com/halx99/pugixml) by halx99 for string_view support
- Version: 1.12.1 - original repo: https://github.com/zeux/pugixml
- all tests passed: https://github.com/halx99/pugixml/actions/runs/4090401630
- Version: 1.13
- License: MIT - License: MIT
## rapidjson ## rapidjson
@ -203,7 +205,7 @@
## stb (stb_image) ## stb (stb_image)
- Upstream: https://github.com/nothings/stb - Upstream: https://github.com/nothings/stb
- Version: 2.27 - Version: 2.28
- License: MIT - License: MIT
## unzip (minizip-1.2) ## unzip (minizip-1.2)
@ -218,7 +220,7 @@
## webp ## webp
- [![Upstream](https://img.shields.io/github/v/tag/webmproject/libwebp?label=Upstream)](https://github.com/webmproject/libwebp) - [![Upstream](https://img.shields.io/github/v/tag/webmproject/libwebp?label=Upstream)](https://github.com/webmproject/libwebp)
- Version: 1.2.4 - Version: 1.3.0
- License: Google Inc - License: Google Inc
## xsbase ## xsbase
@ -248,7 +250,7 @@
## ntcvt ## ntcvt
- [![Upstream](https://img.shields.io/github/v/tag/simdsoft/ntcvt?label=Upstream)](https://github.com/simdsoft/ntcvt) - [![Upstream](https://img.shields.io/github/v/tag/simdsoft/ntcvt?label=Upstream)](https://github.com/simdsoft/ntcvt)
- Version: git-8422188 (7) - Version: 0.0.2
- License: Apache-2.0 - License: Apache-2.0
## Some third party libs supporting axmol too: ## Some third party libs supporting axmol too:

View File

@ -48,8 +48,6 @@
#define ASTCENC_SSE 42 #define ASTCENC_SSE 42
#elif defined(__SSE4_1__) #elif defined(__SSE4_1__)
#define ASTCENC_SSE 41 #define ASTCENC_SSE 41
#elif defined(__SSE3__)
#define ASTCENC_SSE 30
#elif defined(__SSE2__) #elif defined(__SSE2__)
#define ASTCENC_SSE 20 #define ASTCENC_SSE 20
#else #else

View File

@ -1046,7 +1046,7 @@ ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4& t0p)
*/ */
ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4 t1, vint4& t0p, vint4& t1p) ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4 t1, vint4& t0p, vint4& t1p)
{ {
#if ASTCENC_SSE >= 30 #if ASTCENC_SSE >= 41
t0p = t0; t0p = t0;
t1p = t0 ^ t1; t1p = t0 ^ t1;
#else #else
@ -1062,7 +1062,7 @@ ASTCENC_SIMD_INLINE void vtable_prepare(
vint4 t0, vint4 t1, vint4 t2, vint4 t3, vint4 t0, vint4 t1, vint4 t2, vint4 t3,
vint4& t0p, vint4& t1p, vint4& t2p, vint4& t3p) vint4& t0p, vint4& t1p, vint4& t2p, vint4& t3p)
{ {
#if ASTCENC_SSE >= 30 #if ASTCENC_SSE >= 41
t0p = t0; t0p = t0;
t1p = t0 ^ t1; t1p = t0 ^ t1;
t2p = t1 ^ t2; t2p = t1 ^ t2;
@ -1080,7 +1080,7 @@ ASTCENC_SIMD_INLINE void vtable_prepare(
*/ */
ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx) ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx)
{ {
#if ASTCENC_SSE >= 30 #if ASTCENC_SSE >= 41
// Set index byte MSB to 1 for unused bytes so shuffle returns zero // Set index byte MSB to 1 for unused bytes so shuffle returns zero
__m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00))); __m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00)));
@ -1102,7 +1102,7 @@ ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx)
*/ */
ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx) ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx)
{ {
#if ASTCENC_SSE >= 30 #if ASTCENC_SSE >= 41
// Set index byte MSB to 1 for unused bytes so shuffle returns zero // Set index byte MSB to 1 for unused bytes so shuffle returns zero
__m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00))); __m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00)));
@ -1130,7 +1130,7 @@ ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx)
*/ */
ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 t2, vint4 t3, vint4 idx) ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 t2, vint4 t3, vint4 idx)
{ {
#if ASTCENC_SSE >= 30 #if ASTCENC_SSE >= 41
// Set index byte MSB to 1 for unused bytes so shuffle returns zero // Set index byte MSB to 1 for unused bytes so shuffle returns zero
__m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00))); __m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00)));

View File

@ -103,7 +103,8 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId,
if (m_convexBodyWrap->getCollisionShape()->isConvex()) if (m_convexBodyWrap->getCollisionShape()->isConvex())
{ {
#ifndef BT_DISABLE_CONVEX_CONCAVE_EARLY_OUT #ifdef BT_ENABLE_CONVEX_CONCAVE_EARLY_OUT
//todo: check this issue https://github.com/bulletphysics/bullet3/issues/4263
//an early out optimisation if the object is separated from the triangle //an early out optimisation if the object is separated from the triangle
//projected on the triangle normal) //projected on the triangle normal)
{ {
@ -139,7 +140,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId,
if (dist > contact_threshold) if (dist > contact_threshold)
return; return;
} }
#endif //BT_DISABLE_CONVEX_CONCAVE_EARLY_OUT #endif //BT_ENABLE_CONVEX_CONCAVE_EARLY_OUT
btTriangleShape tm(triangle[0], triangle[1], triangle[2]); btTriangleShape tm(triangle[0], triangle[1], triangle[2]);
tm.setMargin(m_collisionMarginTriangle); tm.setMargin(m_collisionMarginTriangle);

View File

@ -229,10 +229,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]); m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]); m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]); m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]); m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]); m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]); m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
} }
btAABB(const btVector3 &V1, btAABB(const btVector3 &V1,
@ -243,10 +245,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]); m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]); m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]); m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]); m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]); m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]); m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
m_min[0] -= margin; m_min[0] -= margin;
m_min[1] -= margin; m_min[1] -= margin;
@ -275,9 +279,11 @@ public:
m_min[0] = SIMD_INFINITY; m_min[0] = SIMD_INFINITY;
m_min[1] = SIMD_INFINITY; m_min[1] = SIMD_INFINITY;
m_min[2] = SIMD_INFINITY; m_min[2] = SIMD_INFINITY;
m_min[3] = 0.f;
m_max[0] = -SIMD_INFINITY; m_max[0] = -SIMD_INFINITY;
m_max[1] = -SIMD_INFINITY; m_max[1] = -SIMD_INFINITY;
m_max[2] = -SIMD_INFINITY; m_max[2] = -SIMD_INFINITY;
m_max[3] = 0.f;
} }
SIMD_FORCE_INLINE void increment_margin(btScalar margin) SIMD_FORCE_INLINE void increment_margin(btScalar margin)
@ -295,10 +301,12 @@ public:
m_min[0] = other.m_min[0] - margin; m_min[0] = other.m_min[0] - margin;
m_min[1] = other.m_min[1] - margin; m_min[1] = other.m_min[1] - margin;
m_min[2] = other.m_min[2] - margin; m_min[2] = other.m_min[2] - margin;
m_min[3] = 0.f;
m_max[0] = other.m_max[0] + margin; m_max[0] = other.m_max[0] + margin;
m_max[1] = other.m_max[1] + margin; m_max[1] = other.m_max[1] + margin;
m_max[2] = other.m_max[2] + margin; m_max[2] = other.m_max[2] + margin;
m_max[3] = 0.f;
} }
template <typename CLASS_POINT> template <typename CLASS_POINT>
@ -310,10 +318,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]); m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]); m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]); m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]); m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]); m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]); m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
} }
template <typename CLASS_POINT> template <typename CLASS_POINT>
@ -325,10 +335,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]); m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]); m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]); m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]); m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]); m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]); m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
m_min[0] -= margin; m_min[0] -= margin;
m_min[1] -= margin; m_min[1] -= margin;

View File

@ -4,8 +4,8 @@ Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty. This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely, including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions: subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
@ -19,8 +19,10 @@ subject to the following restrictions:
#include "btPointCollector.h" #include "btPointCollector.h"
#include "LinearMath/btTransformUtil.h" #include "LinearMath/btTransformUtil.h"
#ifdef MAX_ITERATIONS #ifdef BT_USE_DOUBLE_PRECISION
#define MAX_ITERATIONS 64 #define MAX_ITERATIONS 64
#else
#define MAX_ITERATIONS 32
#endif #endif
btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver) btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)

View File

@ -71,8 +71,8 @@ public:
const btVector3& normal, const btVector3& normal,
btScalar distance) : m_localPointA(pointA), btScalar distance) : m_localPointA(pointA),
m_localPointB(pointB), m_localPointB(pointB),
m_positionWorldOnB(0,0,0), m_positionWorldOnB(0,0,0),
m_positionWorldOnA(0,0,0), m_positionWorldOnA(0,0,0),
m_normalWorldOnB(normal), m_normalWorldOnB(normal),
m_distance1(distance), m_distance1(distance),
m_combinedFriction(btScalar(0.)), m_combinedFriction(btScalar(0.)),
@ -95,8 +95,8 @@ public:
m_contactERP(0.f), m_contactERP(0.f),
m_frictionCFM(0.f), m_frictionCFM(0.f),
m_lifeTime(0), m_lifeTime(0),
m_lateralFrictionDir1(0,0,0), m_lateralFrictionDir1(0,0,0),
m_lateralFrictionDir2(0,0,0) m_lateralFrictionDir2(0,0,0)
{ {
} }

View File

@ -169,9 +169,12 @@ btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
/*the column becomes part of the basis*/ /*the column becomes part of the basis*/
basis[pivotRowIndex] = pivotColIndexOld; basis[pivotRowIndex] = pivotColIndexOld;
bool isRayTermination = false;
pivotRowIndex = findLexicographicMinimum(A, pivotColIndex); pivotRowIndex = findLexicographicMinimum(A, pivotColIndex, z0Row, isRayTermination);
if (isRayTermination)
{
break; // ray termination
}
if (z0Row == pivotRowIndex) if (z0Row == pivotRowIndex)
{ //if z0 leaves the basis the solution is found --> one last elimination step is necessary { //if z0 leaves the basis the solution is found --> one last elimination step is necessary
GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis); GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
@ -217,79 +220,100 @@ btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
return solutionVector; return solutionVector;
} }
int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex) int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex, const int& z0Row, bool& isRayTermination)
{ {
int RowIndex = 0; isRayTermination = false;
btAlignedObjectArray<int> activeRows;
bool firstRow = true;
btScalar currentMin = 0.0;
int dim = A.rows(); int dim = A.rows();
btAlignedObjectArray<btVectorXu> Rows;
for (int row = 0; row < dim; row++) for (int row = 0; row < dim; row++)
{ {
btVectorXu vec(dim + 1); const btScalar denom = A(row, pivotColIndex);
vec.setZero(); //, INIT, 0.)
Rows.push_back(vec);
btScalar a = A(row, pivotColIndex);
if (a > 0)
{
Rows[row][0] = A(row, 2 * dim + 1) / a;
Rows[row][1] = A(row, 2 * dim) / a;
for (int j = 2; j < dim + 1; j++)
Rows[row][j] = A(row, j - 1) / a;
#ifdef BT_DEBUG_OSTREAM if (denom > btMachEps())
// if (DEBUGLEVEL) { {
// cout << "Rows(" << row << ") = " << Rows[row] << endl; const btScalar q = A(row, dim + dim + 1) / denom;
// } if (firstRow)
#endif {
currentMin = q;
activeRows.push_back(row);
firstRow = false;
}
else if (fabs(currentMin - q) < btMachEps())
{
activeRows.push_back(row);
}
else if (currentMin > q)
{
currentMin = q;
activeRows.clear();
activeRows.push_back(row);
}
} }
} }
for (int i = 0; i < Rows.size(); i++) if (activeRows.size() == 0)
{ {
if (Rows[i].nrm2() > 0.) isRayTermination = true;
return 0;
}
else if (activeRows.size() == 1)
{
return activeRows[0];
}
// if there are multiple rows, check if they contain the row for z_0.
for (int i = 0; i < activeRows.size(); i++)
{
if (activeRows[i] == z0Row)
{ {
int j = 0; return z0Row;
for (; j < Rows.size(); j++)
{
if (i != j)
{
if (Rows[j].nrm2() > 0.)
{
btVectorXu test(dim + 1);
for (int ii = 0; ii < dim + 1; ii++)
{
test[ii] = Rows[j][ii] - Rows[i][ii];
}
//=Rows[j] - Rows[i]
if (!LexicographicPositive(test))
break;
}
}
}
if (j == Rows.size())
{
RowIndex += i;
break;
}
} }
} }
return RowIndex; // look through the columns of the inverse of the basic matrix from left to right until the tie is broken.
} for (int col = 0; col < dim ; col++)
{
btAlignedObjectArray<int> activeRowsCopy(activeRows);
activeRows.clear();
firstRow = true;
for (int i = 0; i<activeRowsCopy.size();i++)
{
const int row = activeRowsCopy[i];
bool btLemkeAlgorithm::LexicographicPositive(const btVectorXu& v) // denom is positive here as an invariant.
{ const btScalar denom = A(row, pivotColIndex);
int i = 0; const btScalar ratio = A(row, col) / denom;
// if (DEBUGLEVEL) if (firstRow)
// cout << "v " << v << endl; {
currentMin = ratio;
activeRows.push_back(row);
firstRow = false;
}
else if (fabs(currentMin - ratio) < btMachEps())
{
activeRows.push_back(row);
}
else if (currentMin > ratio)
{
currentMin = ratio;
activeRows.clear();
activeRows.push_back(row);
}
}
while (i < v.size() - 1 && fabs(v[i]) < btMachEps()) if (activeRows.size() == 1)
i++; {
if (v[i] > 0) return activeRows[0];
return true; }
}
return false; // must not reach here.
isRayTermination = true;
return 0;
} }
void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis) void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis)

View File

@ -71,8 +71,7 @@ public:
} }
protected: protected:
int findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex); int findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex, const int& z0Row, bool& isRayTermination);
bool LexicographicPositive(const btVectorXu& v);
void GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis); void GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis);
bool greaterZero(const btVectorXu& vector); bool greaterZero(const btVectorXu& vector);
bool validBasis(const btAlignedObjectArray<int>& basis); bool validBasis(const btAlignedObjectArray<int>& basis);

View File

@ -678,7 +678,9 @@ HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the
if (vcount < 8) vcount = 8; if (vcount < 8) vcount = 8;
btAlignedObjectArray<btVector3> vertexSource; btAlignedObjectArray<btVector3> vertexSource;
vertexSource.resize(static_cast<int>(vcount)); btVector3 zero;
zero.setZero();
vertexSource.resize(static_cast<int>(vcount), zero);
btVector3 scale; btVector3 scale;

View File

@ -25,7 +25,7 @@ subject to the following restrictions:
#include <float.h> #include <float.h>
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/ /* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
#define BT_BULLET_VERSION 324 #define BT_BULLET_VERSION 325
inline int btGetVersion() inline int btGetVersion()
{ {

View File

@ -481,7 +481,7 @@ public:
buffer[9] = '3'; buffer[9] = '3';
buffer[10] = '2'; buffer[10] = '2';
buffer[11] = '4'; buffer[11] = '5';
} }
virtual void startSerialization() virtual void startSerialization()
@ -512,7 +512,7 @@ public:
currentPtr += BT_HEADER_LENGTH; currentPtr += BT_HEADER_LENGTH;
for (int i = 0; i < m_chunkPtrs.size(); i++) for (int i = 0; i < m_chunkPtrs.size(); i++)
{ {
int curLength = sizeof(btChunk) + m_chunkPtrs[i]->m_length; int curLength = (int)sizeof(btChunk) + m_chunkPtrs[i]->m_length;
memcpy(currentPtr, m_chunkPtrs[i], curLength); memcpy(currentPtr, m_chunkPtrs[i], curLength);
btAlignedFree(m_chunkPtrs[i]); btAlignedFree(m_chunkPtrs[i]);
currentPtr += curLength; currentPtr += curLength;

View File

@ -8,7 +8,7 @@ INCLUDE (CheckCSourceCompiles)
INCLUDE (CheckStructHasMember) INCLUDE (CheckStructHasMember)
INCLUDE (CheckLibraryExists) INCLUDE (CheckLibraryExists)
PROJECT (c-ares LANGUAGES C VERSION "1.18.0" ) PROJECT (c-ares LANGUAGES C VERSION "1.19.0" )
# Set this version before release # Set this version before release
SET (CARES_VERSION "${PROJECT_VERSION}") SET (CARES_VERSION "${PROJECT_VERSION}")
@ -26,7 +26,7 @@ INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are w
# For example, a version of 4:0:2 would generate output such as: # For example, a version of 4:0:2 would generate output such as:
# libname.so -> libname.so.2 # libname.so -> libname.so.2
# libname.so.2 -> libname.so.2.2.0 # libname.so.2 -> libname.so.2.2.0
SET (CARES_LIB_VERSIONINFO "7:1:5") SET (CARES_LIB_VERSIONINFO "8:0:6")
OPTION (CARES_STATIC "Build as a static library" OFF) OPTION (CARES_STATIC "Build as a static library" OFF)
@ -82,9 +82,14 @@ SET (TARGETS_INST_DEST
# Function in Library # Function in Library
# CHECK_LIBRARY_EXISTS can't be used as it will return true if the function # CHECK_LIBRARY_EXISTS can't be used as it will return true if the function
# is found in a different dependent library. # is found in a different required/dependent library.
MACRO (CARES_FUNCTION_IN_LIBRARY func lib var) MACRO (CARES_FUNCTION_IN_LIBRARY func lib var)
SET (_ORIG_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
SET (CMAKE_REQUIRED_LIBRARIES )
CHECK_FUNCTION_EXISTS ("${func}" "_CARES_FUNC_IN_LIB_GLOBAL_${func}") CHECK_FUNCTION_EXISTS ("${func}" "_CARES_FUNC_IN_LIB_GLOBAL_${func}")
SET (CMAKE_REQUIRED_LIBRARIES "${_ORIG_CMAKE_REQUIRED_LIBRARIES}")
IF ("${_CARES_FUNC_IN_LIB_GLOBAL_${func}}") IF ("${_CARES_FUNC_IN_LIB_GLOBAL_${func}}")
SET (${var} FALSE) SET (${var} FALSE)
ELSE () ELSE ()
@ -689,6 +694,12 @@ IF (CARES_INSTALL)
if( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) if( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" )
if ( "${CPACK_PACKAGE_ARCHITECTURE}" STREQUAL "" ) if ( "${CPACK_PACKAGE_ARCHITECTURE}" STREQUAL "" )
set( CPACK_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}" )
endif()
if ( "${CPACK_PACKAGE_ARCHITECTURE}" STREQUAL "" )
if ( "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows" )
message( FATAL_ERROR "Failed to determine CPACK_PACKAGE_ARCHITECTURE. Is CMAKE_SYSTEM_PROCESSOR set?" )
endif()
# Note: the architecture should default to the local architecture, but it # Note: the architecture should default to the local architecture, but it
# in fact comes up empty. We call `uname -m` to ask the kernel instead. # in fact comes up empty. We call `uname -m` to ask the kernel instead.
EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE ) EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE )

View File

@ -3,7 +3,7 @@ c-ares
[![Build Status](https://api.cirrus-ci.com/github/c-ares/c-ares.svg)](https://cirrus-ci.com/github/c-ares/c-ares) [![Build Status](https://api.cirrus-ci.com/github/c-ares/c-ares.svg)](https://cirrus-ci.com/github/c-ares/c-ares)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/aevgc5914tm72pvs/branch/master?svg=true)](https://ci.appveyor.com/project/c-ares/c-ares/branch/master) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/aevgc5914tm72pvs/branch/master?svg=true)](https://ci.appveyor.com/project/c-ares/c-ares/branch/master)
[![Coverage Status](https://coveralls.io/repos/c-ares/c-ares/badge.svg?branch=master&service=github)](https://coveralls.io/github/c-ares/c-ares?branch=master) [![Coverage Status](https://coveralls.io/repos/github/c-ares/c-ares/badge.svg)](https://coveralls.io/github/c-ares/c-ares)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/291/badge)](https://bestpractices.coreinfrastructure.org/projects/291) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/291/badge)](https://bestpractices.coreinfrastructure.org/projects/291)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/c-ares.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:c-ares) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/c-ares.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:c-ares)
[![Releases](https://coderelease.io/badge/c-ares/c-ares)](https://coderelease.io/github/repository/c-ares/c-ares) [![Releases](https://coderelease.io/badge/c-ares/c-ares)](https://coderelease.io/github/repository/c-ares/c-ares)

View File

@ -17,7 +17,7 @@ This utility comes with the \fBc\-ares\fR asynchronous resolver library.
\fB\-d\fR \fB\-d\fR
Print some extra debugging output. Print some extra debugging output.
.TP .TP
\fB\-h\fR, \fB\-\-help\fR \fB\-h\fR, \fB\-?\fR
Display this help and exit. Display this help and exit.
.TP .TP
\fB\-v\fR \fB\-v\fR

View File

@ -18,34 +18,40 @@ This utility comes with the \fBc\-ares\fR asynchronous resolver library.
\fB\-c\fR class \fB\-c\fR class
Set the query class. Set the query class.
Possible values for class are Possible values for class are
NY, CHAOS, HS, IN (default). ANY, CHAOS, HS and IN (default).
.TP .TP
\fB\-d\fR \fB\-d\fR
Print some extra debugging output. Print some extra debugging output.
.TP .TP
\fB\-f\fR flag \fB\-f\fR flag
Add a flag. Add a behavior control flag.
Possible values for flag are Possible values for flag are
igntc, noaliases, norecurse, primary, stayopen, usevc. igntc - ignore to query in TCP to get truncated UDP answer,
noaliases - don't honor the HOSTALIASES environment variable,
norecurse - don't query upstream servers recursively,
primary - use the first server,
stayopen - don't close the communication sockets, and
usevc - always use TCP.
.TP .TP
\fB\-h\fR, \fB\-\-help\fR \fB\-h\fR, \fB\-?\fR
Display this help and exit. Display this help and exit.
.TP .TP
\fB\-T\fR port
Use specified TCP port to connect to DNS server.
.TP
\fB\-s\fR server \fB\-s\fR server
Connect to specified DNS server, instead of the system's default one(s). Connect to specified DNS server, instead of the system's default one(s).
Servers are tried in round-robin, if the previous one failed.
.TP .TP
\fB\-t\fR type \fB\-t\fR type
Query records of specified type. Query records of specified type.
Possible values for type are Possible values for type are
A (default), AAAA, AFSDB, ANY, AXFR, CNAME, GPOS, HINFO, ISDN, KEY, LOC, MAILA, A (default), AAAA, AFSDB, ANY, AXFR, CNAME, GPOS, HINFO, ISDN, KEY, LOC, MAILA,
MAILB, MB, MD, MF, MG, MINFO, MR, MX, NAPTR, NS, NSAP, NSAP_PTR, NULL, MAILB, MB, MD, MF, MG, MINFO, MR, MX, NAPTR, NS, NSAP, NSAP_PTR, NULL,
PTR, PX, RP, RT, SIG, SOA, SRV, TXT, URI, WKS, X25, PTR, PX, RP, RT, SIG, SOA, SRV, TXT, URI, WKS and X25.
.TP
\fB\-T\fR port
Connect to the specified TCP port of DNS server.
.TP .TP
\fB\-U\fR port \fB\-U\fR port
Use specified UDP port to connect to DNS server. Connect to the specified UDP port of DNS server.
.TP .TP
\fB\-x\fR \fB\-x\fR
For an IPv4 \fB-t PTR a.b.c.d\fR lookup, query for For an IPv4 \fB-t PTR a.b.c.d\fR lookup, query for

View File

@ -17,7 +17,7 @@ This utility comes with the \fBc\-ares\fR asynchronous resolver library.
\fB\-d\fR \fB\-d\fR
Print some extra debugging output. Print some extra debugging output.
.TP .TP
\fB\-h\fR, \fB\-\-help\fR \fB\-h\fR, \fB\-?\fR
Display this help and exit. Display this help and exit.
.TP .TP
\fB\-t\fR type \fB\-t\fR type

View File

@ -18,9 +18,9 @@
ares_destroy_options \- Destroy options initialized with ares_save_options ares_destroy_options \- Destroy options initialized with ares_save_options
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B void ares_destroy_options(struct ares_options *\fIoptions\fP) void ares_destroy_options(struct ares_options *\fIoptions\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_destroy_options(3)\fP function destroys the options struct The \fBares_destroy_options(3)\fP function destroys the options struct

View File

@ -18,9 +18,9 @@
ares_dup \- Duplicate a resolver channel ares_dup \- Duplicate a resolver channel
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_dup(ares_channel *\fIdest\fP, ares_channel \fIsource\fP) int ares_dup(ares_channel *\fIdest\fP, ares_channel \fIsource\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_dup(3)\fP function duplicates an existing communications channel The \fBares_dup(3)\fP function duplicates an existing communications channel

View File

@ -18,11 +18,11 @@
ares_expand_name \- Expand a DNS-encoded domain name ares_expand_name \- Expand a DNS-encoded domain name
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_expand_name(const unsigned char *\fIencoded\fP, int ares_expand_name(const unsigned char *\fIencoded\fP,
.B const unsigned char *\fIabuf\fP, int \fIalen\fP, char **\fIs\fP, const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B long *\fIenclen\fP) char **\fIs\fP, long *\fIenclen\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,11 +18,11 @@
ares_expand_string \- Expand a length encoded string ares_expand_string \- Expand a length encoded string
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_expand_string(const unsigned char *\fIencoded\fP, int ares_expand_string(const unsigned char *\fIencoded\fP,
.B const unsigned char *\fIabuf\fP, int \fIalen\fP, unsigned char **\fIs\fP, const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B long *\fIenclen\fP) unsigned char **\fIs\fP, long *\fIenclen\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -19,11 +19,9 @@
ares_free_data \- Free data allocated by several c-ares functions ares_free_data \- Free data allocated by several c-ares functions
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B void ares_free_data(void *\fIdataptr\fP) void ares_free_data(void *\fIdataptr\fP)
.PP
.B cc file.c -lcares
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP

View File

@ -18,9 +18,9 @@
ares_free_hostent \- Free host structure allocated by ares functions ares_free_hostent \- Free host structure allocated by ares functions
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B void ares_free_hostent(struct hostent *\fIhost\fP) void ares_free_hostent(struct hostent *\fIhost\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,9 +18,9 @@
ares_free_string \- Free strings allocated by ares functions ares_free_string \- Free strings allocated by ares functions
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B void ares_free_string(void *\fIstr\fP) void ares_free_string(void *\fIstr\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fIares_free_string(3)\fP function frees a string allocated by an ares The \fIares_free_string(3)\fP function frees a string allocated by an ares

View File

@ -19,10 +19,13 @@
ares_get_servers, ares_get_servers_ports \- Retrieve name servers from an initialized ares_channel ares_get_servers, ares_get_servers_ports \- Retrieve name servers from an initialized ares_channel
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_get_servers(ares_channel \fIchannel\fP, struct ares_addr_node **\fIservers\fP) int ares_get_servers(ares_channel \fIchannel\fP,
.B int ares_get_servers_ports(ares_channel \fIchannel\fP, struct ares_addr_port_node **\fIservers\fP) struct ares_addr_node **\fIservers\fP)
int ares_get_servers_ports(ares_channel \fIchannel\fP,
struct ares_addr_port_node **\fIservers\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_get_servers(3)\fP function retrieves name servers configuration The \fBares_get_servers(3)\fP function retrieves name servers configuration

View File

@ -18,14 +18,16 @@
ares_getaddrinfo \- Initiate a host query by name and service ares_getaddrinfo \- Initiate a host query by name and service
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef void (*ares_addrinfo_callback)(void *\fIarg\fP, int \fIstatus\fP, typedef void (*ares_addrinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, struct ares_addrinfo *\fIresult\fP) int \fItimeouts\fP,
.PP struct ares_addrinfo *\fIresult\fP)
.B void ares_getaddrinfo(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B const char* \fIservice\fP, const struct ares_addrinfo_hints *\fIhints\fP, void ares_getaddrinfo(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B ares_addrinfo_callback \fIcallback\fP, void *\fIarg\fP) const char* \fIservice\fP,
const struct ares_addrinfo_hints *\fIhints\fP,
ares_addrinfo_callback \fIcallback\fP, void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,14 +18,15 @@
ares_gethostbyaddr \- Initiate a host query by address ares_gethostbyaddr \- Initiate a host query by address
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP, typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, struct hostent *\fIhostent\fP) int \fItimeouts\fP,
.PP struct hostent *\fIhostent\fP)
.B void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP,
.B int \fIaddrlen\fP, int \fIfamily\fP, ares_host_callback \fIcallback\fP, void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP,
.B void *\fIarg\fP) int \fIaddrlen\fP, int \fIfamily\fP,
ares_host_callback \fIcallback\fP, void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,13 +18,15 @@
ares_gethostbyname \- Initiate a host query by name ares_gethostbyname \- Initiate a host query by name
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP, typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, struct hostent *\fIhostent\fP) int \fItimeouts\fP,
.PP struct hostent *\fIhostent\fP)
.B void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIfamily\fP, ares_host_callback \fIcallback\fP, void *\fIarg\fP) void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP,
int \fIfamily\fP, ares_host_callback \fIcallback\fP,
void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_gethostbyname_file \- Lookup a name in the system's hosts file ares_gethostbyname_file \- Lookup a name in the system's hosts file
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_gethostbyname_file(ares_channel \fIchannel\fP, const char *\fIname\fP, int ares_gethostbyname_file(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIfamily\fP, struct hostent **host) int \fIfamily\fP, struct hostent **host)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,14 +18,15 @@
ares_getnameinfo \- Address-to-nodename translation in protocol-independent manner ares_getnameinfo \- Address-to-nodename translation in protocol-independent manner
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP, typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, char *\fInode\fP, char *\fIservice\fP) int \fItimeouts\fP, char *\fInode\fP,
.PP char *\fIservice\fP)
.B void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP,
.B ares_socklen_t \fIsalen\fP, int \fIflags\fP, ares_nameinfo_callback \fIcallback\fP, void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP,
.B void *\fIarg\fP) ares_socklen_t \fIsalen\fP, int \fIflags\fP,
ares_nameinfo_callback \fIcallback\fP, void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_getsock \- get socket descriptors to wait on ares_getsock \- get socket descriptors to wait on
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_getsock(ares_channel \fIchannel\fP, ares_socket_t *\fIsocks\fP, int ares_getsock(ares_channel \fIchannel\fP, ares_socket_t *\fIsocks\fP,
.B int \fInumsocks\fP); int \fInumsocks\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_inet_ntop \- convert a network format address to presentation format ares_inet_ntop \- convert a network format address to presentation format
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B const char * const char *ares_inet_ntop(int \fIaf\fP, const void *\fIsrc\fP, char *\fIdst\fP,
.B ares_inet_ntop(int af, const void *src, char *dst, ares_socklen_t size); ares_socklen_t \fIsize\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
This is a portable version with the identical functionality of the commonly This is a portable version with the identical functionality of the commonly

View File

@ -18,9 +18,9 @@
ares_inet_pton \- convert an IPv4 or IPv6 address from text to binary form ares_inet_pton \- convert an IPv4 or IPv6 address from text to binary form
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B const char *ares_inet_pton(int af, const char *src, void *dst); const char *ares_inet_pton(int \fIaf\fP, const char *\fIsrc\fP, void *\fIdst\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
This is a portable version with the identical functionality of the commonly This is a portable version with the identical functionality of the commonly

View File

@ -41,6 +41,7 @@ struct ares_options {
int nsort; int nsort;
int ednspsz; int ednspsz;
char *resolvconf_path; char *resolvconf_path;
char *hosts_path;
}; };
int ares_init_options(ares_channel *\fIchannelptr\fP, int ares_init_options(ares_channel *\fIchannelptr\fP,
@ -101,16 +102,14 @@ resolv.conf or the RES_OPTIONS environment variable.
.B ARES_OPT_UDP_PORT .B ARES_OPT_UDP_PORT
.B unsigned short \fIudp_port\fP; .B unsigned short \fIudp_port\fP;
.br .br
The port to use for queries over UDP, in network byte order. The port to use for queries over UDP, in host byte order.
The default value is 53 (in network byte order), the standard name The default value is 53, the standard name service port.
service port.
.TP 18 .TP 18
.B ARES_OPT_TCP_PORT .B ARES_OPT_TCP_PORT
.B unsigned short \fItcp_port\fP; .B unsigned short \fItcp_port\fP;
.br .br
The port to use for queries over TCP, in network byte order. The port to use for queries over TCP, in host byte order.
The default value is 53 (in network byte order), the standard name The default value is 53, the standard name service port.
service port.
.TP 18 .TP 18
.B ARES_OPT_SERVERS .B ARES_OPT_SERVERS
.B struct in_addr *\fIservers\fP; .B struct in_addr *\fIservers\fP;
@ -195,6 +194,16 @@ should be set to a path string, and will be honoured on *nix like systems. The
default is default is
.B /etc/resolv.conf .B /etc/resolv.conf
.br .br
.TP 18
.B ARES_OPT_HOSTS_FILE
.B char *\fIhosts_path\fP;
.br
The path to use for reading the hosts file. The
.I hosts_path
should be set to a path string, and will be honoured on *nix like systems. The
default is
.B /etc/hosts
.br
.PP .PP
The \fIoptmask\fP parameter also includes options without a corresponding The \fIoptmask\fP parameter also includes options without a corresponding
field in the field in the

View File

@ -79,7 +79,8 @@ DllMain function. Doing so will produce deadlocks and other problems.
Initialize everything possible. This sets all known bits. Initialize everything possible. This sets all known bits.
.TP .TP
.B ARES_LIB_INIT_WIN32 .B ARES_LIB_INIT_WIN32
Initialize Win32/64 specific libraries. Initialize Win32/64 specific libraries. As of c-ares 1.19.0, this is ignored
as there are no currently dynamically loaded libraries.
.TP .TP
.B ARES_LIB_INIT_NONE .B ARES_LIB_INIT_NONE
Initialize nothing extra. This sets no bit. Initialize nothing extra. This sets no bit.

View File

@ -18,11 +18,11 @@
ares_mkquery \- Compose a single-question DNS query buffer ares_mkquery \- Compose a single-question DNS query buffer
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_mkquery(const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP, int ares_mkquery(const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP,
.B unsigned short \fIid\fP, int \fIrd\fP, unsigned char **\fIbuf\fP, unsigned short \fIid\fP, int \fIrd\fP, unsigned char **\fIbuf\fP,
.B int *\fIbuflen\fP) int *\fIbuflen\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
Deprecated function. See \fIares_create_query(3)\fP instead! Deprecated function. See \fIares_create_query(3)\fP instead!

View File

@ -18,11 +18,11 @@
ares_parse_a_reply \- Parse a reply to a DNS query of type A ares_parse_a_reply \- Parse a reply to a DNS query of type A
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_a_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, int ares_parse_a_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B struct hostent **\fIhost\fP, struct hostent **\fIhost\fP,
.B struct ares_addrttl *\fIaddrttls\fP, int *\fInaddrttls\fP); struct ares_addrttl *\fIaddrttls\fP, int *\fInaddrttls\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,11 +18,11 @@
ares_parse_aaaa_reply \- Parse a reply to a DNS query of type AAAA ares_parse_aaaa_reply \- Parse a reply to a DNS query of type AAAA
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_aaaa_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, int ares_parse_aaaa_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B struct hostent **\fIhost\fP, struct hostent **\fIhost\fP,
.B struct ares_addr6ttl *\fIaddrttls\fP, int *\fInaddrttls\fP); struct ares_addr6ttl *\fIaddrttls\fP, int *\fInaddrttls\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -17,11 +17,10 @@
.SH NAME .SH NAME
ares_parse_mx_reply \- Parse a reply to a DNS query of type MX ares_parse_mx_reply \- Parse a reply to a DNS query of type MX
.SH SYNOPSIS .SH SYNOPSIS
.nf #include <ares.h>
.B #include <ares.h>
.PP int ares_parse_mx_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B int ares_parse_mx_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP, struct ares_mx_reply** \fImx_out\fP);
.B struct ares_mx_reply** \fImx_out\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_parse_naptr_reply \- Parse a reply to a DNS query of type NAPTR ares_parse_naptr_reply \- Parse a reply to a DNS query of type NAPTR
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_naptr_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP, int ares_parse_naptr_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_naptr_reply** \fInaptr_out\fP); struct ares_naptr_reply** \fInaptr_out\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_parse_ns_reply \- Parse a reply to a DNS query of type NS into a hostent ares_parse_ns_reply \- Parse a reply to a DNS query of type NS into a hostent
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_ns_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, int ares_parse_ns_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B struct hostent **\fIhost\fP); struct hostent **\fIhost\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,11 +18,11 @@
ares_parse_ptr_reply \- Parse a reply to a DNS query of type PTR into a hostent ares_parse_ptr_reply \- Parse a reply to a DNS query of type PTR into a hostent
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_ptr_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, int ares_parse_ptr_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B const void *\fIaddr\fP, int \fIaddrlen\fP, int \fIfamily\fP, const void *\fIaddr\fP, int \fIaddrlen\fP,
.B struct hostent **\fIhost\fP); int \fIfamily\fP, struct hostent **\fIhost\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_parse_soa_reply \- Parse a reply to a DNS query of type SOA ares_parse_soa_reply \- Parse a reply to a DNS query of type SOA
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_soa_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP, int ares_parse_soa_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_soa_reply** \fIsoa_out\fP); struct ares_soa_reply** \fIsoa_out\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_parse_srv_reply \- Parse a reply to a DNS query of type SRV ares_parse_srv_reply \- Parse a reply to a DNS query of type SRV
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_srv_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP, int ares_parse_srv_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_srv_reply** \fIsrv_out\fP); struct ares_srv_reply** \fIsrv_out\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,13 +18,13 @@
ares_parse_txt_reply \- Parse a reply to a DNS query of type TXT ares_parse_txt_reply \- Parse a reply to a DNS query of type TXT
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_txt_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP, int ares_parse_txt_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_txt_reply **\fItxt_out\fP); struct ares_txt_reply **\fItxt_out\fP);
.PP
.B int ares_parse_txt_reply_ext(const unsigned char* \fIabuf\fP, int \fIalen\fP, int ares_parse_txt_reply_ext(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_txt_ext **\fItxt_out\fP); struct ares_txt_ext **\fItxt_out\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,10 +18,10 @@
ares_parse_uri_reply \- Parse a reply to a DNS query of type URI ares_parse_uri_reply \- Parse a reply to a DNS query of type URI
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_parse_uri_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP, int ares_parse_uri_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_uri_reply** \fIuri_out\fP); struct ares_uri_reply** \fIuri_out\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -44,7 +44,7 @@ if they complete successfully or fail.
\fBares_process_fd(3)\fP works the same way but acts and operates only on the \fBares_process_fd(3)\fP works the same way but acts and operates only on the
specific file descriptors (sockets) you pass in to the function. Use specific file descriptors (sockets) you pass in to the function. Use
ARES_SOCKET_BAD for "no action". This function is provided to allow users of ARES_SOCKET_BAD for "no action". This function is provided to allow users of
c-ares to void \fIselect(3)\fP in their applications and within c-ares. c-ares to avoid \fIselect(3)\fP in their applications and within c-ares.
To only process possible timeout conditions without a socket event occurring, To only process possible timeout conditions without a socket event occurring,
one may pass NULL as the values for both \fIread_fds\fP and \fIwrite_fds\fP for one may pass NULL as the values for both \fIread_fds\fP and \fIwrite_fds\fP for

View File

@ -18,14 +18,15 @@
ares_query \- Initiate a single-question DNS query ares_query \- Initiate a single-question DNS query
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP) int \fItimeouts\fP, unsigned char *\fIabuf\fP,
.PP int \fIalen\fP)
.B void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP, void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B void *\fIarg\fP) int \fIdnsclass\fP, int \fItype\fP,
ares_callback \fIcallback\fP, void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,9 +18,10 @@
ares_save_options \- Save configuration values obtained from initialized ares_channel ares_save_options \- Save configuration values obtained from initialized ares_channel
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_save_options(ares_channel \fIchannel\fP, struct ares_options *\fIoptions\fP, int *\fIoptmask\fP) int ares_save_options(ares_channel \fIchannel\fP,
struct ares_options *\fIoptions\fP, int *\fIoptmask\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_save_options(3)\fP function saves the channel data identified by The \fBares_save_options(3)\fP function saves the channel data identified by

View File

@ -18,14 +18,15 @@
ares_search \- Initiate a DNS query with domain search ares_search \- Initiate a DNS query with domain search
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP) int \fItimeouts\fP, unsigned char *\fIabuf\fP,
.PP int \fIalen\fP)
.B void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP, void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B void *\fIarg\fP) int \fIdnsclass\fP, int \fItype\fP,
ares_callback \fIcallback\fP, void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,13 +18,14 @@
ares_send \- Initiate a DNS query ares_send \- Initiate a DNS query
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP) int \fItimeouts\fP, unsigned char *\fIabuf\fP,
.PP int \fIalen\fP)
.B void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
.B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP) void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -18,9 +18,9 @@
ares_set_local_dev \- Bind to a specific network device when creating sockets. ares_set_local_dev \- Bind to a specific network device when creating sockets.
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B void ares_set_local_dev(ares_channel \fIchannel\fP, const char* \fIlocal_dev_name\fP) void ares_set_local_dev(ares_channel \fIchannel\fP, const char* \fIlocal_dev_name\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_set_local_dev\fP function causes all future sockets The \fBares_set_local_dev\fP function causes all future sockets

View File

@ -18,9 +18,9 @@
ares_set_local_ip4 \- Set local IPv4 address outgoing requests. ares_set_local_ip4 \- Set local IPv4 address outgoing requests.
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B void ares_set_local_ip4(ares_channel \fIchannel\fP, unsigned int \fIlocal_ip\fP) void ares_set_local_ip4(ares_channel \fIchannel\fP, unsigned int \fIlocal_ip\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_set_local_ip4\fP function sets the IP address for outbound The \fBares_set_local_ip4\fP function sets the IP address for outbound

View File

@ -18,15 +18,15 @@
ares_set_local_ip6 \- Set local IPv6 address outgoing requests. ares_set_local_ip6 \- Set local IPv6 address outgoing requests.
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B void ares_set_local_ip6(ares_channel \fIchannel\fP, const unsigned char* \fIlocal_ip6\fP) void ares_set_local_ip6(ares_channel \fIchannel\fP, const unsigned char* \fIlocal_ip6\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_set_local_ip6\fP function sets the IPv6 address for outbound The \fBares_set_local_ip6\fP function sets the IPv6 address for outbound IPv6
IPv6 requests. The parameter \fIlocal_ip6\fP is specified in network byte requests. The parameter \fIlocal_ip6\fP is specified in network byte order.
order. This allows users to specify outbound interfaces when used on This allows users to specify outbound interfaces when used on multi-homed
multi-homed systems. The local_ip6 argument must be 16 bytes in length. systems. The \fIlocal_ip6\fP argument must be 16 bytes in length.
.SH SEE ALSO .SH SEE ALSO
.BR ares_set_local_ip4 (3) .BR ares_set_local_ip4 (3)
.SH NOTES .SH NOTES

View File

@ -18,10 +18,13 @@
ares_set_servers, ares_set_servers_ports \- Initialize an ares_channel name servers configuration ares_set_servers, ares_set_servers_ports \- Initialize an ares_channel name servers configuration
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_set_servers(ares_channel \fIchannel\fP, struct ares_addr_node *\fIservers\fP) int ares_set_servers(ares_channel \fIchannel\fP,
.B int ares_set_servers_ports(ares_channel \fIchannel\fP, struct ares_addr_port_node *\fIservers\fP) struct ares_addr_node *\fIservers\fP)
int ares_set_servers_ports(ares_channel \fIchannel\fP,
struct ares_addr_port_node *\fIservers\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_set_servers(3)\fP function initializes name servers configuration The \fBares_set_servers(3)\fP function initializes name servers configuration

View File

@ -18,10 +18,11 @@
ares_set_servers_csv, ares_set_servers_ports_csv \- Set list of DNS servers to be used. ares_set_servers_csv, ares_set_servers_ports_csv \- Set list of DNS servers to be used.
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_set_servers_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP) int ares_set_servers_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP)
.B int ares_set_servers_ports_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP)
int ares_set_servers_ports_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_set_servers_csv\fP and \fBares_set_servers_ports_csv\fPfunctions set The \fBares_set_servers_csv\fP and \fBares_set_servers_ports_csv\fPfunctions set

View File

@ -4,15 +4,15 @@
ares_set_socket_callback \- Set a socket creation callback ares_set_socket_callback \- Set a socket creation callback
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef int (*ares_sock_create_callback)(ares_socket_t \fIsocket_fd\fP, typedef int (*ares_sock_create_callback)(ares_socket_t \fIsocket_fd\fP,
int \fItype\fP, int \fItype\fP,
void *\fIuserdata\fP) void *\fIuserdata\fP)
.PP
.B void ares_set_socket_callback(ares_channel \fIchannel\fP, void ares_set_socket_callback(ares_channel \fIchannel\fP,
ares_sock_create_callback \fIcallback\fP, ares_sock_create_callback \fIcallback\fP,
void *\fIuserdata\fP) void *\fIuserdata\fP)
.PP .PP
.B cc file.c -lcares .B cc file.c -lcares
.fi .fi

View File

@ -4,17 +4,15 @@
ares_set_socket_configure_callback \- Set a socket configuration callback ares_set_socket_configure_callback \- Set a socket configuration callback
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B typedef int (*ares_sock_config_callback)(ares_socket_t \fIsocket_fd\fP, typedef int (*ares_sock_config_callback)(ares_socket_t \fIsocket_fd\fP,
int \fItype\fP, int \fItype\fP,
void *\fIuserdata\fP) void *\fIuserdata\fP)
.PP
.B void ares_set_socket_configure_callback(ares_channel \fIchannel\fP, void ares_set_socket_configure_callback(ares_channel \fIchannel\fP,
ares_sock_config_callback \fIcallback\fP, ares_sock_config_callback \fIcallback\fP,
void *\fIuserdata\fP) void *\fIuserdata\fP)
.PP
.B cc file.c -lcares
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP

View File

@ -4,21 +4,20 @@
ares_set_socket_functions \- Set socket io callbacks ares_set_socket_functions \- Set socket io callbacks
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B struct ares_socket_functions {
ares_socket_t(*\fIasocket\fP)(int, int, int, void *);
int(*\fIaclose\fP)(ares_socket_t, void *);
int(*\fIaconnect\fP)(ares_socket_t, const struct sockaddr *, ares_socklen_t, void *);
ares_ssize_t(*\fIarecvfrom\fP)(ares_socket_t, void *, size_t, int, struct sockaddr *, ares_socklen_t *, void *);
ares_ssize_t(*\fIasendv\fP)(ares_socket_t, const struct iovec *, int, void *);
};
.PP struct ares_socket_functions {
.B void ares_set_socket_functions(ares_channel \fIchannel\fP, ares_socket_t (*\fIasocket\fP)(int, int, int, void *);
const struct ares_socket_functions * \fIfunctions\fP, int (*\fIaclose\fP)(ares_socket_t, void *);
void *\fIuser_data\fP); int (*\fIaconnect\fP)(ares_socket_t, const struct sockaddr *, ares_socklen_t, void *);
ares_ssize_t (*\fIarecvfrom\fP)(ares_socket_t, void *, size_t, int,
struct sockaddr *, ares_socklen_t *, void *);
ares_ssize_t (*\fIasendv\fP)(ares_socket_t, const struct iovec *, int, void *);
};
void ares_set_socket_functions(ares_channel \fIchannel\fP,
const struct ares_socket_functions * \fIfunctions\fP,
void *\fIuser_data\fP);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP

View File

@ -16,9 +16,9 @@
ares_set_sortlist \- Initialize an ares_channel sortlist configuration ares_set_sortlist \- Initialize an ares_channel sortlist configuration
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B int ares_set_sortlist(ares_channel \fIchannel\fP, const char *\fIsortstr\fP) int ares_set_sortlist(ares_channel \fIchannel\fP, const char *\fIsortstr\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The \fBares_set_sortlist(3)\fP function initializes an address sortlist configuration The \fBares_set_sortlist(3)\fP function initializes an address sortlist configuration

View File

@ -18,9 +18,9 @@
ares_strerror \- Get the description of an ares library error code ares_strerror \- Get the description of an ares library error code
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B #include <ares.h> #include <ares.h>
.PP
.B const char *ares_strerror(int \fIcode\fP) const char *ares_strerror(int \fIcode\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@ -63,6 +63,13 @@
# include <windows.h> # include <windows.h>
# include <winsock2.h> # include <winsock2.h>
# include <ws2tcpip.h> # include <ws2tcpip.h>
/* To aid with linking against a static c-ares build, lets tell the microsoft
* compiler to pull in needed dependencies */
# ifdef _MSC_VER
# pragma comment(lib, "ws2_32")
# pragma comment(lib, "advapi32")
# pragma comment(lib, "iphlpapi")
# endif
#else #else
# include <sys/socket.h> # include <sys/socket.h>
# include <netinet/in.h> # include <netinet/in.h>
@ -168,6 +175,7 @@ extern "C" {
#define ARES_OPT_EDNSPSZ (1 << 15) #define ARES_OPT_EDNSPSZ (1 << 15)
#define ARES_OPT_NOROTATE (1 << 16) #define ARES_OPT_NOROTATE (1 << 16)
#define ARES_OPT_RESOLVCONF (1 << 17) #define ARES_OPT_RESOLVCONF (1 << 17)
#define ARES_OPT_HOSTS_FILE (1 << 18)
/* Nameinfo flag values */ /* Nameinfo flag values */
#define ARES_NI_NOFQDN (1 << 0) #define ARES_NI_NOFQDN (1 << 0)
@ -277,6 +285,7 @@ struct ares_options {
int nsort; int nsort;
int ednspsz; int ednspsz;
char *resolvconf_path; char *resolvconf_path;
char *hosts_path;
}; };
struct hostent; struct hostent;

View File

@ -6,12 +6,12 @@
#define ARES_COPYRIGHT "2004 - 2021 Daniel Stenberg, <daniel@haxx.se>." #define ARES_COPYRIGHT "2004 - 2021 Daniel Stenberg, <daniel@haxx.se>."
#define ARES_VERSION_MAJOR 1 #define ARES_VERSION_MAJOR 1
#define ARES_VERSION_MINOR 18 #define ARES_VERSION_MINOR 19
#define ARES_VERSION_PATCH 1 #define ARES_VERSION_PATCH 0
#define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\ #define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\
(ARES_VERSION_MINOR<<8)|\ (ARES_VERSION_MINOR<<8)|\
(ARES_VERSION_PATCH)) (ARES_VERSION_PATCH))
#define ARES_VERSION_STR "1.18.1" #define ARES_VERSION_STR "1.19.0"
#if (ARES_VERSION >= 0x010700) #if (ARES_VERSION >= 0x010700)
# define CARES_HAVE_ARES_LIBRARY_INIT 1 # define CARES_HAVE_ARES_LIBRARY_INIT 1

View File

@ -10,6 +10,11 @@ CONFIGURE_FILE (ares_config.h.cmake ${PROJECT_BINARY_DIR}/ares_config.h)
IF (CARES_SHARED) IF (CARES_SHARED)
ADD_LIBRARY (${PROJECT_NAME} SHARED ${CSOURCES}) ADD_LIBRARY (${PROJECT_NAME} SHARED ${CSOURCES})
# Include resource file in windows builds for versioned DLLs
IF (WIN32)
TARGET_SOURCES (${PROJECT_NAME} PRIVATE cares.rc)
ENDIF()
# Convert CARES_LIB_VERSIONINFO libtool version format into VERSION and SOVERSION # Convert CARES_LIB_VERSIONINFO libtool version format into VERSION and SOVERSION
# Convert from ":" separated into CMake list format using ";" # Convert from ":" separated into CMake list format using ";"
STRING (REPLACE ":" ";" CARES_LIB_VERSIONINFO ${CARES_LIB_VERSIONINFO}) STRING (REPLACE ":" ";" CARES_LIB_VERSIONINFO ${CARES_LIB_VERSIONINFO})

View File

@ -65,7 +65,6 @@ HHEADERS = ares_android.h \
ares_inet_net_pton.h \ ares_inet_net_pton.h \
ares_iphlpapi.h \ ares_iphlpapi.h \
ares_ipv6.h \ ares_ipv6.h \
ares_library_init.h \
ares_llist.h \ ares_llist.h \
ares_nowarn.h \ ares_nowarn.h \
ares_platform.h \ ares_platform.h \

View File

@ -1,3 +1,6 @@
#ifndef __ARES_DATA_H
#define __ARES_DATA_H
/* Copyright (C) 2009-2013 by Daniel Stenberg /* Copyright (C) 2009-2013 by Daniel Stenberg
* *
@ -74,3 +77,5 @@ struct ares_data {
void *ares_malloc_data(ares_datatype type); void *ares_malloc_data(ares_datatype type);
#endif // __ARES_DATA_H

View File

@ -38,6 +38,8 @@ void ares_destroy_options(struct ares_options *options)
ares_free(options->lookups); ares_free(options->lookups);
if(options->resolvconf_path) if(options->resolvconf_path)
ares_free(options->resolvconf_path); ares_free(options->resolvconf_path);
if(options->hosts_path)
ares_free(options->hosts_path);
} }
void ares_destroy(ares_channel channel) void ares_destroy(ares_channel channel)
@ -90,6 +92,9 @@ void ares_destroy(ares_channel channel)
if (channel->resolvconf_path) if (channel->resolvconf_path)
ares_free(channel->resolvconf_path); ares_free(channel->resolvconf_path);
if (channel->hosts_path)
ares_free(channel->hosts_path);
ares_free(channel); ares_free(channel);
} }

View File

@ -64,6 +64,8 @@ static int ares__isprint(int ch)
* - underscores which are used in SRV records. * - underscores which are used in SRV records.
* - Forward slashes such as are used for classless in-addr.arpa * - Forward slashes such as are used for classless in-addr.arpa
* delegation (CNAMEs) * delegation (CNAMEs)
* - Asterisks may be used for wildcard domains in CNAMEs as seen in the
* real world.
* While RFC 2181 section 11 does state not to do validation, * While RFC 2181 section 11 does state not to do validation,
* that applies to servers, not clients. Vulnerabilities have been * that applies to servers, not clients. Vulnerabilities have been
* reported when this validation is not performed. Security is more * reported when this validation is not performed. Security is more
@ -71,7 +73,7 @@ static int ares__isprint(int ch)
* anyhow). */ * anyhow). */
static int is_hostnamech(int ch) static int is_hostnamech(int ch)
{ {
/* [A-Za-z0-9-._/] /* [A-Za-z0-9-*._/]
* Don't use isalnum() as it is locale-specific * Don't use isalnum() as it is locale-specific
*/ */
if (ch >= 'A' && ch <= 'Z') if (ch >= 'A' && ch <= 'Z')
@ -80,7 +82,7 @@ static int is_hostnamech(int ch)
return 1; return 1;
if (ch >= '0' && ch <= '9') if (ch >= '0' && ch <= '9')
return 1; return 1;
if (ch == '-' || ch == '.' || ch == '_' || ch == '/') if (ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '*')
return 1; return 1;
return 0; return 0;

View File

@ -326,7 +326,7 @@ static int fake_addrinfo(const char *name,
} }
} }
if (family == AF_INET6 || family == AF_UNSPEC) if (!result && (family == AF_INET6 || family == AF_UNSPEC))
{ {
struct ares_in6_addr addr6; struct ares_in6_addr addr6;
result = ares_inet_pton(AF_INET6, name, &addr6) < 1 ? 0 : 1; result = ares_inet_pton(AF_INET6, name, &addr6) < 1 ? 0 : 1;
@ -404,16 +404,46 @@ static void end_hquery(struct host_query *hquery, int status)
ares_free(hquery); ares_free(hquery);
} }
static int is_localhost(const char *name)
{
/* RFC6761 6.3 says : The domain "localhost." and any names falling within ".localhost." */
size_t len;
if (name == NULL)
return 0;
if (strcmp(name, "localhost") == 0)
return 1;
len = strlen(name);
if (len < 10 /* strlen(".localhost") */)
return 0;
if (strcmp(name + (len - 10 /* strlen(".localhost") */), ".localhost") == 0)
return 1;
return 0;
}
static int file_lookup(struct host_query *hquery) static int file_lookup(struct host_query *hquery)
{ {
FILE *fp; FILE *fp;
int error; int error;
int status; int status;
const char *path_hosts = NULL; char *path_hosts = NULL;
if (hquery->hints.ai_flags & ARES_AI_ENVHOSTS) if (hquery->hints.ai_flags & ARES_AI_ENVHOSTS)
{ {
path_hosts = getenv("CARES_HOSTS"); path_hosts = ares_strdup(getenv("CARES_HOSTS"));
if (!path_hosts)
return ARES_ENOMEM;
}
if (hquery->channel->hosts_path)
{
path_hosts = ares_strdup(hquery->channel->hosts_path);
if (!path_hosts)
return ARES_ENOMEM;
} }
if (!path_hosts) if (!path_hosts)
@ -447,15 +477,15 @@ static int file_lookup(struct host_query *hquery)
return ARES_ENOTFOUND; return ARES_ENOTFOUND;
strcat(PATH_HOSTS, WIN_PATH_HOSTS); strcat(PATH_HOSTS, WIN_PATH_HOSTS);
path_hosts = PATH_HOSTS;
#elif defined(WATT32) #elif defined(WATT32)
const char *PATH_HOSTS = _w32_GetHostsFile(); const char *PATH_HOSTS = _w32_GetHostsFile();
if (!PATH_HOSTS) if (!PATH_HOSTS)
return ARES_ENOTFOUND; return ARES_ENOTFOUND;
#endif #endif
path_hosts = PATH_HOSTS; path_hosts = ares_strdup(PATH_HOSTS);
if (!path_hosts)
return ARES_ENOMEM;
} }
fp = fopen(path_hosts, "r"); fp = fopen(path_hosts, "r");
@ -466,21 +496,29 @@ static int file_lookup(struct host_query *hquery)
{ {
case ENOENT: case ENOENT:
case ESRCH: case ESRCH:
return ARES_ENOTFOUND; status = ARES_ENOTFOUND;
break;
default: default:
DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error,
strerror(error))); strerror(error)));
DEBUGF(fprintf(stderr, "Error opening file: %s\n", path_hosts)); DEBUGF(fprintf(stderr, "Error opening file: %s\n", path_hosts));
return ARES_EFILE; status = ARES_EFILE;
break;
} }
} }
status = ares__readaddrinfo(fp, hquery->name, hquery->port, &hquery->hints, hquery->ai); else
fclose(fp); {
status = ares__readaddrinfo(fp, hquery->name, hquery->port, &hquery->hints, hquery->ai);
fclose(fp);
}
ares_free(path_hosts);
/* RFC6761 section 6.3 #3 states that "Name resolution APIs and libraries /* RFC6761 section 6.3 #3 states that "Name resolution APIs and libraries
* SHOULD recognize localhost names as special and SHOULD always return the * SHOULD recognize localhost names as special and SHOULD always return the
* IP loopback address for address queries" */ * IP loopback address for address queries".
if (status == ARES_ENOTFOUND && strcmp(hquery->name, "localhost") == 0) * We will also ignore ALL errors when trying to resolve localhost, such
* as permissions errors reading /etc/hosts or a malformed /etc/hosts */
if (status != ARES_SUCCESS && is_localhost(hquery->name))
{ {
return ares__addrinfo_localhost(hquery->name, hquery->port, return ares__addrinfo_localhost(hquery->name, hquery->port,
&hquery->hints, hquery->ai); &hquery->hints, hquery->ai);
@ -497,7 +535,7 @@ static void next_lookup(struct host_query *hquery, int status)
/* RFC6761 section 6.3 #3 says "Name resolution APIs SHOULD NOT send /* RFC6761 section 6.3 #3 says "Name resolution APIs SHOULD NOT send
* queries for localhost names to their configured caching DNS * queries for localhost names to their configured caching DNS
* server(s)." */ * server(s)." */
if (strcmp(hquery->name, "localhost") != 0) if (!is_localhost(hquery->name))
{ {
/* DNS lookup */ /* DNS lookup */
if (next_dns_lookup(hquery)) if (next_dns_lookup(hquery))
@ -543,7 +581,16 @@ static void host_callback(void *arg, int status, int timeouts,
if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA) if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA)
{ {
/* error in parsing result e.g. no memory */ /* error in parsing result e.g. no memory */
end_hquery(hquery, addinfostatus); if (addinfostatus == ARES_EBADRESP && hquery->ai->nodes)
{
/* We got a bad response from server, but at least one query
* ended with ARES_SUCCESS */
end_hquery(hquery, ARES_SUCCESS);
}
else
{
end_hquery(hquery, addinfostatus);
}
} }
else if (hquery->ai->nodes) else if (hquery->ai->nodes)
{ {

View File

@ -47,9 +47,12 @@
#include <resolv.h> #include <resolv.h>
#endif #endif
#if defined(USE_WINSOCK)
# include <iphlpapi.h>
#endif
#include "ares.h" #include "ares.h"
#include "ares_inet_net_pton.h" #include "ares_inet_net_pton.h"
#include "ares_library_init.h"
#include "ares_nowarn.h" #include "ares_nowarn.h"
#include "ares_platform.h" #include "ares_platform.h"
#include "ares_private.h" #include "ares_private.h"
@ -58,6 +61,18 @@
#undef WIN32 /* Redefined in MingW/MSVC headers */ #undef WIN32 /* Redefined in MingW/MSVC headers */
#endif #endif
/* Define RtlGenRandom = SystemFunction036. This is in advapi32.dll. There is
* no need to dynamically load this, other software used widely does not.
* http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
* https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
*/
#ifdef _WIN32
BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength);
# ifndef RtlGenRandom
# define RtlGenRandom(a,b) SystemFunction036(a,b)
# endif
#endif
static int init_by_options(ares_channel channel, static int init_by_options(ares_channel channel,
const struct ares_options *options, const struct ares_options *options,
int optmask); int optmask);
@ -149,6 +164,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
channel->sock_funcs = NULL; channel->sock_funcs = NULL;
channel->sock_func_cb_data = NULL; channel->sock_func_cb_data = NULL;
channel->resolvconf_path = NULL; channel->resolvconf_path = NULL;
channel->hosts_path = NULL;
channel->last_server = 0; channel->last_server = 0;
channel->last_timeout_processed = (time_t)now.tv_sec; channel->last_timeout_processed = (time_t)now.tv_sec;
@ -217,13 +233,15 @@ done:
if (channel->servers) if (channel->servers)
ares_free(channel->servers); ares_free(channel->servers);
if (channel->ndomains != -1) if (channel->ndomains != -1)
ares_strsplit_free(channel->domains, channel->ndomains); ares__strsplit_free(channel->domains, channel->ndomains);
if (channel->sortlist) if (channel->sortlist)
ares_free(channel->sortlist); ares_free(channel->sortlist);
if(channel->lookups) if(channel->lookups)
ares_free(channel->lookups); ares_free(channel->lookups);
if(channel->resolvconf_path) if(channel->resolvconf_path)
ares_free(channel->resolvconf_path); ares_free(channel->resolvconf_path);
if(channel->hosts_path)
ares_free(channel->hosts_path);
ares_free(channel); ares_free(channel);
return status; return status;
} }
@ -335,6 +353,9 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
if (channel->resolvconf_path) if (channel->resolvconf_path)
(*optmask) |= ARES_OPT_RESOLVCONF; (*optmask) |= ARES_OPT_RESOLVCONF;
if (channel->hosts_path)
(*optmask) |= ARES_OPT_HOSTS_FILE;
/* Copy easy stuff */ /* Copy easy stuff */
options->flags = channel->flags; options->flags = channel->flags;
@ -414,6 +435,13 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
return ARES_ENOMEM; return ARES_ENOMEM;
} }
/* copy path for hosts file */
if (channel->hosts_path) {
options->hosts_path = ares_strdup(channel->hosts_path);
if (!options->hosts_path)
return ARES_ENOMEM;
}
return ARES_SUCCESS; return ARES_SUCCESS;
} }
@ -530,6 +558,14 @@ static int init_by_options(ares_channel channel,
return ARES_ENOMEM; return ARES_ENOMEM;
} }
/* Set path for hosts file, if given. */
if ((optmask & ARES_OPT_HOSTS_FILE) && !channel->hosts_path)
{
channel->hosts_path = ares_strdup(options->hosts_path);
if (!channel->hosts_path && options->hosts_path)
return ARES_ENOMEM;
}
channel->optmask = optmask; channel->optmask = optmask;
return ARES_SUCCESS; return ARES_SUCCESS;
@ -608,227 +644,6 @@ static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
return 1; return 1;
} }
/*
* get_REG_SZ_9X()
*
* Functionally identical to get_REG_SZ()
*
* Supported on Windows 95, 98 and ME.
*/
static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
{
DWORD dataType = 0;
DWORD size = 0;
int res;
*outptr = NULL;
/* Find out size of string stored in registry */
res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, NULL, &size);
if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
return 0;
/* Allocate buffer of indicated size plus one given that string
might have been stored without null termination */
*outptr = ares_malloc(size+1);
if (!*outptr)
return 0;
/* Get the value for real */
res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType,
(unsigned char *)*outptr, &size);
if ((res != ERROR_SUCCESS) || (size == 1))
{
ares_free(*outptr);
*outptr = NULL;
return 0;
}
/* Null terminate buffer allways */
*(*outptr + size) = '\0';
return 1;
}
/*
* get_enum_REG_SZ()
*
* Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName'
* pointer to the name of the registry leaf key to be queried, parent key
* is enumerated searching in child keys for given leaf key name and its
* associated string value. When located, this returns a pointer in *outptr
* to a newly allocated memory area holding it as a null-terminated string.
*
* Returns 0 and nullifies *outptr upon inability to return a string value.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*
* Supported on Windows NT 3.5 and newer.
*/
static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName,
char **outptr)
{
char enumKeyName[256];
DWORD enumKeyNameBuffSize;
DWORD enumKeyIdx = 0;
HKEY hKeyEnum;
int gotString;
int res;
*outptr = NULL;
for(;;)
{
enumKeyNameBuffSize = sizeof(enumKeyName);
res = RegEnumKeyExA(hKeyParent, enumKeyIdx++, enumKeyName,
&enumKeyNameBuffSize, 0, NULL, NULL, NULL);
if (res != ERROR_SUCCESS)
break;
res = RegOpenKeyExA(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE,
&hKeyEnum);
if (res != ERROR_SUCCESS)
continue;
gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr);
RegCloseKey(hKeyEnum);
if (gotString)
break;
}
if (!*outptr)
return 0;
return 1;
}
/*
* get_DNS_Registry_9X()
*
* Functionally identical to get_DNS_Registry()
*
* Implementation supports Windows 95, 98 and ME.
*/
static int get_DNS_Registry_9X(char **outptr)
{
HKEY hKey_VxD_MStcp;
int gotString;
int res;
*outptr = NULL;
res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ,
&hKey_VxD_MStcp);
if (res != ERROR_SUCCESS)
return 0;
gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr);
RegCloseKey(hKey_VxD_MStcp);
if (!gotString || !*outptr)
return 0;
return 1;
}
/*
* get_DNS_Registry_NT()
*
* Functionally identical to get_DNS_Registry()
*
* Refs: Microsoft Knowledge Base articles KB120642 and KB314053.
*
* Implementation supports Windows NT 3.5 and newer.
*/
static int get_DNS_Registry_NT(char **outptr)
{
HKEY hKey_Interfaces = NULL;
HKEY hKey_Tcpip_Parameters;
int gotString;
int res;
*outptr = NULL;
res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
&hKey_Tcpip_Parameters);
if (res != ERROR_SUCCESS)
return 0;
/*
** Global DNS settings override adapter specific parameters when both
** are set. Additionally static DNS settings override DHCP-configured
** parameters when both are set.
*/
/* Global DNS static parameters */
gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr);
if (gotString)
goto done;
/* Global DNS DHCP-configured parameters */
gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr);
if (gotString)
goto done;
/* Try adapter specific parameters */
res = RegOpenKeyExA(hKey_Tcpip_Parameters, "Interfaces", 0,
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
&hKey_Interfaces);
if (res != ERROR_SUCCESS)
{
hKey_Interfaces = NULL;
goto done;
}
/* Adapter specific DNS static parameters */
gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr);
if (gotString)
goto done;
/* Adapter specific DNS DHCP-configured parameters */
gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr);
done:
if (hKey_Interfaces)
RegCloseKey(hKey_Interfaces);
RegCloseKey(hKey_Tcpip_Parameters);
if (!gotString || !*outptr)
return 0;
return 1;
}
/*
* get_DNS_Registry()
*
* Locates DNS info in the registry. When located, this returns a pointer
* in *outptr to a newly allocated memory area holding a null-terminated
* string with a space or comma seperated list of DNS IP addresses.
*
* Returns 0 and nullifies *outptr upon inability to return DNSes string.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*/
static int get_DNS_Registry(char **outptr)
{
win_platform platform;
int gotString = 0;
*outptr = NULL;
platform = ares__getplatform();
if (platform == WIN_NT)
gotString = get_DNS_Registry_NT(outptr);
else if (platform == WIN_9X)
gotString = get_DNS_Registry_9X(outptr);
if (!gotString)
return 0;
return 1;
}
static void commanjoin(char** dst, const char* const src, const size_t len) static void commanjoin(char** dst, const char* const src, const size_t len)
{ {
char *newbuf; char *newbuf;
@ -857,106 +672,6 @@ static void commajoin(char **dst, const char *src)
commanjoin(dst, src, strlen(src)); commanjoin(dst, src, strlen(src));
} }
/*
* get_DNS_NetworkParams()
*
* Locates DNS info using GetNetworkParams() function from the Internet
* Protocol Helper (IP Helper) API. When located, this returns a pointer
* in *outptr to a newly allocated memory area holding a null-terminated
* string with a space or comma seperated list of DNS IP addresses.
*
* Returns 0 and nullifies *outptr upon inability to return DNSes string.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*
* Implementation supports Windows 98 and newer.
*
* Note: Ancient PSDK required in order to build a W98 target.
*/
static int get_DNS_NetworkParams(char **outptr)
{
FIXED_INFO *fi, *newfi;
struct ares_addr namesrvr;
char *txtaddr;
IP_ADDR_STRING *ipAddr;
int res;
DWORD size = sizeof (*fi);
*outptr = NULL;
/* Verify run-time availability of GetNetworkParams() */
if (ares_fpGetNetworkParams == ZERO_NULL)
return 0;
fi = ares_malloc(size);
if (!fi)
return 0;
res = (*ares_fpGetNetworkParams) (fi, &size);
if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
goto done;
newfi = ares_realloc(fi, size);
if (!newfi)
goto done;
fi = newfi;
res = (*ares_fpGetNetworkParams) (fi, &size);
if (res != ERROR_SUCCESS)
goto done;
for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next)
{
txtaddr = &ipAddr->IpAddress.String[0];
/* Validate converting textual address to binary format. */
if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1)
{
if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) ||
(namesrvr.addrV4.S_un.S_addr == INADDR_NONE))
continue;
}
else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1)
{
if (memcmp(&namesrvr.addrV6, &ares_in6addr_any,
sizeof(namesrvr.addrV6)) == 0)
continue;
}
else
continue;
commajoin(outptr, txtaddr);
if (!*outptr)
break;
}
done:
if (fi)
ares_free(fi);
if (!*outptr)
return 0;
return 1;
}
static BOOL ares_IsWindowsVistaOrGreater(void)
{
OSVERSIONINFO vinfo;
memset(&vinfo, 0, sizeof(vinfo));
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996) /* warning C4996: 'GetVersionExW': was declared deprecated */
#endif
if (!GetVersionEx(&vinfo) || vinfo.dwMajorVersion < 6)
return FALSE;
return TRUE;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
/* A structure to hold the string form of IPv4 and IPv6 addresses so we can /* A structure to hold the string form of IPv4 and IPv6 addresses so we can
* sort them by a metric. * sort them by a metric.
@ -1033,21 +748,20 @@ static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
/* On this interface, get the best route to that destination. */ /* On this interface, get the best route to that destination. */
MIB_IPFORWARD_ROW2 row; MIB_IPFORWARD_ROW2 row;
SOCKADDR_INET ignored; SOCKADDR_INET ignored;
if(!ares_fpGetBestRoute2 || if(GetBestRoute2(/* The interface to use. The index is ignored since we are
ares_fpGetBestRoute2(/* The interface to use. The index is ignored since we are * passing a LUID.
* passing a LUID. */
*/ luid, 0,
luid, 0, /* No specific source address. */
/* No specific source address. */ NULL,
NULL, /* Our destination address. */
/* Our destination address. */ dest,
dest, /* No options. */
/* No options. */ 0,
0, /* The route row. */
/* The route row. */ &row,
&row, /* The best source address, which we don't need. */
/* The best source address, which we don't need. */ &ignored) != NO_ERROR
&ignored) != NO_ERROR
/* If the metric is "unused" (-1) or too large for us to add the two /* If the metric is "unused" (-1) or too large for us to add the two
* metrics, use the worst possible, thus sorting this last. * metrics, use the worst possible, thus sorting this last.
*/ */
@ -1067,7 +781,7 @@ static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
} }
/* /*
* get_DNS_AdaptersAddresses() * get_DNS_Windows()
* *
* Locates DNS info using GetAdaptersAddresses() function from the Internet * Locates DNS info using GetAdaptersAddresses() function from the Internet
* Protocol Helper (IP Helper) API. When located, this returns a pointer * Protocol Helper (IP Helper) API. When located, this returns a pointer
@ -1082,7 +796,7 @@ static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
*/ */
#define IPAA_INITIAL_BUF_SZ 15 * 1024 #define IPAA_INITIAL_BUF_SZ 15 * 1024
#define IPAA_MAX_TRIES 3 #define IPAA_MAX_TRIES 3
static int get_DNS_AdaptersAddresses(char **outptr) static int get_DNS_Windows(char **outptr)
{ {
IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr; IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry; IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry;
@ -1107,10 +821,6 @@ static int get_DNS_AdaptersAddresses(char **outptr)
*outptr = NULL; *outptr = NULL;
/* Verify run-time availability of GetAdaptersAddresses() */
if (ares_fpGetAdaptersAddresses == ZERO_NULL)
return 0;
ipaa = ares_malloc(Bufsz); ipaa = ares_malloc(Bufsz);
if (!ipaa) if (!ipaa)
return 0; return 0;
@ -1127,8 +837,7 @@ static int get_DNS_AdaptersAddresses(char **outptr)
} }
/* Usually this call suceeds with initial buffer size */ /* Usually this call suceeds with initial buffer size */
res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL, res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
ipaa, &ReqBufsz);
if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
goto done; goto done;
@ -1142,8 +851,7 @@ static int get_DNS_AdaptersAddresses(char **outptr)
Bufsz = ReqBufsz; Bufsz = ReqBufsz;
ipaa = newipaa; ipaa = newipaa;
} }
res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL, res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
ipaa, &ReqBufsz);
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
break; break;
} }
@ -1185,26 +893,17 @@ static int get_DNS_AdaptersAddresses(char **outptr)
addressesSize = newSize; addressesSize = newSize;
} }
/* Vista required for Luid or Ipv4Metric */ addresses[addressesIndex].metric =
if (ares_IsWindowsVistaOrGreater()) getBestRouteMetric(&ipaaEntry->Luid,
{ (SOCKADDR_INET*)(namesrvr.sa),
/* Save the address as the next element in addresses. */ ipaaEntry->Ipv4Metric);
addresses[addressesIndex].metric =
getBestRouteMetric(&ipaaEntry->Luid,
(SOCKADDR_INET*)(namesrvr.sa),
ipaaEntry->Ipv4Metric);
}
else
{
addresses[addressesIndex].metric = (ULONG)-1;
}
/* Record insertion index to make qsort stable */ /* Record insertion index to make qsort stable */
addresses[addressesIndex].orig_idx = addressesIndex; addresses[addressesIndex].orig_idx = addressesIndex;
if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr, if (!ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
addresses[addressesIndex].text, addresses[addressesIndex].text,
sizeof(addresses[0].text))) { sizeof(addresses[0].text))) {
continue; continue;
} }
++addressesIndex; ++addressesIndex;
@ -1227,26 +926,17 @@ static int get_DNS_AdaptersAddresses(char **outptr)
addressesSize = newSize; addressesSize = newSize;
} }
/* Vista required for Luid or Ipv4Metric */ addresses[addressesIndex].metric =
if (ares_IsWindowsVistaOrGreater()) getBestRouteMetric(&ipaaEntry->Luid,
{ (SOCKADDR_INET*)(namesrvr.sa),
/* Save the address as the next element in addresses. */ ipaaEntry->Ipv6Metric);
addresses[addressesIndex].metric =
getBestRouteMetric(&ipaaEntry->Luid,
(SOCKADDR_INET*)(namesrvr.sa),
ipaaEntry->Ipv6Metric);
}
else
{
addresses[addressesIndex].metric = (ULONG)-1;
}
/* Record insertion index to make qsort stable */ /* Record insertion index to make qsort stable */
addresses[addressesIndex].orig_idx = addressesIndex; addresses[addressesIndex].orig_idx = addressesIndex;
if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr, if (!ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr,
addresses[addressesIndex].text, addresses[addressesIndex].text,
sizeof(addresses[0].text))) { sizeof(addresses[0].text))) {
continue; continue;
} }
++addressesIndex; ++addressesIndex;
@ -1294,35 +984,6 @@ done:
return 1; return 1;
} }
/*
* get_DNS_Windows()
*
* Locates DNS info from Windows employing most suitable methods available at
* run-time no matter which Windows version it is. When located, this returns
* a pointer in *outptr to a newly allocated memory area holding a string with
* a space or comma seperated list of DNS IP addresses, null-terminated.
*
* Returns 0 and nullifies *outptr upon inability to return DNSes string.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*
* Implementation supports Windows 95 and newer.
*/
static int get_DNS_Windows(char **outptr)
{
/* Try using IP helper API GetAdaptersAddresses(). IPv4 + IPv6, also sorts
* DNS servers by interface route metrics to try to use the best DNS server. */
if (get_DNS_AdaptersAddresses(outptr))
return 1;
/* Try using IP helper API GetNetworkParams(). IPv4 only. */
if (get_DNS_NetworkParams(outptr))
return 1;
/* Fall-back to registry information */
return get_DNS_Registry(outptr);
}
/* /*
* get_SuffixList_Windows() * get_SuffixList_Windows()
* *
@ -1686,8 +1347,12 @@ static int init_by_resolv_conf(ares_channel channel)
channel->tries = res.retry; channel->tries = res.retry;
if (channel->rotate == -1) if (channel->rotate == -1)
channel->rotate = res.options & RES_ROTATE; channel->rotate = res.options & RES_ROTATE;
if (channel->timeout == -1) if (channel->timeout == -1) {
channel->timeout = res.retrans * 1000; channel->timeout = res.retrans * 1000;
#ifdef __APPLE__
channel->timeout /= (res.retry + 1) * (res.nscount > 0 ? res.nscount : 1);
#endif
}
res_ndestroy(&res); res_ndestroy(&res);
} }
@ -2021,6 +1686,11 @@ static int init_by_defaults(ares_channel channel)
ares_free(channel->resolvconf_path); ares_free(channel->resolvconf_path);
channel->resolvconf_path = NULL; channel->resolvconf_path = NULL;
} }
if(channel->hosts_path) {
ares_free(channel->hosts_path);
channel->hosts_path = NULL;
}
} }
if(hostname) if(hostname)
@ -2243,6 +1913,8 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
q = str; q = str;
while (*q && *q != '/' && *q != ';' && !ISSPACE(*q)) while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
q++; q++;
if (q-str >= 16)
return ARES_EBADSTR;
memcpy(ipbuf, str, q-str); memcpy(ipbuf, str, q-str);
ipbuf[q-str] = '\0'; ipbuf[q-str] = '\0';
/* Find the prefix */ /* Find the prefix */
@ -2251,6 +1923,8 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
const char *str2 = q+1; const char *str2 = q+1;
while (*q && *q != ';' && !ISSPACE(*q)) while (*q && *q != ';' && !ISSPACE(*q))
q++; q++;
if (q-str >= 32)
return ARES_EBADSTR;
memcpy(ipbufpfx, str, q-str); memcpy(ipbufpfx, str, q-str);
ipbufpfx[q-str] = '\0'; ipbufpfx[q-str] = '\0';
str = str2; str = str2;
@ -2325,12 +1999,12 @@ static int set_search(ares_channel channel, const char *str)
if(channel->ndomains != -1) { if(channel->ndomains != -1) {
/* LCOV_EXCL_START: all callers check ndomains == -1 */ /* LCOV_EXCL_START: all callers check ndomains == -1 */
/* if we already have some domains present, free them first */ /* if we already have some domains present, free them first */
ares_strsplit_free(channel->domains, channel->ndomains); ares__strsplit_free(channel->domains, channel->ndomains);
channel->domains = NULL; channel->domains = NULL;
channel->ndomains = -1; channel->ndomains = -1;
} /* LCOV_EXCL_STOP */ } /* LCOV_EXCL_STOP */
channel->domains = ares_strsplit(str, ", ", 1, &cnt); channel->domains = ares__strsplit(str, ", ", &cnt);
channel->ndomains = (int)cnt; channel->ndomains = (int)cnt;
if (channel->domains == NULL || channel->ndomains == 0) { if (channel->domains == NULL || channel->ndomains == 0) {
channel->domains = NULL; channel->domains = NULL;
@ -2495,12 +2169,10 @@ static int sortlist_alloc(struct apattern **sortlist, int *nsort,
return 1; return 1;
} }
/* initialize an rc4 key. If possible a cryptographically secure random key /* initialize an rc4 key. If possible a cryptographically secure random key
is generated using a suitable function (for example win32's RtlGenRandom as is generated using a suitable function otherwise the code defaults to
described in cross-platform albeit less secure mechanism using rand
http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
otherwise the code defaults to cross-platform albeit less secure mechanism
using rand
*/ */
static void randomize_key(unsigned char* key,int key_data_len) static void randomize_key(unsigned char* key,int key_data_len)
{ {
@ -2508,21 +2180,20 @@ static void randomize_key(unsigned char* key,int key_data_len)
int counter=0; int counter=0;
#ifdef WIN32 #ifdef WIN32
BOOLEAN res; BOOLEAN res;
if (ares_fpSystemFunction036)
{ res = RtlGenRandom(key, key_data_len);
res = (*ares_fpSystemFunction036) (key, key_data_len); if (res)
if (res) randomized = 1;
randomized = 1;
}
#else /* !WIN32 */ #else /* !WIN32 */
#ifdef CARES_RANDOM_FILE # ifdef CARES_RANDOM_FILE
FILE *f = fopen(CARES_RANDOM_FILE, "rb"); FILE *f = fopen(CARES_RANDOM_FILE, "rb");
if(f) { if(f) {
setvbuf(f, NULL, _IONBF, 0); setvbuf(f, NULL, _IONBF, 0);
counter = aresx_uztosi(fread(key, 1, key_data_len, f)); counter = aresx_uztosi(fread(key, 1, key_data_len, f));
fclose(f); fclose(f);
} }
#endif # endif
#endif /* WIN32 */ #endif /* WIN32 */
if (!randomized) { if (!randomized) {

View File

@ -18,18 +18,10 @@
#include "ares_setup.h" #include "ares_setup.h"
#include "ares.h" #include "ares.h"
#include "ares_library_init.h"
#include "ares_private.h" #include "ares_private.h"
/* library-private global and unique instance vars */ /* library-private global and unique instance vars */
#ifdef USE_WINSOCK
fpGetNetworkParams_t ares_fpGetNetworkParams = ZERO_NULL;
fpSystemFunction036_t ares_fpSystemFunction036 = ZERO_NULL;
fpGetAdaptersAddresses_t ares_fpGetAdaptersAddresses = ZERO_NULL;
fpGetBestRoute2_t ares_fpGetBestRoute2 = ZERO_NULL;
#endif
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
#include "ares_android.h" #include "ares_android.h"
#endif #endif
@ -59,81 +51,8 @@ void *(*ares_malloc)(size_t size) = default_malloc;
void *(*ares_realloc)(void *ptr, size_t size) = default_realloc; void *(*ares_realloc)(void *ptr, size_t size) = default_realloc;
void (*ares_free)(void *ptr) = default_free; void (*ares_free)(void *ptr) = default_free;
#ifdef USE_WINSOCK
static HMODULE hnd_iphlpapi;
static HMODULE hnd_advapi32;
#endif
static int ares_win32_init(void)
{
#ifdef USE_WINSOCK
hnd_iphlpapi = 0;
hnd_iphlpapi = LoadLibraryW(L"iphlpapi.dll");
if (!hnd_iphlpapi)
return ARES_ELOADIPHLPAPI;
ares_fpGetNetworkParams = (fpGetNetworkParams_t)
GetProcAddress(hnd_iphlpapi, "GetNetworkParams");
if (!ares_fpGetNetworkParams)
{
FreeLibrary(hnd_iphlpapi);
return ARES_EADDRGETNETWORKPARAMS;
}
ares_fpGetAdaptersAddresses = (fpGetAdaptersAddresses_t)
GetProcAddress(hnd_iphlpapi, "GetAdaptersAddresses");
if (!ares_fpGetAdaptersAddresses)
{
/* This can happen on clients before WinXP, I don't
think it should be an error, unless we don't want to
support Windows 2000 anymore */
}
ares_fpGetBestRoute2 = (fpGetBestRoute2_t)
GetProcAddress(hnd_iphlpapi, "GetBestRoute2");
if (!ares_fpGetBestRoute2)
{
/* This can happen on clients before Vista, I don't
think it should be an error, unless we don't want to
support Windows XP anymore */
}
/*
* When advapi32.dll is unavailable or advapi32.dll has no SystemFunction036,
* also known as RtlGenRandom, which is the case for Windows versions prior
* to WinXP then c-ares uses portable rand() function. Then don't error here.
*/
hnd_advapi32 = 0;
hnd_advapi32 = LoadLibraryW(L"advapi32.dll");
if (hnd_advapi32)
{
ares_fpSystemFunction036 = (fpSystemFunction036_t)
GetProcAddress(hnd_advapi32, "SystemFunction036");
}
#endif
return ARES_SUCCESS;
}
static void ares_win32_cleanup(void)
{
#ifdef USE_WINSOCK
if (hnd_advapi32)
FreeLibrary(hnd_advapi32);
if (hnd_iphlpapi)
FreeLibrary(hnd_iphlpapi);
#endif
}
int ares_library_init(int flags) int ares_library_init(int flags)
{ {
int res;
if (ares_initialized) if (ares_initialized)
{ {
ares_initialized++; ares_initialized++;
@ -141,12 +60,7 @@ int ares_library_init(int flags)
} }
ares_initialized++; ares_initialized++;
if (flags & ARES_LIB_INIT_WIN32) /* NOTE: ARES_LIB_INIT_WIN32 flag no longer used */
{
res = ares_win32_init();
if (res != ARES_SUCCESS)
return res; /* LCOV_EXCL_LINE: can't test Win32 init failure */
}
ares_init_flags = flags; ares_init_flags = flags;
@ -176,8 +90,7 @@ void ares_library_cleanup(void)
if (ares_initialized) if (ares_initialized)
return; return;
if (ares_init_flags & ARES_LIB_INIT_WIN32) /* NOTE: ARES_LIB_INIT_WIN32 flag no longer used */
ares_win32_cleanup();
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
ares_library_cleanup_android(); ares_library_cleanup_android();

View File

@ -1,43 +0,0 @@
#ifndef HEADER_CARES_LIBRARY_INIT_H
#define HEADER_CARES_LIBRARY_INIT_H
/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2004-2011 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#include "ares_setup.h"
#ifdef USE_WINSOCK
#include <iphlpapi.h>
#include "ares_iphlpapi.h"
typedef DWORD (WINAPI *fpGetNetworkParams_t) (FIXED_INFO*, DWORD*);
typedef BOOLEAN (APIENTRY *fpSystemFunction036_t) (void*, ULONG);
typedef ULONG (WINAPI *fpGetAdaptersAddresses_t) ( ULONG, ULONG, void*, IP_ADAPTER_ADDRESSES*, ULONG* );
typedef NETIO_STATUS (WINAPI *fpGetBestRoute2_t) ( NET_LUID *, NET_IFINDEX, const SOCKADDR_INET *, const SOCKADDR_INET *, ULONG, PMIB_IPFORWARD_ROW2, SOCKADDR_INET * );
/* Forward-declaration of variables defined in ares_library_init.c */
/* that are global and unique instances for whole c-ares library. */
extern fpGetNetworkParams_t ares_fpGetNetworkParams;
extern fpSystemFunction036_t ares_fpSystemFunction036;
extern fpGetAdaptersAddresses_t ares_fpGetAdaptersAddresses;
extern fpGetBestRoute2_t ares_fpGetBestRoute2;
#endif /* USE_WINSOCK */
#endif /* HEADER_CARES_LIBRARY_INIT_H */

View File

@ -339,6 +339,9 @@ struct ares_channeldata {
/* Path for resolv.conf file, configurable via ares_options */ /* Path for resolv.conf file, configurable via ares_options */
char *resolvconf_path; char *resolvconf_path;
/* Path for hosts file, configurable via ares_options */
char *hosts_path;
}; };
/* Does the domain end in ".onion" or ".onion."? Case-insensitive. */ /* Does the domain end in ".onion" or ".onion."? Case-insensitive. */

View File

@ -209,6 +209,17 @@ static void write_tcp_data(ares_channel channel,
ares_ssize_t scount; ares_ssize_t scount;
ares_ssize_t wcount; ares_ssize_t wcount;
size_t n; size_t n;
/* From writev manpage: An implementation can advertise its limit by defining
IOV_MAX in <limits.h> or at run time via the return value from
sysconf(_SC_IOV_MAX). On modern Linux systems, the limit is 1024. Back in
Linux 2.0 days, this limit was 16. */
#if defined(IOV_MAX)
const size_t maxn = IOV_MAX; /* FreeBSD */
#elif defined(_SC_IOV_MAX)
const size_t maxn = sysconf(_SC_IOV_MAX); /* Linux */
#else
const size_t maxn = 16; /* Safe default */
#endif
if(!write_fds && (write_fd == ARES_SOCKET_BAD)) if(!write_fds && (write_fd == ARES_SOCKET_BAD))
/* no possible action */ /* no possible action */
@ -256,6 +267,8 @@ static void write_tcp_data(ares_channel channel,
vec[n].iov_base = (char *) sendreq->data; vec[n].iov_base = (char *) sendreq->data;
vec[n].iov_len = sendreq->len; vec[n].iov_len = sendreq->len;
n++; n++;
if(n >= maxn)
break;
} }
wcount = socket_writev(channel, server->tcp_socket, vec, (int)n); wcount = socket_writev(channel, server->tcp_socket, vec, (int)n);
ares_free(vec); ares_free(vec);

View File

@ -22,47 +22,7 @@
#include "ares.h" #include "ares.h"
#include "ares_private.h" #include "ares_private.h"
static int list_contains(char * const *list, size_t num_elem, const char *str, int insensitive) void ares__strsplit_free(char **elms, size_t num_elm)
{
size_t len;
size_t i;
len = strlen(str);
for (i=0; i<num_elem; i++)
{
if (insensitive)
{
#ifdef WIN32
if (strnicmp(list[i], str, len) == 0)
#else
if (strncasecmp(list[i], str, len) == 0)
#endif
return 1;
}
else
{
if (strncmp(list[i], str, len) == 0)
return 1;
}
}
return 0;
}
static int is_delim(char c, const char *delims, size_t num_delims)
{
size_t i;
for (i=0; i<num_delims; i++)
{
if (c == delims[i])
return 1;
}
return 0;
}
void ares_strsplit_free(char **elms, size_t num_elm)
{ {
size_t i; size_t i;
@ -74,105 +34,67 @@ void ares_strsplit_free(char **elms, size_t num_elm)
ares_free(elms); ares_free(elms);
} }
char **ares__strsplit(const char *in, const char *delms, size_t *num_elm) {
char **ares_strsplit(const char *in, const char *delms, int make_set, size_t *num_elm) const char *p;
{ char **table;
char *parsestr; void *tmp;
char **temp; size_t i, j, k, count;
char **out;
size_t cnt;
size_t nelms;
size_t in_len;
size_t num_delims;
size_t i;
if (in == NULL || delms == NULL || num_elm == NULL) if (in == NULL || delms == NULL || num_elm == NULL)
return NULL; return NULL;
*num_elm = 0; *num_elm = 0;
in_len = strlen(in); /* count non-empty delimited substrings */
num_delims = strlen(delms); count = 0;
p = in;
do {
i = strcspn(p, delms);
if (i != 0) {
/* string is non-empty */
count++;
p += i;
}
} while(*p++ != 0);
/* Figure out how many elements. */ if (count == 0)
nelms = 1; return NULL;
for (i=0; i<in_len; i++) table = ares_malloc(count * sizeof(*table));
{ if (table == NULL)
if (is_delim(in[i], delms, num_delims)) return NULL;
{
nelms++; j = 0; /* current table entry */
/* re-calculate indices and allocate new strings for table */
for (p = in; j < count; p += i + 1) {
i = strcspn(p, delms);
if (i != 0) {
for (k = 0; k < j; k++) {
#ifdef WIN32
if (strnicmp(table[k], p, i) == 0 && table[k][i] == 0)
break;
#else
if (strncasecmp(table[k], p, i) == 0 && table[k][i] == 0)
break;
#endif
}
if (k == j) {
/* copy unique strings only */
table[j] = ares_malloc(i + 1);
if (table[j] == NULL) {
ares__strsplit_free(table, j);
return NULL;
}
strncpy(table[j], p, i);
table[j++][i] = 0;
} else
count--;
} }
} }
/* Copy of input so we can cut it up. */ tmp = ares_realloc(table, count * sizeof (*table));
parsestr = ares_strdup(in); if (tmp != NULL)
if (parsestr == NULL) table = tmp;
return NULL;
/* Temporary array to store locations of start of each element *num_elm = count;
* within parsestr. */ return table;
temp = ares_malloc(nelms * sizeof(*temp));
if (temp == NULL)
{
ares_free(parsestr);
return NULL;
}
temp[0] = parsestr;
cnt = 1;
for (i=0; i<in_len && cnt<nelms; i++)
{
if (!is_delim(parsestr[i], delms, num_delims))
continue;
/* Replace sep with NULL. */
parsestr[i] = '\0';
/* Add the pointer to the array of elements */
temp[cnt] = parsestr+i+1;
cnt++;
}
/* Copy each element to our output array. */
out = ares_malloc(nelms * sizeof(*out));
if (out == NULL)
{
ares_free(parsestr);
ares_free(temp);
return NULL;
}
nelms = 0;
for (i=0; i<cnt; i++)
{
if (temp[i][0] == '\0')
continue;
if (make_set && list_contains(out, nelms, temp[i], 1))
continue;
out[nelms] = ares_strdup(temp[i]);
if (out[nelms] == NULL)
{
ares_strsplit_free(out, nelms);
ares_free(parsestr);
ares_free(temp);
return NULL;
}
nelms++;
}
/* If there are no elements don't return an empty allocated
* array. */
if (nelms == 0)
{
ares_strsplit_free(out, nelms);
out = NULL;
}
/* Get the true number of elements (recalculated because of make_set) */
*num_elm = nelms;
ares_free(parsestr);
ares_free(temp);
return out;
} }

View File

@ -18,25 +18,24 @@
#include "ares_setup.h" #include "ares_setup.h"
/* Split a string on delem skipping empty elements. /* Split a string on delms skipping empty or duplicate elements.
* *
* param in String to split. * param in String to split.
* param delims String of characters to treat as a delimitor. * param delms String of characters to treat as a delimitor.
* Each character in the string is a delimitor so * Each character in the string is a delimitor so
* there can be multiple delimitors to split on. * there can be multiple delimitors to split on.
* E.g. ", " will split on all comma's and spaces. * E.g. ", " will split on all comma's and spaces.
* param make_set Have the list be a Set where there are no * Duplicate entries are removed.
* duplicate entries. 1 for true, 0 or false.
* param num_elm Return parameter of the number of elements * param num_elm Return parameter of the number of elements
* in the result array. * in the result array.
* *
* returns an allocated array of allocated string elements. * returns an allocated array of allocated string elements.
* *
*/ */
char **ares_strsplit(const char *in, const char *delms, int make_set, size_t *num_elm); char **ares__strsplit(const char *in, const char *delms, size_t *num_elm);
/* Frees the result returned from ares_strsplit(). */ /* Frees the result returned from ares__strsplit(). */
void ares_strsplit_free(char **elms, size_t num_elm); void ares__strsplit_free(char **elms, size_t num_elm);
#endif /* HEADER_CARES_STRSPLIT_H */ #endif /* HEADER_CARES_STRSPLIT_H */

View File

@ -1,3 +1,4 @@
// require C++17+
#ifndef SIMDSOFT__NTCVT_HPP #ifndef SIMDSOFT__NTCVT_HPP
#define SIMDSOFT__NTCVT_HPP #define SIMDSOFT__NTCVT_HPP
@ -40,7 +41,7 @@ public:
// std::string: use memset (usually implemented with SIMD) // std::string: use memset (usually implemented with SIMD)
// std::wstring: for loop (slow performance) // std::wstring: for loop (slow performance)
// only works on msvc currently // only works on msvc currently
_Elem* resize_nofill(size_t len) _Elem* resize_for_overwrite(size_t len)
{ {
this->reserve(len); this->reserve(len);
#if _MSC_VER >= 1920 // VS2019+ #if _MSC_VER >= 1920 // VS2019+
@ -62,7 +63,7 @@ auto prepare(_Cont& str, size_t size)
{ {
using _Elem = typename _Cont::value_type; using _Elem = typename _Cont::value_type;
intrusive_string<_Elem>& helper = (intrusive_string<_Elem>&)str; intrusive_string<_Elem>& helper = (intrusive_string<_Elem>&)str;
return helper.resize_nofill(size); return helper.resize_for_overwrite(size);
} }
#if defined(_AFX) #if defined(_AFX)
template <> inline template <> inline
@ -130,12 +131,12 @@ inline wchar_t* mcbs2wdup(const char* mcb, int len, int* wbuf_len, UINT cp = NTC
#if _HAS_CXX17 #if _HAS_CXX17
inline std::string from_chars(const std::wstring_view& wcb, UINT cp = NTCVT_CP_DEFAULT) inline std::string from_chars(const std::wstring_view& wcb, UINT cp = NTCVT_CP_DEFAULT)
{ {
return wcbs2a<std::string>(wcb.data(), wcb.length(), cp); return wcbs2a<std::string>(wcb.data(), static_cast<int>(wcb.length()), cp);
} }
inline std::wstring from_chars(const std::string_view& mcb, UINT cp = NTCVT_CP_DEFAULT) inline std::wstring from_chars(const std::string_view& mcb, UINT cp = NTCVT_CP_DEFAULT)
{ {
return mcbs2w<std::wstring>(mcb.data(), mcb.length(), cp); return mcbs2w<std::wstring>(mcb.data(), static_cast<int>(mcb.length()), cp);
} }
#else #else
inline std::string from_chars(const std::wstring& wcb, UINT cp = NTCVT_CP_DEFAULT) inline std::string from_chars(const std::wstring& wcb, UINT cp = NTCVT_CP_DEFAULT)
@ -170,7 +171,7 @@ namespace afx
# if _HAS_CXX17 # if _HAS_CXX17
inline CStringW from_chars(std::string_view mcb, UINT cp = NTCVT_CP_DEFAULT) inline CStringW from_chars(std::string_view mcb, UINT cp = NTCVT_CP_DEFAULT)
{ {
return mcbs2w<CStringW>(mcb.data(), mcb.length(), cp); return mcbs2w<CStringW>(mcb.data(), static_cast<int>(mcb.length()), cp);
} }
# else # else
inline CStringW from_chars(const char* str, UINT cp = NTCVT_CP_DEFAULT) inline CStringW from_chars(const char* str, UINT cp = NTCVT_CP_DEFAULT)
@ -179,7 +180,7 @@ inline CStringW from_chars(const char* str, UINT cp = NTCVT_CP_DEFAULT)
} }
inline CStringW from_chars(const std::string& mcb, UINT cp = NTCVT_CP_DEFAULT) inline CStringW from_chars(const std::string& mcb, UINT cp = NTCVT_CP_DEFAULT)
{ {
return mcbs2w<CStringW>(mcb.c_str(), mcb.length(), cp); return mcbs2w<CStringW>(mcb.c_str(), static_cast<int>(mcb.length()), cp);
} }
# endif # endif
} // namespace afx } // namespace afx

View File

@ -30,6 +30,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
endif() endif()
endif() endif()
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
if(COMMAND CMAKE_POLICY) if(COMMAND CMAKE_POLICY)
cmake_policy(SET CMP0003 NEW) cmake_policy(SET CMP0003 NEW)
cmake_policy(SET CMP0005 NEW) cmake_policy(SET CMP0005 NEW)
@ -42,6 +45,12 @@ if(COMMAND CMAKE_POLICY)
if(POLICY CMP0054) if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0054 NEW)
endif(POLICY CMP0054) endif(POLICY CMP0054)
if(POLICY CMP0058)
cmake_policy(SET CMP0058 NEW)
endif(POLICY CMP0058)
if(POLICY CMP0063)
cmake_policy(SET CMP0063 NEW)
endif(POLICY CMP0063)
if(POLICY CMP0075) if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW) cmake_policy(SET CMP0075 NEW)
endif(POLICY CMP0075) endif(POLICY CMP0075)
@ -161,8 +170,8 @@ if(NOT LIBTYPE)
endif() endif()
set(LIB_MAJOR_VERSION "1") set(LIB_MAJOR_VERSION "1")
set(LIB_MINOR_VERSION "22") set(LIB_MINOR_VERSION "23")
set(LIB_REVISION "2") set(LIB_REVISION "0")
set(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}") set(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}")
set(LIB_VERSION_NUM ${LIB_MAJOR_VERSION},${LIB_MINOR_VERSION},${LIB_REVISION},0) set(LIB_VERSION_NUM ${LIB_MAJOR_VERSION},${LIB_MINOR_VERSION},${LIB_REVISION},0)
@ -170,7 +179,7 @@ set(EXPORT_DECL "")
# Require C++14 # Require C++14
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# Prefer C11, but support C99 and C90 too. # Prefer C11, but support C99 and C90 too.
@ -230,7 +239,7 @@ if(MSVC)
if(HAVE_PERMISSIVE_SWITCH) if(HAVE_PERMISSIVE_SWITCH)
set(C_FLAGS ${C_FLAGS} $<$<COMPILE_LANGUAGE:CXX>:/permissive->) set(C_FLAGS ${C_FLAGS} $<$<COMPILE_LANGUAGE:CXX>:/permissive->)
endif() endif()
set(C_FLAGS ${C_FLAGS} /W4 /w14640 /wd4065 /wd4127 /wd4268 /wd4324 /wd5030) set(C_FLAGS ${C_FLAGS} /W4 /w14640 /wd4065 /wd4127 /wd4268 /wd4324 /wd5030 /wd5051)
if(NOT DXSDK_DIR) if(NOT DXSDK_DIR)
string(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}") string(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}")
@ -258,6 +267,16 @@ else()
-Wpedantic -Wpedantic
$<$<COMPILE_LANGUAGE:CXX>:-Wold-style-cast -Wnon-virtual-dtor -Woverloaded-virtual>) $<$<COMPILE_LANGUAGE:CXX>:-Wold-style-cast -Wnon-virtual-dtor -Woverloaded-virtual>)
check_cxx_compiler_flag(-Wno-c++20-attribute-extensions HAVE_WNO_CXX20_ATTR_EXT)
if(HAVE_WNO_CXX20_ATTR_EXT)
set(C_FLAGS ${C_FLAGS} $<$<COMPILE_LANGUAGE:CXX>:-Wno-c++20-attribute-extensions>)
else()
check_cxx_compiler_flag(-Wno-c++20-extensions HAVE_WNO_CXX20_EXT)
if(HAVE_WNO_CXX20_EXT)
set(C_FLAGS ${C_FLAGS} $<$<COMPILE_LANGUAGE:CXX>:-Wno-c++20-extensions>)
endif()
endif()
if(ALSOFT_WERROR) if(ALSOFT_WERROR)
set(C_FLAGS ${C_FLAGS} -Werror) set(C_FLAGS ${C_FLAGS} -Werror)
endif() endif()
@ -346,13 +365,6 @@ else()
endif() endif()
endif() endif()
if(HAVE_GCC_PROTECTED_VISIBILITY OR HAVE_GCC_DEFAULT_VISIBILITY)
check_c_compiler_flag(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH)
if(HAVE_VISIBILITY_HIDDEN_SWITCH)
set(C_FLAGS ${C_FLAGS} -fvisibility=hidden)
endif()
endif()
set(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}") set(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}")
endif() endif()
@ -472,7 +484,7 @@ if(CMAKE_SIZEOF_VOID_P MATCHES "4" AND HAVE_SSE2)
# assumes the stack is suitably aligned. Older Linux code or other # assumes the stack is suitably aligned. Older Linux code or other
# OSs don't guarantee this on 32-bit, so externally-callable # OSs don't guarantee this on 32-bit, so externally-callable
# functions need to ensure an aligned stack. # functions need to ensure an aligned stack.
set(EXPORT_DECL "${EXPORT_DECL} __attribute__((force_align_arg_pointer))") set(EXPORT_DECL "${EXPORT_DECL}__attribute__((force_align_arg_pointer))")
endif() endif()
endif() endif()
endif() endif()
@ -1051,8 +1063,8 @@ if(PULSEAUDIO_FOUND)
set(HAVE_PULSEAUDIO 1) set(HAVE_PULSEAUDIO 1)
set(BACKENDS "${BACKENDS} PulseAudio${IS_LINKED},") set(BACKENDS "${BACKENDS} PulseAudio${IS_LINKED},")
set(ALC_OBJS ${ALC_OBJS} alc/backends/pulseaudio.cpp alc/backends/pulseaudio.h) set(ALC_OBJS ${ALC_OBJS} alc/backends/pulseaudio.cpp alc/backends/pulseaudio.h)
add_backend_libs(${PULSEAUDIO_LIBRARIES}) add_backend_libs(${PULSEAUDIO_LIBRARY})
set(INC_PATHS ${INC_PATHS} ${PULSEAUDIO_INCLUDE_DIRS}) set(INC_PATHS ${INC_PATHS} ${PULSEAUDIO_INCLUDE_DIR})
endif() endif()
endif() endif()
if(ALSOFT_REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO) if(ALSOFT_REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO)
@ -1086,19 +1098,22 @@ if(COREAUDIO_FRAMEWORK AND AUDIOUNIT_INCLUDE_DIR)
set(HAVE_COREAUDIO 1) set(HAVE_COREAUDIO 1)
set(ALC_OBJS ${ALC_OBJS} alc/backends/coreaudio.cpp alc/backends/coreaudio.h) set(ALC_OBJS ${ALC_OBJS} alc/backends/coreaudio.cpp alc/backends/coreaudio.h)
set(BACKENDS "${BACKENDS} CoreAudio,") set(BACKENDS "${BACKENDS} CoreAudio,")
set(EXTRA_LIBS -Wl,-framework,CoreAudio ${EXTRA_LIBS})
if(CMAKE_SYSTEM_NAME MATCHES "^(iOS|tvOS)$") if(CMAKE_SYSTEM_NAME MATCHES "^(iOS|tvOS)$")
find_library(COREFOUNDATION_FRAMEWORK NAMES CoreFoundation) find_library(COREFOUNDATION_FRAMEWORK NAMES CoreFoundation)
set(EXTRA_LIBS ${COREAUDIO_FRAMEWORK} ${COREFOUNDATION_FRAMEWORK} ${EXTRA_LIBS}) if(COREFOUNDATION_FRAMEWORK)
set(EXTRA_LIBS -Wl,-framework,CoreFoundation ${EXTRA_LIBS})
endif()
else() else()
set(EXTRA_LIBS ${COREAUDIO_FRAMEWORK} /System/Library/Frameworks/AudioUnit.framework set(EXTRA_LIBS -Wl,-framework,AudioUnit,-framework,ApplicationServices ${EXTRA_LIBS})
/System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS})
endif() endif()
# Some versions of OSX may need the AudioToolbox framework. Add it if # Some versions of OSX may need the AudioToolbox framework. Add it if
# it's found. # it's found.
find_library(AUDIOTOOLBOX_LIBRARY NAMES AudioToolbox) find_library(AUDIOTOOLBOX_LIBRARY NAMES AudioToolbox)
if(AUDIOTOOLBOX_LIBRARY) if(AUDIOTOOLBOX_LIBRARY)
set(EXTRA_LIBS ${AUDIOTOOLBOX_LIBRARY} ${EXTRA_LIBS}) set(EXTRA_LIBS -Wl,-framework,AudioToolbox ${EXTRA_LIBS})
endif() endif()
set(INC_PATHS ${INC_PATHS} ${AUDIOUNIT_INCLUDE_DIR}) set(INC_PATHS ${INC_PATHS} ${AUDIOUNIT_INCLUDE_DIR})
@ -1129,17 +1144,7 @@ set(OBOE_TARGET )
if(ANDROID) if(ANDROID)
set(OBOE_SOURCE "" CACHE STRING "Source directory for Oboe.") set(OBOE_SOURCE "" CACHE STRING "Source directory for Oboe.")
if(OBOE_SOURCE) if(OBOE_SOURCE)
# Force Oboe to build with hidden symbols. Don't want to be exporting
# them from OpenAL.
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
check_cxx_compiler_flag(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH)
if(HAVE_VISIBILITY_HIDDEN_SWITCH)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
endif()
add_subdirectory(${OBOE_SOURCE} ./oboe) add_subdirectory(${OBOE_SOURCE} ./oboe)
set(CMAKE_CXX_FLAGS ${OLD_CXX_FLAGS})
unset(OLD_CXX_FLAGS)
set(OBOE_TARGET oboe) set(OBOE_TARGET oboe)
else() else()
find_package(oboe CONFIG) find_package(oboe CONFIG)
@ -1168,7 +1173,7 @@ endif()
# Check for SDL2 backend # Check for SDL2 backend
option(ALSOFT_REQUIRE_SDL2 "Require SDL2 backend" OFF) option(ALSOFT_REQUIRE_SDL2 "Require SDL2 backend" OFF)
find_package(SDL2) find_package(SDL2 QUIET)
if(SDL2_FOUND) if(SDL2_FOUND)
# Off by default, since it adds a runtime dependency # Off by default, since it adds a runtime dependency
option(ALSOFT_BACKEND_SDL2 "Enable SDL2 backend" OFF) option(ALSOFT_BACKEND_SDL2 "Enable SDL2 backend" OFF)
@ -1176,9 +1181,10 @@ if(SDL2_FOUND)
set(HAVE_SDL2 1) set(HAVE_SDL2 1)
set(ALC_OBJS ${ALC_OBJS} alc/backends/sdl2.cpp alc/backends/sdl2.h) set(ALC_OBJS ${ALC_OBJS} alc/backends/sdl2.cpp alc/backends/sdl2.h)
set(BACKENDS "${BACKENDS} SDL2,") set(BACKENDS "${BACKENDS} SDL2,")
set(EXTRA_LIBS ${SDL2_LIBRARY} ${EXTRA_LIBS}) set(EXTRA_LIBS ${EXTRA_LIBS} SDL2::SDL2)
set(INC_PATHS ${INC_PATHS} ${SDL2_INCLUDE_DIR})
endif() endif()
else()
message(STATUS "Could NOT find SDL2")
endif() endif()
if(ALSOFT_REQUIRE_SDL2 AND NOT SDL2_FOUND) if(ALSOFT_REQUIRE_SDL2 AND NOT SDL2_FOUND)
message(FATAL_ERROR "Failed to enabled required SDL2 backend") message(FATAL_ERROR "Failed to enabled required SDL2 backend")
@ -1199,13 +1205,19 @@ set(BACKENDS "${BACKENDS} Null")
find_package(Git) find_package(Git)
if(ALSOFT_UPDATE_BUILD_VERSION AND GIT_FOUND AND EXISTS "${OpenAL_SOURCE_DIR}/.git") if(ALSOFT_UPDATE_BUILD_VERSION AND GIT_FOUND AND EXISTS "${OpenAL_SOURCE_DIR}/.git")
# Get the current working branch and its latest abbreviated commit hash # Get the current working branch and its latest abbreviated commit hash
add_custom_target(build_version add_custom_command(OUTPUT "${OpenAL_BINARY_DIR}/version_witness.txt"
${CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE} -D LIB_VERSION=${LIB_VERSION} BYPRODUCTS "${OpenAL_BINARY_DIR}/version.h"
COMMAND ${CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE} -D LIB_VERSION=${LIB_VERSION}
-D LIB_VERSION_NUM=${LIB_VERSION_NUM} -D SRC=${OpenAL_SOURCE_DIR}/version.h.in -D LIB_VERSION_NUM=${LIB_VERSION_NUM} -D SRC=${OpenAL_SOURCE_DIR}/version.h.in
-D DST=${OpenAL_BINARY_DIR}/version.h -P ${OpenAL_SOURCE_DIR}/version.cmake -D DST=${OpenAL_BINARY_DIR}/version.h -P ${OpenAL_SOURCE_DIR}/version.cmake
COMMAND ${CMAKE_COMMAND} -E touch "${OpenAL_BINARY_DIR}/version_witness.txt"
WORKING_DIRECTORY "${OpenAL_SOURCE_DIR}" WORKING_DIRECTORY "${OpenAL_SOURCE_DIR}"
MAIN_DEPENDENCY "${OpenAL_SOURCE_DIR}/version.h.in"
DEPENDS "${OpenAL_SOURCE_DIR}/.git/index" "${OpenAL_SOURCE_DIR}/version.cmake"
VERBATIM VERBATIM
) )
add_custom_target(build_version DEPENDS "${OpenAL_BINARY_DIR}/version_witness.txt")
else() else()
set(GIT_BRANCH "UNKNOWN") set(GIT_BRANCH "UNKNOWN")
set(GIT_COMMIT_HASH "unknown") set(GIT_COMMIT_HASH "unknown")
@ -1219,11 +1231,11 @@ option(ALSOFT_EMBED_HRTF_DATA "Embed the HRTF data files (increases library foot
if(ALSOFT_EMBED_HRTF_DATA) if(ALSOFT_EMBED_HRTF_DATA)
macro(make_hrtf_header FILENAME VARNAME) macro(make_hrtf_header FILENAME VARNAME)
set(infile "${OpenAL_SOURCE_DIR}/hrtf/${FILENAME}") set(infile "${OpenAL_SOURCE_DIR}/hrtf/${FILENAME}")
set(outfile "${OpenAL_BINARY_DIR}/${VARNAME}.h") set(outfile "${OpenAL_BINARY_DIR}/${VARNAME}.txt")
add_custom_command(OUTPUT "${outfile}" add_custom_command(OUTPUT "${outfile}"
COMMAND ${CMAKE_COMMAND} -D "INPUT_FILE=${infile}" -D "OUTPUT_FILE=${outfile}" COMMAND ${CMAKE_COMMAND} -D "INPUT_FILE=${infile}" -D "OUTPUT_FILE=${outfile}"
-D "VARIABLE_NAME=${VARNAME}" -P "${CMAKE_MODULE_PATH}/bin2h.script.cmake" -P "${CMAKE_MODULE_PATH}/bin2h.script.cmake"
WORKING_DIRECTORY "${OpenAL_SOURCE_DIR}" WORKING_DIRECTORY "${OpenAL_SOURCE_DIR}"
DEPENDS "${infile}" "${CMAKE_MODULE_PATH}/bin2h.script.cmake" DEPENDS "${infile}" "${CMAKE_MODULE_PATH}/bin2h.script.cmake"
VERBATIM VERBATIM
@ -1231,7 +1243,7 @@ if(ALSOFT_EMBED_HRTF_DATA)
set(ALC_OBJS ${ALC_OBJS} "${outfile}") set(ALC_OBJS ${ALC_OBJS} "${outfile}")
endmacro() endmacro()
make_hrtf_header("Default HRTF.mhr" "hrtf_default") make_hrtf_header("Default HRTF.mhr" "default_hrtf")
endif() endif()
@ -1246,7 +1258,6 @@ if(ALSOFT_UTILS)
endif() endif()
if(ALSOFT_UTILS OR ALSOFT_EXAMPLES) if(ALSOFT_UTILS OR ALSOFT_EXAMPLES)
find_package(SndFile) find_package(SndFile)
find_package(SDL2)
if(SDL2_FOUND) if(SDL2_FOUND)
find_package(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE) find_package(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE)
endif() endif()
@ -1271,9 +1282,12 @@ if(LIBTYPE STREQUAL "STATIC")
set(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC) set(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC)
foreach(FLAG ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) foreach(FLAG ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB})
# If this is already a linker flag, or is a full path+file, add it # If this is already a linker flag, or is a full path+file, add it
# as-is. Otherwise, it's a name intended to be dressed as -lname. # as-is. If it's an SDL2 target, add the link flag for it. Otherwise,
# it's a name intended to be dressed as -lname.
if(FLAG MATCHES "^-.*" OR EXISTS "${FLAG}") if(FLAG MATCHES "^-.*" OR EXISTS "${FLAG}")
set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} ${FLAG}") set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} ${FLAG}")
elseif(FLAG MATCHES "^SDL2::SDL2")
set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -lSDL2")
else() else()
set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -l${FLAG}") set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -l${FLAG}")
endif() endif()
@ -1352,7 +1366,8 @@ else()
# !important: for osx framework public header works, the headers must be in # !important: for osx framework public header works, the headers must be in
# the project # the project
set(TARGET_PUBLIC_HEADERS include/AL/al.h include/AL/alc.h include/AL/alext.h include/AL/efx.h) set(TARGET_PUBLIC_HEADERS include/AL/al.h include/AL/alc.h include/AL/alext.h include/AL/efx.h
include/AL/efx-presets.h)
add_library(${IMPL_TARGET} SHARED ${OPENAL_OBJS} ${ALC_OBJS} ${CORE_OBJS} ${RC_CONFIG} add_library(${IMPL_TARGET} SHARED ${OPENAL_OBJS} ${ALC_OBJS} ${CORE_OBJS} ${RC_CONFIG}
${TARGET_PUBLIC_HEADERS}) ${TARGET_PUBLIC_HEADERS})
if(WIN32) if(WIN32)
@ -1364,7 +1379,7 @@ else()
# Sets framework name to soft_oal to avoid ambiguity with the system OpenAL.framework # Sets framework name to soft_oal to avoid ambiguity with the system OpenAL.framework
set(LIBNAME "soft_oal") set(LIBNAME "soft_oal")
if(GIT_FOUND) if(GIT_FOUND)
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} rev-list --count head EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD
TIMEOUT 5 TIMEOUT 5
OUTPUT_VARIABLE BUNDLE_VERSION OUTPUT_VARIABLE BUNDLE_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE) OUTPUT_STRIP_TRAILING_WHITESPACE)
@ -1385,8 +1400,8 @@ else()
FRAMEWORK_VERSION C FRAMEWORK_VERSION C
MACOSX_FRAMEWORK_NAME "${IMPL_TARGET}" MACOSX_FRAMEWORK_NAME "${IMPL_TARGET}"
MACOSX_FRAMEWORK_IDENTIFIER "org.openal-soft.openal" MACOSX_FRAMEWORK_IDENTIFIER "org.openal-soft.openal"
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${LIB_VERSION} MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${LIB_VERSION}"
MACOSX_FRAMEWORK_BUNDLE_VERSION ${BUNDLE_VERSION} MACOSX_FRAMEWORK_BUNDLE_VERSION "${BUNDLE_VERSION}"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
@ -1438,6 +1453,11 @@ if(WIN32 AND MINGW AND ALSOFT_BUILD_IMPORT_LIB AND NOT LIBTYPE STREQUAL "STATIC"
add_custom_command(TARGET OpenAL POST_BUILD add_custom_command(TARGET OpenAL POST_BUILD
COMMAND "${SED_EXECUTABLE}" -i -e "s/ @[^ ]*//" OpenAL32.def COMMAND "${SED_EXECUTABLE}" -i -e "s/ @[^ ]*//" OpenAL32.def
COMMAND "${CMAKE_DLLTOOL}" -d OpenAL32.def -l OpenAL32.lib -D OpenAL32.dll COMMAND "${CMAKE_DLLTOOL}" -d OpenAL32.def -l OpenAL32.lib -D OpenAL32.dll
# Technically OpenAL32.def was created by the build, but cmake
# doesn't recognize it due to -Wl,--output-def,OpenAL32.def being
# manually specified. But declaring the file here allows it to be
# properly cleaned, e.g. during make clean.
BYPRODUCTS OpenAL32.def OpenAL32.lib
COMMENT "Stripping ordinals from OpenAL32.def and generating OpenAL32.lib..." COMMENT "Stripping ordinals from OpenAL32.def and generating OpenAL32.lib..."
VERBATIM VERBATIM
) )
@ -1668,9 +1688,8 @@ if(ALSOFT_EXAMPLES)
if(SDL2_FOUND) if(SDL2_FOUND)
add_executable(alloopback examples/alloopback.c) add_executable(alloopback examples/alloopback.c)
target_include_directories(alloopback PRIVATE ${SDL2_INCLUDE_DIR})
target_link_libraries(alloopback target_link_libraries(alloopback
PRIVATE ${LINKER_FLAGS} ${SDL2_LIBRARY} ex-common ${MATH_LIB}) PRIVATE ${LINKER_FLAGS} SDL2::SDL2 ex-common ${MATH_LIB})
if(ALSOFT_INSTALL_EXAMPLES) if(ALSOFT_INSTALL_EXAMPLES)
set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alloopback) set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alloopback)
@ -1681,33 +1700,32 @@ if(ALSOFT_EXAMPLES)
set(FFVER_OK FALSE) set(FFVER_OK FALSE)
if(FFMPEG_FOUND) if(FFMPEG_FOUND)
set(FFVER_OK TRUE) set(FFVER_OK TRUE)
if(AVFORMAT_VERSION VERSION_LESS "57.56.101") if(AVFORMAT_VERSION VERSION_LESS "59.27.100")
message(STATUS "libavformat is too old! (${AVFORMAT_VERSION}, wanted 57.56.101)") message(STATUS "libavformat is too old! (${AVFORMAT_VERSION}, wanted 59.27.100)")
set(FFVER_OK FALSE) set(FFVER_OK FALSE)
endif() endif()
if(AVCODEC_VERSION VERSION_LESS "57.64.101") if(AVCODEC_VERSION VERSION_LESS "59.37.100")
message(STATUS "libavcodec is too old! (${AVCODEC_VERSION}, wanted 57.64.101)") message(STATUS "libavcodec is too old! (${AVCODEC_VERSION}, wanted 59.37.100)")
set(FFVER_OK FALSE) set(FFVER_OK FALSE)
endif() endif()
if(AVUTIL_VERSION VERSION_LESS "55.34.101") if(AVUTIL_VERSION VERSION_LESS "57.28.100")
message(STATUS "libavutil is too old! (${AVUTIL_VERSION}, wanted 55.34.101)") message(STATUS "libavutil is too old! (${AVUTIL_VERSION}, wanted 57.28.100)")
set(FFVER_OK FALSE) set(FFVER_OK FALSE)
endif() endif()
if(SWSCALE_VERSION VERSION_LESS "4.2.100") if(SWSCALE_VERSION VERSION_LESS "6.7.100")
message(STATUS "libswscale is too old! (${SWSCALE_VERSION}, wanted 4.2.100)") message(STATUS "libswscale is too old! (${SWSCALE_VERSION}, wanted 6.7.100)")
set(FFVER_OK FALSE) set(FFVER_OK FALSE)
endif() endif()
if(SWRESAMPLE_VERSION VERSION_LESS "2.3.100") if(SWRESAMPLE_VERSION VERSION_LESS "4.7.100")
message(STATUS "libswresample is too old! (${SWRESAMPLE_VERSION}, wanted 2.3.100)") message(STATUS "libswresample is too old! (${SWRESAMPLE_VERSION}, wanted 4.7.100)")
set(FFVER_OK FALSE) set(FFVER_OK FALSE)
endif() endif()
endif() endif()
if(FFVER_OK) if(FFVER_OK)
add_executable(alffplay examples/alffplay.cpp) add_executable(alffplay examples/alffplay.cpp)
target_include_directories(alffplay target_include_directories(alffplay PRIVATE ${FFMPEG_INCLUDE_DIRS})
PRIVATE ${SDL2_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIRS})
target_link_libraries(alffplay target_link_libraries(alffplay
PRIVATE ${LINKER_FLAGS} ${SDL2_LIBRARY} ${FFMPEG_LIBRARIES} ex-common) PRIVATE ${LINKER_FLAGS} SDL2::SDL2 ${FFMPEG_LIBRARIES} ex-common)
if(ALSOFT_INSTALL_EXAMPLES) if(ALSOFT_INSTALL_EXAMPLES)
set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alffplay) set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alffplay)

View File

@ -1,3 +1,55 @@
openal-soft-1.23.0:
Fixed CoreAudio capture support.
Fixed handling per-version EAX properties.
Fixed interpolating changes to the Super Stereo width source property.
Fixed detection of the update and buffer size from PipeWire.
Fixed resuming playback devices with OpenSL.
Fixed support for certain OpenAL implementations with the router.
Improved reverb environment transitions.
Improved performance of convolution reverb.
Improved quality and performance of the pitch shifter effect slightly.
Improved sub-sample precision for resampled sources.
Improved blending spatialized multi-channel sources that use the source
radius property.
Improved mixing 2D ambisonic sources for higher-order 3D ambisonic mixing.
Improved quadraphonic and 7.1 surround sound output slightly.
Added config options for UHJ encoding/decoding quality. Including Super
Stereo processing.
Added a config option for specifying the speaker distance.
Added a compatibility config option for specifying the NFC distance
scaling.
Added a config option for mixing on PipeWire's non-real-time thread.
Added support for virtual source nodes with PipeWire capture.
Added the ability for the WASAPI backend to use different playback rates.
Added support for SOFA files that define per-response delays in makemhr.
Changed the default fallback playback sample rate to 48khz. This doesn't
affect most backends, which can detect a default rate from the system.
Changed the default resampler to cubic.
Changed the default HRTF size from 32 to 64 points.
openal-soft-1.22.2: openal-soft-1.22.2:
Fixed PipeWire version check. Fixed PipeWire version check.

View File

@ -1,12 +1,12 @@
OpenAL soft OpenAL Soft
=========== ===========
`master` branch CI status : [![Build Status](https://travis-ci.org/kcat/openal-soft.svg?branch=master)](https://travis-ci.org/kcat/openal-soft) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true) `master` branch CI status : [![GitHub Actions Status](https://github.com/kcat/openal-soft/actions/workflows/ci.yml/badge.svg)](https://github.com/kcat/openal-soft/actions) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)
OpenAL Soft is an LGPL-licensed, cross-platform, software implementation of the OpenAL 3D audio API. It's forked from the open-sourced Windows version available originally from openal.org's SVN repository (now defunct). OpenAL Soft is an LGPL-licensed, cross-platform, software implementation of the OpenAL 3D audio API. It's forked from the open-sourced Windows version available originally from openal.org's SVN repository (now defunct).
OpenAL provides capabilities for playing audio in a virtual 3D environment. Distance attenuation, doppler shift, and directional sound emitters are among the features handled by the API. More advanced effects, including air absorption, occlusion, and environmental reverb, are available through the EFX extension. It also facilitates streaming audio, multi-channel buffers, and audio capture. OpenAL provides capabilities for playing audio in a virtual 3D environment. Distance attenuation, doppler shift, and directional sound emitters are among the features handled by the API. More advanced effects, including air absorption, occlusion, and environmental reverb, are available through the EFX extension. It also facilitates streaming audio, multi-channel buffers, and audio capture.
More information is available on the [official website](http://openal-soft.org/) More information is available on the [official website](http://openal-soft.org/).
Source Install Source Install
------------- -------------
@ -17,20 +17,37 @@ directory, and run:
cmake .. cmake ..
``` ```
Assuming configuration went well, you can then build it, typically using GNU Alternatively, you can use any available CMake front-end, like cmake-gui,
Make (KDevelop, MSVC, and others are possible depending on your system setup ccmake, or your preferred IDE's CMake project parser.
and CMake configuration).
Assuming configuration went well, you can then build it. The command
`cmake --build .` will instruct CMake to build the project with the toolchain
chosen during configuration (often GNU Make or NMake, although others are
possible).
Please Note: Double check that the appropriate backends were detected. Often, Please Note: Double check that the appropriate backends were detected. Often,
complaints of no sound, crashing, and missing devices can be solved by making complaints of no sound, crashing, and missing devices can be solved by making
sure the correct backends are being used. CMake's output will identify which sure the correct backends are being used. CMake's output will identify which
backends were enabled. backends were enabled.
For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio For most systems, you will likely want to make sure PipeWire, PulseAudio, and
were detected (if your target system uses them). For Windows, make sure ALSA were detected (if your target system uses them). For Windows, make sure
DirectSound was detected. WASAPI was detected.
Building openal-soft - Using vcpkg
----------------------------------
You can download and install openal-soft using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install openal-soft
The openal-soft port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
Utilities Utilities
--------- ---------
The source package comes with an informational utility, openal-info, and is The source package comes with an informational utility, openal-info, and is

File diff suppressed because it is too large Load Diff

View File

@ -20,13 +20,23 @@
#include <memory> #include <memory>
#include "eax/call.h" #include "eax/call.h"
#include "eax/effect.h" #include "eax/effect.h"
#include "eax/exception.h"
#include "eax/fx_slot_index.h" #include "eax/fx_slot_index.h"
#include "eax/utils.h"
#endif // ALSOFT_EAX #endif // ALSOFT_EAX
struct ALbuffer; struct ALbuffer;
struct ALeffect; struct ALeffect;
struct WetBuffer; struct WetBuffer;
#ifdef ALSOFT_EAX
class EaxFxSlotException : public EaxException {
public:
explicit EaxFxSlotException(const char* message)
: EaxException{"EAX_FX_SLOT", message}
{}
};
#endif // ALSOFT_EAX
enum class SlotState : ALenum { enum class SlotState : ALenum {
Initial = AL_INITIAL, Initial = AL_INITIAL,
@ -53,12 +63,12 @@ struct ALeffectslot {
RefCount ref{0u}; RefCount ref{0u};
EffectSlot mSlot; EffectSlot *mSlot{nullptr};
/* Self ID */ /* Self ID */
ALuint id{}; ALuint id{};
ALeffectslot(); ALeffectslot(ALCcontext *context);
ALeffectslot(const ALeffectslot&) = delete; ALeffectslot(const ALeffectslot&) = delete;
ALeffectslot& operator=(const ALeffectslot&) = delete; ALeffectslot& operator=(const ALeffectslot&) = delete;
~ALeffectslot(); ~ALeffectslot();
@ -72,169 +82,289 @@ struct ALeffectslot {
#ifdef ALSOFT_EAX #ifdef ALSOFT_EAX
public: public:
void eax_initialize( void eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index);
const EaxCall& call,
ALCcontext& al_context,
EaxFxSlotIndexValue index);
const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept; EaxFxSlotIndexValue eax_get_index() const noexcept { return eax_fx_slot_index_; }
const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept
{ return eax_; }
// Returns `true` if all sources should be updated, or `false` otherwise.
// [[nodiscard]]
bool eax_dispatch(const EaxCall& call) bool eax_dispatch(const EaxCall& call)
{ return call.is_get() ? eax_get(call) : eax_set(call); } { return call.is_get() ? eax_get(call) : eax_set(call); }
void eax_commit();
void eax_unlock_legacy() noexcept;
void eax_commit() { eax_apply_deferred(); }
private: private:
static constexpr auto eax_load_effect_dirty_bit = EaxDirtyFlags{1} << 0;
static constexpr auto eax_volume_dirty_bit = EaxDirtyFlags{1} << 1;
static constexpr auto eax_lock_dirty_bit = EaxDirtyFlags{1} << 2;
static constexpr auto eax_flags_dirty_bit = EaxDirtyFlags{1} << 3;
static constexpr auto eax_occlusion_dirty_bit = EaxDirtyFlags{1} << 4;
static constexpr auto eax_occlusion_lf_ratio_dirty_bit = EaxDirtyFlags{1} << 5;
using Exception = EaxFxSlotException;
using Eax4Props = EAX40FXSLOTPROPERTIES;
struct Eax4State {
Eax4Props i; // Immediate.
};
using Eax5Props = EAX50FXSLOTPROPERTIES;
struct Eax5State {
Eax5Props i; // Immediate.
};
struct EaxRangeValidator {
template<typename TValue>
void operator()(
const char* name,
const TValue& value,
const TValue& min_value,
const TValue& max_value) const
{
eax_validate_range<Exception>(name, value, min_value, max_value);
}
};
struct Eax4GuidLoadEffectValidator {
void operator()(const GUID& guidLoadEffect) const
{
if (guidLoadEffect != EAX_NULL_GUID &&
guidLoadEffect != EAX_REVERB_EFFECT &&
guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT &&
guidLoadEffect != EAX_AUTOWAH_EFFECT &&
guidLoadEffect != EAX_CHORUS_EFFECT &&
guidLoadEffect != EAX_DISTORTION_EFFECT &&
guidLoadEffect != EAX_ECHO_EFFECT &&
guidLoadEffect != EAX_EQUALIZER_EFFECT &&
guidLoadEffect != EAX_FLANGER_EFFECT &&
guidLoadEffect != EAX_FREQUENCYSHIFTER_EFFECT &&
guidLoadEffect != EAX_VOCALMORPHER_EFFECT &&
guidLoadEffect != EAX_PITCHSHIFTER_EFFECT &&
guidLoadEffect != EAX_RINGMODULATOR_EFFECT)
{
eax_fail_unknown_effect_id();
}
}
};
struct Eax4VolumeValidator {
void operator()(long lVolume) const
{
EaxRangeValidator{}(
"Volume",
lVolume,
EAXFXSLOT_MINVOLUME,
EAXFXSLOT_MAXVOLUME);
}
};
struct Eax4LockValidator {
void operator()(long lLock) const
{
EaxRangeValidator{}(
"Lock",
lLock,
EAXFXSLOT_MINLOCK,
EAXFXSLOT_MAXLOCK);
}
};
struct Eax4FlagsValidator {
void operator()(unsigned long ulFlags) const
{
EaxRangeValidator{}(
"Flags",
ulFlags,
0UL,
~EAX40FXSLOTFLAGS_RESERVED);
}
};
struct Eax4AllValidator {
void operator()(const EAX40FXSLOTPROPERTIES& all) const
{
Eax4GuidLoadEffectValidator{}(all.guidLoadEffect);
Eax4VolumeValidator{}(all.lVolume);
Eax4LockValidator{}(all.lLock);
Eax4FlagsValidator{}(all.ulFlags);
}
};
struct Eax5OcclusionValidator {
void operator()(long lOcclusion) const
{
EaxRangeValidator{}(
"Occlusion",
lOcclusion,
EAXFXSLOT_MINOCCLUSION,
EAXFXSLOT_MAXOCCLUSION);
}
};
struct Eax5OcclusionLfRatioValidator {
void operator()(float flOcclusionLFRatio) const
{
EaxRangeValidator{}(
"Occlusion LF Ratio",
flOcclusionLFRatio,
EAXFXSLOT_MINOCCLUSIONLFRATIO,
EAXFXSLOT_MAXOCCLUSIONLFRATIO);
}
};
struct Eax5FlagsValidator {
void operator()(unsigned long ulFlags) const
{
EaxRangeValidator{}(
"Flags",
ulFlags,
0UL,
~EAX50FXSLOTFLAGS_RESERVED);
}
};
struct Eax5AllValidator {
void operator()(const EAX50FXSLOTPROPERTIES& all) const
{
Eax4AllValidator{}(static_cast<const EAX40FXSLOTPROPERTIES&>(all));
Eax5OcclusionValidator{}(all.lOcclusion);
Eax5OcclusionLfRatioValidator{}(all.flOcclusionLFRatio);
}
};
ALCcontext* eax_al_context_{}; ALCcontext* eax_al_context_{};
EaxFxSlotIndexValue eax_fx_slot_index_{}; EaxFxSlotIndexValue eax_fx_slot_index_{};
int eax_version_{}; // Current EAX version.
EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{}; EaxDirtyFlags eax_df_{}; // Dirty flags for the current EAX version.
EaxEffectUPtr eax_effect_{}; EaxEffectUPtr eax_effect_{};
bool eax_is_locked_{}; Eax5State eax123_{}; // EAX1/EAX2/EAX3 state.
Eax4State eax4_{}; // EAX4 state.
Eax5State eax5_{}; // EAX5 state.
Eax5Props eax_{}; // Current EAX state.
[[noreturn]] static void eax_fail(const char* message);
[[noreturn]] static void eax_fail_unknown_effect_id();
[[noreturn]] static void eax_fail_unknown_property_id();
[[noreturn]] static void eax_fail_unknown_version();
[[noreturn]] // Gets a new value from EAX call,
static void eax_fail( // validates it,
const char* message); // sets a dirty flag only if the new value differs form the old one,
// and assigns the new value.
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
static void eax_fx_slot_set(const EaxCall& call, TProperties& dst, EaxDirtyFlags& dirty_flags)
{
const auto& src = call.get_value<Exception, const TProperties>();
TValidator{}(src);
dirty_flags |= (dst != src ? TDirtyBit : EaxDirtyFlags{});
dst = src;
}
// Gets a new value from EAX call,
// validates it,
// sets a dirty flag without comparing the values,
// and assigns the new value.
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
static void eax_fx_slot_set_dirty(const EaxCall& call, TProperties& dst,
EaxDirtyFlags& dirty_flags)
{
const auto& src = call.get_value<Exception, const TProperties>();
TValidator{}(src);
dirty_flags |= TDirtyBit;
dst = src;
}
GUID eax_get_eax_default_effect_guid() const noexcept; constexpr bool eax4_fx_slot_is_legacy() const noexcept
{ return eax_fx_slot_index_ < 2; }
void eax4_fx_slot_ensure_unlocked() const;
static ALenum eax_get_efx_effect_type(const GUID& guid);
const GUID& eax_get_eax_default_effect_guid() const noexcept;
long eax_get_eax_default_lock() const noexcept; long eax_get_eax_default_lock() const noexcept;
void eax_set_eax_fx_slot_defaults(); void eax4_fx_slot_set_defaults(Eax4Props& props) noexcept;
void eax5_fx_slot_set_defaults(Eax5Props& props) noexcept;
void eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept;
void eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept;
void eax_fx_slot_set_current_defaults();
void eax_fx_slot_set_defaults();
void eax_initialize_eax(); void eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const;
void eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props) const;
void eax_initialize_lock(); void eax_fx_slot_get(const EaxCall& call) const;
// Returns `true` if all sources should be updated, or `false` otherwise.
void eax_initialize_effects(const EaxCall& call);
void eax_get_fx_slot_all(const EaxCall& call) const;
void eax_get_fx_slot(const EaxCall& call) const;
// [[nodiscard]]
bool eax_get(const EaxCall& call); bool eax_get(const EaxCall& call);
void eax_fx_slot_load_effect();
void eax_fx_slot_set_volume();
void eax_fx_slot_set_environment_flag();
void eax_fx_slot_set_flags();
void eax_set_fx_slot_effect(const EaxCall& call, ALenum effect_type); void eax4_fx_slot_set_all(const EaxCall& call);
void eax5_fx_slot_set_all(const EaxCall& call);
void eax_set_fx_slot_effect(const EaxCall& call); bool eax_fx_slot_should_update_sources() const noexcept;
// Returns `true` if all sources should be updated, or `false` otherwise.
void eax_set_efx_effect_slot_gain(); bool eax4_fx_slot_set(const EaxCall& call);
// Returns `true` if all sources should be updated, or `false` otherwise.
void eax_set_fx_slot_volume(); bool eax5_fx_slot_set(const EaxCall& call);
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax_fx_slot_set(const EaxCall& call);
void eax_set_effect_slot_send_auto(); // Returns `true` if all sources should be updated, or `false` otherwise.
void eax_set_fx_slot_flags();
void eax_ensure_is_unlocked() const;
void eax_validate_fx_slot_effect(const GUID& eax_effect_id);
void eax_validate_fx_slot_volume(long eax_volume);
void eax_validate_fx_slot_lock(long eax_lock);
void eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags);
void eax_validate_fx_slot_occlusion(long eax_occlusion);
void eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio);
void eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot);
void eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot);
void eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id);
void eax_set_fx_slot_volume(
long eax_volume);
void eax_set_fx_slot_lock(
long eax_lock);
void eax_set_fx_slot_flags(
unsigned long eax_flags);
// [[nodiscard]]
bool eax_set_fx_slot_occlusion(
long eax_occlusion);
// [[nodiscard]]
bool eax_set_fx_slot_occlusion_lf_ratio(
float eax_occlusion_lf_ratio);
void eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot);
// [[nodiscard]]
bool eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot);
void eax_defer_fx_slot_effect(const EaxCall& call);
void eax_defer_fx_slot_volume(const EaxCall& call);
void eax_defer_fx_slot_lock(const EaxCall& call);
void eax_defer_fx_slot_flags(const EaxCall& call);
// [[nodiscard]]
bool eax_defer_fx_slot_occlusion(const EaxCall& call);
// [[nodiscard]]
bool eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call);
// [[nodiscard]]
bool eax_defer_fx_slot_all(const EaxCall& call);
bool eax_set_fx_slot(const EaxCall& call);
void eax_apply_deferred();
// [[nodiscard]]
bool eax_set(const EaxCall& call); bool eax_set(const EaxCall& call);
template<
EaxDirtyFlags TDirtyBit,
typename TMemberResult,
typename TProps,
typename TState>
void eax_fx_slot_commit_property(TState& state, EaxDirtyFlags& dst_df,
TMemberResult TProps::*member) noexcept
{
auto& src_i = state.i;
auto& dst_i = eax_;
if((eax_df_ & TDirtyBit) != EaxDirtyFlags{})
{
dst_df |= TDirtyBit;
dst_i.*member = src_i.*member;
}
}
void eax4_fx_slot_commit(EaxDirtyFlags& dst_df);
void eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df);
void eax_dispatch_effect(const EaxCall& call); void eax_dispatch_effect(const EaxCall& call);
// `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)`
void eax_set_effect_slot_effect(EaxEffect &effect); void eax_set_efx_slot_effect(EaxEffect &effect);
// `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)` // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)`
void eax_set_effect_slot_send_auto(bool is_send_auto); void eax_set_efx_slot_send_auto(bool is_send_auto);
// `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)` // `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)`
void eax_set_effect_slot_gain(ALfloat gain); void eax_set_efx_slot_gain(ALfloat gain);
public: public:
class EaxDeleter { class EaxDeleter {
public: public:
void operator()(ALeffectslot *effect_slot); void operator()(ALeffectslot *effect_slot);
}; // EaxAlEffectSlotDeleter };
#endif // ALSOFT_EAX #endif // ALSOFT_EAX
}; };
void UpdateAllEffectSlotProps(ALCcontext *context); void UpdateAllEffectSlotProps(ALCcontext *context);
#ifdef ALSOFT_EAX #ifdef ALSOFT_EAX
using EaxAlEffectSlotUPtr = std::unique_ptr<ALeffectslot, ALeffectslot::EaxDeleter>; using EaxAlEffectSlotUPtr = std::unique_ptr<ALeffectslot, ALeffectslot::EaxDeleter>;
EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context);
EaxAlEffectSlotUPtr eax_create_al_effect_slot( void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot);
ALCcontext& context);
void eax_delete_al_effect_slot(
ALCcontext& context,
ALeffectslot& effect_slot);
#endif // ALSOFT_EAX #endif // ALSOFT_EAX
#endif #endif

View File

@ -288,8 +288,8 @@ al::optional<AmbiLayout> AmbiLayoutFromEnum(ALenum layout)
{ {
switch(layout) switch(layout)
{ {
case AL_FUMA_SOFT: return al::make_optional(AmbiLayout::FuMa); case AL_FUMA_SOFT: return AmbiLayout::FuMa;
case AL_ACN_SOFT: return al::make_optional(AmbiLayout::ACN); case AL_ACN_SOFT: return AmbiLayout::ACN;
} }
return al::nullopt; return al::nullopt;
} }
@ -307,9 +307,9 @@ al::optional<AmbiScaling> AmbiScalingFromEnum(ALenum scale)
{ {
switch(scale) switch(scale)
{ {
case AL_FUMA_SOFT: return al::make_optional(AmbiScaling::FuMa); case AL_FUMA_SOFT: return AmbiScaling::FuMa;
case AL_SN3D_SOFT: return al::make_optional(AmbiScaling::SN3D); case AL_SN3D_SOFT: return AmbiScaling::SN3D;
case AL_N3D_SOFT: return al::make_optional(AmbiScaling::N3D); case AL_N3D_SOFT: return AmbiScaling::N3D;
} }
return al::nullopt; return al::nullopt;
} }
@ -329,18 +329,18 @@ al::optional<FmtChannels> FmtFromUserFmt(UserFmtChannels chans)
{ {
switch(chans) switch(chans)
{ {
case UserFmtMono: return al::make_optional(FmtMono); case UserFmtMono: return FmtMono;
case UserFmtStereo: return al::make_optional(FmtStereo); case UserFmtStereo: return FmtStereo;
case UserFmtRear: return al::make_optional(FmtRear); case UserFmtRear: return FmtRear;
case UserFmtQuad: return al::make_optional(FmtQuad); case UserFmtQuad: return FmtQuad;
case UserFmtX51: return al::make_optional(FmtX51); case UserFmtX51: return FmtX51;
case UserFmtX61: return al::make_optional(FmtX61); case UserFmtX61: return FmtX61;
case UserFmtX71: return al::make_optional(FmtX71); case UserFmtX71: return FmtX71;
case UserFmtBFormat2D: return al::make_optional(FmtBFormat2D); case UserFmtBFormat2D: return FmtBFormat2D;
case UserFmtBFormat3D: return al::make_optional(FmtBFormat3D); case UserFmtBFormat3D: return FmtBFormat3D;
case UserFmtUHJ2: return al::make_optional(FmtUHJ2); case UserFmtUHJ2: return FmtUHJ2;
case UserFmtUHJ3: return al::make_optional(FmtUHJ3); case UserFmtUHJ3: return FmtUHJ3;
case UserFmtUHJ4: return al::make_optional(FmtUHJ4); case UserFmtUHJ4: return FmtUHJ4;
} }
return al::nullopt; return al::nullopt;
} }
@ -348,12 +348,12 @@ al::optional<FmtType> FmtFromUserFmt(UserFmtType type)
{ {
switch(type) switch(type)
{ {
case UserFmtUByte: return al::make_optional(FmtUByte); case UserFmtUByte: return FmtUByte;
case UserFmtShort: return al::make_optional(FmtShort); case UserFmtShort: return FmtShort;
case UserFmtFloat: return al::make_optional(FmtFloat); case UserFmtFloat: return FmtFloat;
case UserFmtDouble: return al::make_optional(FmtDouble); case UserFmtDouble: return FmtDouble;
case UserFmtMulaw: return al::make_optional(FmtMulaw); case UserFmtMulaw: return FmtMulaw;
case UserFmtAlaw: return al::make_optional(FmtAlaw); case UserFmtAlaw: return FmtAlaw;
/* ADPCM not handled here. */ /* ADPCM not handled here. */
case UserFmtIMA4: break; case UserFmtIMA4: break;
case UserFmtMSADPCM: break; case UserFmtMSADPCM: break;
@ -411,14 +411,14 @@ bool EnsureBuffers(ALCdevice *device, size_t needed)
while(needed > count) while(needed > count)
{ {
if UNLIKELY(device->BufferList.size() >= 1<<25) if(device->BufferList.size() >= 1<<25) [[unlikely]]
return false; return false;
device->BufferList.emplace_back(); device->BufferList.emplace_back();
auto sublist = device->BufferList.end() - 1; auto sublist = device->BufferList.end() - 1;
sublist->FreeMask = ~0_u64; sublist->FreeMask = ~0_u64;
sublist->Buffers = static_cast<ALbuffer*>(al_calloc(alignof(ALbuffer), sizeof(ALbuffer)*64)); sublist->Buffers = static_cast<ALbuffer*>(al_calloc(alignof(ALbuffer), sizeof(ALbuffer)*64));
if UNLIKELY(!sublist->Buffers) if(!sublist->Buffers) [[unlikely]]
{ {
device->BufferList.pop_back(); device->BufferList.pop_back();
return false; return false;
@ -467,10 +467,10 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
const size_t lidx{(id-1) >> 6}; const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f}; const ALuint slidx{(id-1) & 0x3f};
if UNLIKELY(lidx >= device->BufferList.size()) if(lidx >= device->BufferList.size()) [[unlikely]]
return nullptr; return nullptr;
BufferSubList &sublist = device->BufferList[lidx]; BufferSubList &sublist = device->BufferList[lidx];
if UNLIKELY(sublist.FreeMask & (1_u64 << slidx)) if(sublist.FreeMask & (1_u64 << slidx)) [[unlikely]]
return nullptr; return nullptr;
return sublist.Buffers + slidx; return sublist.Buffers + slidx;
} }
@ -531,14 +531,14 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
UserFmtChannels SrcChannels, UserFmtType SrcType, const al::byte *SrcData, UserFmtChannels SrcChannels, UserFmtType SrcType, const al::byte *SrcData,
ALbitfieldSOFT access) ALbitfieldSOFT access)
{ {
if UNLIKELY(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_OPERATION,, "Modifying storage for in-use buffer %u", return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u",
ALBuf->id); ALBuf->id);
/* Currently no channel configurations need to be converted. */ /* Currently no channel configurations need to be converted. */
auto DstChannels = FmtFromUserFmt(SrcChannels); auto DstChannels = FmtFromUserFmt(SrcChannels);
if UNLIKELY(!DstChannels) if(!DstChannels) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_ENUM, , "Invalid format"); return context->setError(AL_INVALID_ENUM, "Invalid format");
/* IMA4 and MSADPCM convert to 16-bit short. /* IMA4 and MSADPCM convert to 16-bit short.
* *
@ -548,19 +548,19 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
*/ */
if((access&MAP_READ_WRITE_FLAGS)) if((access&MAP_READ_WRITE_FLAGS))
{ {
if UNLIKELY(SrcType == UserFmtIMA4 || SrcType == UserFmtMSADPCM) if(SrcType == UserFmtIMA4 || SrcType == UserFmtMSADPCM) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_VALUE,, "%s samples cannot be mapped", return context->setError(AL_INVALID_VALUE, "%s samples cannot be mapped",
NameFromUserFmtType(SrcType)); NameFromUserFmtType(SrcType));
} }
auto DstType = (SrcType == UserFmtIMA4 || SrcType == UserFmtMSADPCM) auto DstType = (SrcType == UserFmtIMA4 || SrcType == UserFmtMSADPCM)
? al::make_optional(FmtShort) : FmtFromUserFmt(SrcType); ? al::make_optional(FmtShort) : FmtFromUserFmt(SrcType);
if UNLIKELY(!DstType) if(!DstType) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_ENUM, , "Invalid format"); return context->setError(AL_INVALID_ENUM, "Invalid format");
const ALuint unpackalign{ALBuf->UnpackAlign}; const ALuint unpackalign{ALBuf->UnpackAlign};
const ALuint align{SanitizeAlignment(SrcType, unpackalign)}; const ALuint align{SanitizeAlignment(SrcType, unpackalign)};
if UNLIKELY(align < 1) if(align < 1) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid unpack alignment %u for %s samples", return context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u for %s samples",
unpackalign, NameFromUserFmtType(SrcType)); unpackalign, NameFromUserFmtType(SrcType));
const ALuint ambiorder{IsBFormat(*DstChannels) ? ALBuf->UnpackAmbiOrder : const ALuint ambiorder{IsBFormat(*DstChannels) ? ALBuf->UnpackAmbiOrder :
@ -569,12 +569,12 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
if((access&AL_PRESERVE_DATA_BIT_SOFT)) if((access&AL_PRESERVE_DATA_BIT_SOFT))
{ {
/* Can only preserve data with the same format and alignment. */ /* Can only preserve data with the same format and alignment. */
if UNLIKELY(ALBuf->mChannels != *DstChannels || ALBuf->OriginalType != SrcType) if(ALBuf->mChannels != *DstChannels || ALBuf->OriginalType != SrcType) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched format"); return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched format");
if UNLIKELY(ALBuf->OriginalAlign != align) if(ALBuf->OriginalAlign != align) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched alignment"); return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched alignment");
if(ALBuf->mAmbiOrder != ambiorder) if(ALBuf->mAmbiOrder != ambiorder) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched order"); return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched order");
} }
/* Convert the input/source size in bytes to sample frames using the unpack /* Convert the input/source size in bytes to sample frames using the unpack
@ -584,13 +584,13 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
((SrcType == UserFmtIMA4) ? (align-1)/2 + 4 : ((SrcType == UserFmtIMA4) ? (align-1)/2 + 4 :
(SrcType == UserFmtMSADPCM) ? (align-2)/2 + 7 : (SrcType == UserFmtMSADPCM) ? (align-2)/2 + 7 :
(align * BytesFromUserFmt(SrcType)))}; (align * BytesFromUserFmt(SrcType)))};
if UNLIKELY((size%SrcByteAlign) != 0) if((size%SrcByteAlign) != 0) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_VALUE,, return context->setError(AL_INVALID_VALUE,
"Data size %d is not a multiple of frame size %d (%d unpack alignment)", "Data size %d is not a multiple of frame size %d (%d unpack alignment)",
size, SrcByteAlign, align); size, SrcByteAlign, align);
if UNLIKELY(size/SrcByteAlign > std::numeric_limits<ALsizei>::max()/align) if(size/SrcByteAlign > std::numeric_limits<ALsizei>::max()/align) [[unlikely]]
SETERR_RETURN(context, AL_OUT_OF_MEMORY,, return context->setError(AL_OUT_OF_MEMORY,
"Buffer size overflow, %d blocks x %d samples per block", size/SrcByteAlign, align); "Buffer size overflow, %d blocks x %d samples per block", size/SrcByteAlign, align);
const ALuint frames{size / SrcByteAlign * align}; const ALuint frames{size / SrcByteAlign * align};
@ -599,8 +599,8 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
*/ */
ALuint NumChannels{ChannelsFromFmt(*DstChannels, ambiorder)}; ALuint NumChannels{ChannelsFromFmt(*DstChannels, ambiorder)};
ALuint FrameSize{NumChannels * BytesFromFmt(*DstType)}; ALuint FrameSize{NumChannels * BytesFromFmt(*DstType)};
if UNLIKELY(frames > std::numeric_limits<size_t>::max()/FrameSize) if(frames > std::numeric_limits<size_t>::max()/FrameSize) [[unlikely]]
SETERR_RETURN(context, AL_OUT_OF_MEMORY,, return context->setError(AL_OUT_OF_MEMORY,
"Buffer size overflow, %d frames x %d bytes per frame", frames, FrameSize); "Buffer size overflow, %d frames x %d bytes per frame", frames, FrameSize);
size_t newsize{static_cast<size_t>(frames) * FrameSize}; size_t newsize{static_cast<size_t>(frames) * FrameSize};
@ -609,7 +609,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
{ {
ALCdevice &device = *context->mALDevice; ALCdevice &device = *context->mALDevice;
if(!eax_x_ram_check_availability(device, *ALBuf, size)) if(!eax_x_ram_check_availability(device, *ALBuf, size))
SETERR_RETURN(context, AL_OUT_OF_MEMORY,, return context->setError(AL_OUT_OF_MEMORY,
"Out of X-RAM memory (avail: %u, needed: %u)", device.eax_x_ram_free_size, size); "Out of X-RAM memory (avail: %u, needed: %u)", device.eax_x_ram_free_size, size);
} }
#endif #endif
@ -631,6 +631,9 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
} }
newdata.swap(ALBuf->mData); newdata.swap(ALBuf->mData);
} }
#ifdef ALSOFT_EAX
eax_x_ram_clear(*context->mALDevice, *ALBuf);
#endif
if(SrcType == UserFmtIMA4) if(SrcType == UserFmtIMA4)
{ {
@ -683,19 +686,19 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
UserFmtChannels SrcChannels, UserFmtType SrcType, ALBUFFERCALLBACKTYPESOFT callback, UserFmtChannels SrcChannels, UserFmtType SrcType, ALBUFFERCALLBACKTYPESOFT callback,
void *userptr) void *userptr)
{ {
if UNLIKELY(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_OPERATION,, "Modifying callback for in-use buffer %u", return context->setError(AL_INVALID_OPERATION, "Modifying callback for in-use buffer %u",
ALBuf->id); ALBuf->id);
/* Currently no channel configurations need to be converted. */ /* Currently no channel configurations need to be converted. */
auto DstChannels = FmtFromUserFmt(SrcChannels); auto DstChannels = FmtFromUserFmt(SrcChannels);
if UNLIKELY(!DstChannels) if(!DstChannels) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid format"); return context->setError(AL_INVALID_ENUM, "Invalid format");
/* IMA4 and MSADPCM convert to 16-bit short. Not supported with callbacks. */ /* IMA4 and MSADPCM convert to 16-bit short. Not supported with callbacks. */
auto DstType = FmtFromUserFmt(SrcType); auto DstType = FmtFromUserFmt(SrcType);
if UNLIKELY(!DstType) if(!DstType) [[unlikely]]
SETERR_RETURN(context, AL_INVALID_ENUM,, "Unsupported callback format"); return context->setError(AL_INVALID_ENUM, "Unsupported callback format");
const ALuint ambiorder{IsBFormat(*DstChannels) ? ALBuf->UnpackAmbiOrder : const ALuint ambiorder{IsBFormat(*DstChannels) ? ALBuf->UnpackAmbiOrder :
(IsUHJ(*DstChannels) ? 1 : 0)}; (IsUHJ(*DstChannels) ? 1 : 0)};
@ -820,11 +823,11 @@ AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
if UNLIKELY(n < 0) if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Generating %d buffers", n); context->setError(AL_INVALID_VALUE, "Generating %d buffers", n);
if UNLIKELY(n <= 0) return; if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
@ -834,7 +837,7 @@ START_API_FUNC
return; return;
} }
if LIKELY(n == 1) if(n == 1) [[likely]]
{ {
/* Special handling for the easy and normal case. */ /* Special handling for the easy and normal case. */
ALbuffer *buffer{AllocBuffer(device)}; ALbuffer *buffer{AllocBuffer(device)};
@ -860,11 +863,11 @@ AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
if UNLIKELY(n < 0) if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Deleting %d buffers", n); context->setError(AL_INVALID_VALUE, "Deleting %d buffers", n);
if UNLIKELY(n <= 0) return; if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
@ -874,12 +877,12 @@ START_API_FUNC
{ {
if(!bid) return true; if(!bid) return true;
ALbuffer *ALBuf{LookupBuffer(device, bid)}; ALbuffer *ALBuf{LookupBuffer(device, bid)};
if UNLIKELY(!ALBuf) if(!ALBuf) [[unlikely]]
{ {
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", bid); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", bid);
return false; return false;
} }
if UNLIKELY(ReadRef(ALBuf->ref) != 0) if(ReadRef(ALBuf->ref) != 0) [[unlikely]]
{ {
context->setError(AL_INVALID_OPERATION, "Deleting in-use buffer %u", bid); context->setError(AL_INVALID_OPERATION, "Deleting in-use buffer %u", bid);
return false; return false;
@ -888,7 +891,7 @@ START_API_FUNC
}; };
const ALuint *buffers_end = buffers + n; const ALuint *buffers_end = buffers + n;
auto invbuf = std::find_if_not(buffers, buffers_end, validate_buffer); auto invbuf = std::find_if_not(buffers, buffers_end, validate_buffer);
if UNLIKELY(invbuf != buffers_end) return; if(invbuf != buffers_end) [[unlikely]] return;
/* All good. Delete non-0 buffer IDs. */ /* All good. Delete non-0 buffer IDs. */
auto delete_buffer = [device](const ALuint bid) -> void auto delete_buffer = [device](const ALuint bid) -> void
@ -904,7 +907,7 @@ AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if LIKELY(context) if(context) [[likely]]
{ {
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
@ -925,28 +928,28 @@ AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(size < 0) else if(size < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Negative storage size %d", size); context->setError(AL_INVALID_VALUE, "Negative storage size %d", size);
else if UNLIKELY(freq < 1) else if(freq < 1) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq); context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq);
else if UNLIKELY((flags&INVALID_STORAGE_MASK) != 0) else if((flags&INVALID_STORAGE_MASK) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid storage flags 0x%x", context->setError(AL_INVALID_VALUE, "Invalid storage flags 0x%x",
flags&INVALID_STORAGE_MASK); flags&INVALID_STORAGE_MASK);
else if UNLIKELY((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS)) else if((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS)) [[unlikely]]
context->setError(AL_INVALID_VALUE, context->setError(AL_INVALID_VALUE,
"Declaring persistently mapped storage without read or write access"); "Declaring persistently mapped storage without read or write access");
else else
{ {
auto usrfmt = DecomposeUserFormat(format); auto usrfmt = DecomposeUserFormat(format);
if UNLIKELY(!usrfmt) if(!usrfmt) [[unlikely]]
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else else
{ {
@ -961,39 +964,40 @@ AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return nullptr; if(!context) [[unlikely]] return nullptr;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY((access&INVALID_MAP_FLAGS) != 0) else if((access&INVALID_MAP_FLAGS) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid map flags 0x%x", access&INVALID_MAP_FLAGS); context->setError(AL_INVALID_VALUE, "Invalid map flags 0x%x", access&INVALID_MAP_FLAGS);
else if UNLIKELY(!(access&MAP_READ_WRITE_FLAGS)) else if(!(access&MAP_READ_WRITE_FLAGS)) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Mapping buffer %u without read or write access", context->setError(AL_INVALID_VALUE, "Mapping buffer %u without read or write access",
buffer); buffer);
else else
{ {
ALbitfieldSOFT unavailable = (albuf->Access^access) & access; ALbitfieldSOFT unavailable = (albuf->Access^access) & access;
if UNLIKELY(ReadRef(albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) if(ReadRef(albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_OPERATION, context->setError(AL_INVALID_OPERATION,
"Mapping in-use buffer %u without persistent mapping", buffer); "Mapping in-use buffer %u without persistent mapping", buffer);
else if UNLIKELY(albuf->MappedAccess != 0) else if(albuf->MappedAccess != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Mapping already-mapped buffer %u", buffer); context->setError(AL_INVALID_OPERATION, "Mapping already-mapped buffer %u", buffer);
else if UNLIKELY((unavailable&AL_MAP_READ_BIT_SOFT)) else if((unavailable&AL_MAP_READ_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_VALUE, context->setError(AL_INVALID_VALUE,
"Mapping buffer %u for reading without read access", buffer); "Mapping buffer %u for reading without read access", buffer);
else if UNLIKELY((unavailable&AL_MAP_WRITE_BIT_SOFT)) else if((unavailable&AL_MAP_WRITE_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_VALUE, context->setError(AL_INVALID_VALUE,
"Mapping buffer %u for writing without write access", buffer); "Mapping buffer %u for writing without write access", buffer);
else if UNLIKELY((unavailable&AL_MAP_PERSISTENT_BIT_SOFT)) else if((unavailable&AL_MAP_PERSISTENT_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_VALUE, context->setError(AL_INVALID_VALUE,
"Mapping buffer %u persistently without persistent access", buffer); "Mapping buffer %u persistently without persistent access", buffer);
else if UNLIKELY(offset < 0 || length <= 0 else if(offset < 0 || length <= 0
|| static_cast<ALuint>(offset) >= albuf->OriginalSize || static_cast<ALuint>(offset) >= albuf->OriginalSize
|| static_cast<ALuint>(length) > albuf->OriginalSize - static_cast<ALuint>(offset)) || static_cast<ALuint>(length) > albuf->OriginalSize - static_cast<ALuint>(offset))
[[unlikely]]
context->setError(AL_INVALID_VALUE, "Mapping invalid range %d+%d for buffer %u", context->setError(AL_INVALID_VALUE, "Mapping invalid range %d+%d for buffer %u",
offset, length, buffer); offset, length, buffer);
else else
@ -1014,15 +1018,15 @@ AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(albuf->MappedAccess == 0) else if(albuf->MappedAccess == 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer); context->setError(AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer);
else else
{ {
@ -1037,20 +1041,20 @@ AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, A
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)) else if(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Flushing buffer %u while not mapped for writing", context->setError(AL_INVALID_OPERATION, "Flushing buffer %u while not mapped for writing",
buffer); buffer);
else if UNLIKELY(offset < albuf->MappedOffset || length <= 0 else if(offset < albuf->MappedOffset || length <= 0
|| offset >= albuf->MappedOffset+albuf->MappedSize || offset >= albuf->MappedOffset+albuf->MappedSize
|| length > albuf->MappedOffset+albuf->MappedSize-offset) || length > albuf->MappedOffset+albuf->MappedSize-offset) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u", offset, context->setError(AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u", offset,
length, buffer); length, buffer);
else else
@ -1069,20 +1073,20 @@ AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
{ {
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
return; return;
} }
auto usrfmt = DecomposeUserFormat(format); auto usrfmt = DecomposeUserFormat(format);
if UNLIKELY(!usrfmt) if(!usrfmt) [[unlikely]]
{ {
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
return; return;
@ -1090,18 +1094,18 @@ START_API_FUNC
ALuint unpack_align{albuf->UnpackAlign}; ALuint unpack_align{albuf->UnpackAlign};
ALuint align{SanitizeAlignment(usrfmt->type, unpack_align)}; ALuint align{SanitizeAlignment(usrfmt->type, unpack_align)};
if UNLIKELY(align < 1) if(align < 1) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u", unpack_align); context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u", unpack_align);
else if UNLIKELY(long{usrfmt->channels} != long{albuf->mChannels} else if(al::to_underlying(usrfmt->channels) != al::to_underlying(albuf->mChannels)
|| usrfmt->type != albuf->OriginalType) || usrfmt->type != albuf->OriginalType) [[unlikely]]
context->setError(AL_INVALID_ENUM, "Unpacking data with mismatched format"); context->setError(AL_INVALID_ENUM, "Unpacking data with mismatched format");
else if UNLIKELY(align != albuf->OriginalAlign) else if(align != albuf->OriginalAlign) [[unlikely]]
context->setError(AL_INVALID_VALUE, context->setError(AL_INVALID_VALUE,
"Unpacking data with alignment %u does not match original alignment %u", align, "Unpacking data with alignment %u does not match original alignment %u", align,
albuf->OriginalAlign); albuf->OriginalAlign);
else if UNLIKELY(albuf->isBFormat() && albuf->UnpackAmbiOrder != albuf->mAmbiOrder) else if(albuf->isBFormat() && albuf->UnpackAmbiOrder != albuf->mAmbiOrder) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Unpacking data with mismatched ambisonic order"); context->setError(AL_INVALID_VALUE, "Unpacking data with mismatched ambisonic order");
else if UNLIKELY(albuf->MappedAccess != 0) else if(albuf->MappedAccess != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u", buffer); context->setError(AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u", buffer);
else else
{ {
@ -1113,15 +1117,16 @@ START_API_FUNC
(align * frame_size) (align * frame_size)
}; };
if UNLIKELY(offset < 0 || length < 0 || static_cast<ALuint>(offset) > albuf->OriginalSize if(offset < 0 || length < 0 || static_cast<ALuint>(offset) > albuf->OriginalSize
|| static_cast<ALuint>(length) > albuf->OriginalSize-static_cast<ALuint>(offset)) || static_cast<ALuint>(length) > albuf->OriginalSize-static_cast<ALuint>(offset))
[[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid data sub-range %d+%d on buffer %u", context->setError(AL_INVALID_VALUE, "Invalid data sub-range %d+%d on buffer %u",
offset, length, buffer); offset, length, buffer);
else if UNLIKELY((static_cast<ALuint>(offset)%byte_align) != 0) else if((static_cast<ALuint>(offset)%byte_align) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, context->setError(AL_INVALID_VALUE,
"Sub-range offset %d is not a multiple of frame size %d (%d unpack alignment)", "Sub-range offset %d is not a multiple of frame size %d (%d unpack alignment)",
offset, byte_align, align); offset, byte_align, align);
else if UNLIKELY((static_cast<ALuint>(length)%byte_align) != 0) else if((static_cast<ALuint>(length)%byte_align) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, context->setError(AL_INVALID_VALUE,
"Sub-range length %d is not a multiple of frame size %d (%d unpack alignment)", "Sub-range length %d is not a multiple of frame size %d (%d unpack alignment)",
length, byte_align, align); length, byte_align, align);
@ -1140,7 +1145,7 @@ START_API_FUNC
static_cast<const al::byte*>(data), num_chans, samplen, align); static_cast<const al::byte*>(data), num_chans, samplen, align);
else else
{ {
assert(long{usrfmt->type} == long{albuf->mType}); assert(al::to_underlying(usrfmt->type) == al::to_underlying(albuf->mType));
memcpy(dst, data, size_t{samplen} * frame_size); memcpy(dst, data, size_t{samplen} * frame_size);
} }
} }
@ -1155,7 +1160,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint /*buffer*/, ALuint /*samplera
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported"); context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported");
} }
@ -1166,7 +1171,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint /*buffer*/, ALsizei /*offs
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported"); context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported");
} }
@ -1177,7 +1182,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint /*buffer*/, ALsizei /*offs
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported"); context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported");
} }
@ -1187,7 +1192,7 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return AL_FALSE; if(!context) [[unlikely]] return AL_FALSE;
context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported"); context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported");
return AL_FALSE; return AL_FALSE;
@ -1199,12 +1204,12 @@ AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat /*value*/
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param) else switch(param)
{ {
@ -1219,12 +1224,12 @@ AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param,
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param) else switch(param)
{ {
@ -1238,14 +1243,14 @@ AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *v
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values) else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1260,52 +1265,53 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param) else switch(param)
{ {
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
if UNLIKELY(value < 0) if(value < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack block alignment %d", value); context->setError(AL_INVALID_VALUE, "Invalid unpack block alignment %d", value);
else else
albuf->UnpackAlign = static_cast<ALuint>(value); albuf->UnpackAlign = static_cast<ALuint>(value);
break; break;
case AL_PACK_BLOCK_ALIGNMENT_SOFT: case AL_PACK_BLOCK_ALIGNMENT_SOFT:
if UNLIKELY(value < 0) if(value < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid pack block alignment %d", value); context->setError(AL_INVALID_VALUE, "Invalid pack block alignment %d", value);
else else
albuf->PackAlign = static_cast<ALuint>(value); albuf->PackAlign = static_cast<ALuint>(value);
break; break;
case AL_AMBISONIC_LAYOUT_SOFT: case AL_AMBISONIC_LAYOUT_SOFT:
if UNLIKELY(ReadRef(albuf->ref) != 0) if(ReadRef(albuf->ref) != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic layout", context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic layout",
buffer); buffer);
else if UNLIKELY(value != AL_FUMA_SOFT && value != AL_ACN_SOFT) else if(value != AL_FUMA_SOFT && value != AL_ACN_SOFT) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic layout %04x", value); context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic layout %04x", value);
else else
albuf->mAmbiLayout = AmbiLayoutFromEnum(value).value(); albuf->mAmbiLayout = AmbiLayoutFromEnum(value).value();
break; break;
case AL_AMBISONIC_SCALING_SOFT: case AL_AMBISONIC_SCALING_SOFT:
if UNLIKELY(ReadRef(albuf->ref) != 0) if(ReadRef(albuf->ref) != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic scaling", context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic scaling",
buffer); buffer);
else if UNLIKELY(value != AL_FUMA_SOFT && value != AL_SN3D_SOFT && value != AL_N3D_SOFT) else if(value != AL_FUMA_SOFT && value != AL_SN3D_SOFT && value != AL_N3D_SOFT)
[[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic scaling %04x", value); context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic scaling %04x", value);
else else
albuf->mAmbiScaling = AmbiScalingFromEnum(value).value(); albuf->mAmbiScaling = AmbiScalingFromEnum(value).value();
break; break;
case AL_UNPACK_AMBISONIC_ORDER_SOFT: case AL_UNPACK_AMBISONIC_ORDER_SOFT:
if UNLIKELY(value < 1 || value > 14) if(value < 1 || value > 14) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic order %d", value); context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic order %d", value);
else else
albuf->UnpackAmbiOrder = static_cast<ALuint>(value); albuf->UnpackAmbiOrder = static_cast<ALuint>(value);
@ -1322,12 +1328,12 @@ AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param,
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param) else switch(param)
{ {
@ -1355,24 +1361,24 @@ START_API_FUNC
} }
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values) else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
case AL_LOOP_POINTS_SOFT: case AL_LOOP_POINTS_SOFT:
if UNLIKELY(ReadRef(albuf->ref) != 0) if(ReadRef(albuf->ref) != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points", context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points",
buffer); buffer);
else if UNLIKELY(values[0] < 0 || values[0] >= values[1] else if(values[0] < 0 || values[0] >= values[1]
|| static_cast<ALuint>(values[1]) > albuf->mSampleLen) || static_cast<ALuint>(values[1]) > albuf->mSampleLen) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid loop point range %d -> %d on buffer %u", context->setError(AL_INVALID_VALUE, "Invalid loop point range %d -> %d on buffer %u",
values[0], values[1], buffer); values[0], values[1], buffer);
else else
@ -1393,15 +1399,15 @@ AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value) else if(!value) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1415,14 +1421,14 @@ AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *valu
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value1 || !value2 || !value3) else if(!value1 || !value2 || !value3) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1443,14 +1449,14 @@ START_API_FUNC
} }
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values) else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1465,14 +1471,14 @@ AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value) else if(!value) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1522,13 +1528,13 @@ AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value1 || !value2 || !value3) else if(!value1 || !value2 || !value3) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1560,14 +1566,14 @@ START_API_FUNC
} }
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values) else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1588,22 +1594,22 @@ AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsiz
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(freq < 1) else if(freq < 1) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq); context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq);
else if UNLIKELY(callback == nullptr) else if(callback == nullptr) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL callback"); context->setError(AL_INVALID_VALUE, "NULL callback");
else else
{ {
auto usrfmt = DecomposeUserFormat(format); auto usrfmt = DecomposeUserFormat(format);
if UNLIKELY(!usrfmt) if(!usrfmt) [[unlikely]]
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else else
PrepareCallback(context.get(), albuf, freq, usrfmt->channels, usrfmt->type, callback, PrepareCallback(context.get(), albuf, freq, usrfmt->channels, usrfmt->type, callback,
@ -1616,14 +1622,14 @@ AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid *
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer); ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf) if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value) else if(!value) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1644,13 +1650,13 @@ AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value1 || !value2 || !value3) else if(!value1 || !value2 || !value3) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1672,13 +1678,13 @@ START_API_FUNC
} }
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock}; std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr) if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values) else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer"); context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param) else switch(param)
{ {
@ -1763,7 +1769,7 @@ START_API_FUNC
continue; continue;
const auto al_buffer = LookupBuffer(device, buffer); const auto al_buffer = LookupBuffer(device, buffer);
if (!al_buffer) if(!al_buffer) [[unlikely]]
{ {
ERR(EAX_PREFIX "Invalid buffer ID %u.\n", buffer); ERR(EAX_PREFIX "Invalid buffer ID %u.\n", buffer);
return ALC_FALSE; return ALC_FALSE;
@ -1779,7 +1785,7 @@ START_API_FUNC
* buffer ID is specified multiple times in the provided list, it * buffer ID is specified multiple times in the provided list, it
* counts each instance as more memory that needs to fit in X-RAM. * counts each instance as more memory that needs to fit in X-RAM.
*/ */
if(unlikely(std::numeric_limits<size_t>::max()-al_buffer->OriginalSize < total_needed)) if(std::numeric_limits<size_t>::max()-al_buffer->OriginalSize < total_needed) [[unlikely]]
{ {
context->setError(AL_OUT_OF_MEMORY, EAX_PREFIX "Buffer size overflow (%u + %zu)\n", context->setError(AL_OUT_OF_MEMORY, EAX_PREFIX "Buffer size overflow (%u + %zu)\n",
al_buffer->OriginalSize, total_needed); al_buffer->OriginalSize, total_needed);

View File

@ -269,7 +269,8 @@ const GUID EAX_RINGMODULATOR_EFFECT =
}; };
const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0; const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0;
const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX50_FXSlot0;
const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX40ACTIVEFXSLOTS const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX40ACTIVEFXSLOTS
{{ {{

View File

@ -28,11 +28,14 @@ typedef struct _GUID {
std::uint8_t Data4[8]; std::uint8_t Data4[8];
} GUID; } GUID;
#ifndef _SYS_GUID_OPERATOR_EQ_
#define _SYS_GUID_OPERATOR_EQ_
inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept
{ return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; } { return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; }
inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept
{ return !(lhs == rhs); } { return !(lhs == rhs); }
#endif // _SYS_GUID_OPERATOR_EQ_
#endif // GUID_DEFINED #endif // GUID_DEFINED
@ -287,21 +290,19 @@ extern const GUID EAXPROPERTYID_EAX40_Context;
extern const GUID EAXPROPERTYID_EAX50_Context; extern const GUID EAXPROPERTYID_EAX50_Context;
// EAX50 // EAX50
enum : unsigned long constexpr auto HEADPHONES = 0UL;
{ constexpr auto SPEAKERS_2 = 1UL;
HEADPHONES = 0, constexpr auto SPEAKERS_4 = 2UL;
SPEAKERS_2, constexpr auto SPEAKERS_5 = 3UL; // 5.1 speakers
SPEAKERS_4, constexpr auto SPEAKERS_6 = 4UL; // 6.1 speakers
SPEAKERS_5, // 5.1 speakers constexpr auto SPEAKERS_7 = 5UL; // 7.1 speakers
SPEAKERS_6, // 6.1 speakers
SPEAKERS_7, // 7.1 speakers constexpr auto EAXCONTEXT_MINSPEAKERCONFIG = HEADPHONES;
}; constexpr auto EAXCONTEXT_MAXSPEAKERCONFIG = SPEAKERS_7;
// EAX50 // EAX50
enum : unsigned long { constexpr auto EAX_40 = 5UL; // EAX 4.0
EAX_40 = 5, // EAX 4.0 constexpr auto EAX_50 = 6UL; // EAX 5.0
EAX_50 = 6, // EAX 5.0
};
constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40; constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40;
constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50; constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50;
@ -370,7 +371,8 @@ extern const GUID EAXPROPERTYID_EAX50_FXSlot2;
extern const GUID EAXPROPERTYID_EAX40_FXSlot3; extern const GUID EAXPROPERTYID_EAX40_FXSlot3;
extern const GUID EAXPROPERTYID_EAX50_FXSlot3; extern const GUID EAXPROPERTYID_EAX50_FXSlot3;
extern const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID; extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID;
extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID;
enum EAXFXSLOT_PROPERTY : unsigned int { enum EAXFXSLOT_PROPERTY : unsigned int {
EAXFXSLOT_PARAMETER = 0, EAXFXSLOT_PARAMETER = 0,

View File

@ -23,6 +23,7 @@ EaxCall::EaxCall(
ALvoid* property_buffer, ALvoid* property_buffer,
ALuint property_size) ALuint property_size)
: type_{type}, version_{0}, property_set_id_{EaxCallPropertySetId::none} : type_{type}, version_{0}, property_set_id_{EaxCallPropertySetId::none}
, is_deferred_{(property_id & deferred_flag) != 0}
, property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id}
, property_buffer_{property_buffer}, property_size_{property_size} , property_buffer_{property_buffer}, property_size_{property_size}
{ {
@ -150,7 +151,28 @@ EaxCall::EaxCall(
fail("EAX version out of range."); fail("EAX version out of range.");
} }
if(!(property_id&deferred_flag)) switch(property_id)
{
case EAXCONTEXT_LASTERROR:
case EAXCONTEXT_SPEAKERCONFIG:
case EAXCONTEXT_EAXSESSION:
case EAXFXSLOT_NONE:
case EAXFXSLOT_ALLPARAMETERS:
case EAXFXSLOT_LOADEFFECT:
case EAXFXSLOT_VOLUME:
case EAXFXSLOT_LOCK:
case EAXFXSLOT_FLAGS:
case EAXFXSLOT_OCCLUSION:
case EAXFXSLOT_OCCLUSIONLFRATIO:
// EAX allow to set "defer" flag on immediate-only properties.
// If we don't clear our flag then "applyAllUpdates" in EAX context won't be called.
is_deferred_ = false;
break;
default:
break;
}
if(!is_deferred_)
{ {
if(property_set_id_ != EaxCallPropertySetId::fx_slot && property_id_ != 0) if(property_set_id_ != EaxCallPropertySetId::fx_slot && property_id_ != 0)
{ {

View File

@ -32,6 +32,7 @@ public:
ALuint property_size); ALuint property_size);
bool is_get() const noexcept { return type_ == EaxCallType::get; } bool is_get() const noexcept { return type_ == EaxCallType::get; }
bool is_deferred() const noexcept { return is_deferred_; }
int get_version() const noexcept { return version_; } int get_version() const noexcept { return version_; }
EaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } EaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; }
ALuint get_property_id() const noexcept { return property_id_; } ALuint get_property_id() const noexcept { return property_id_; }
@ -76,6 +77,7 @@ private:
int version_; int version_;
EaxFxSlotIndex fx_slot_index_; EaxFxSlotIndex fx_slot_index_;
EaxCallPropertySetId property_set_id_; EaxCallPropertySetId property_set_id_;
bool is_deferred_;
ALuint property_id_; ALuint property_id_;
ALuint property_source_id_; ALuint property_source_id_;

View File

@ -35,8 +35,8 @@ template<typename TException, typename TProps>
class EaxEffect4 : public EaxEffect class EaxEffect4 : public EaxEffect
{ {
public: public:
EaxEffect4(ALenum type, const EaxCall& call) EaxEffect4(ALenum type, int eax_version)
: EaxEffect{type}, version_{clamp(call.get_version(), 4, 5)} : EaxEffect{type}, version_{clamp(eax_version, 4, 5)}
{} {}
void initialize() void initialize()
@ -70,10 +70,10 @@ protected:
Props d; // Deferred. Props d; // Deferred.
}; // State }; // State
int version_; int version_{};
Props props_; Props props_{};
State state4_; State state4_{};
State state5_; State state5_{};
template<typename TValidator, typename TProperty> template<typename TValidator, typename TProperty>
static void defer(const EaxCall& call, TProperty& property) static void defer(const EaxCall& call, TProperty& property)
@ -149,25 +149,25 @@ using EaxEffectUPtr = std::unique_ptr<EaxEffect>;
// Creates EAX4+ effect. // Creates EAX4+ effect.
template<typename TEffect> template<typename TEffect>
EaxEffectUPtr eax_create_eax4_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax4_effect(int eax_version)
{ {
auto effect = std::make_unique<TEffect>(call); auto effect = std::make_unique<TEffect>(eax_version);
effect->initialize(); effect->initialize();
return effect; return effect;
} }
EaxEffectUPtr eax_create_eax_null_effect(); EaxEffectUPtr eax_create_eax_null_effect();
EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version);
EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version);
EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_echo_effect(int eax_version);
EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_flanger_effect(int eax_version);
EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_frequency_shifter_effect(int eax_version);
EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_vocal_morpher_effect(int eax_version);
EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_pitch_shifter_effect(int eax_version);
EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_ring_modulator_effect(int eax_version);
EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version);
EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_compressor_effect(int eax_version);
EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_equalizer_effect(int eax_version);
EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call); EaxEffectUPtr eax_create_eax_reverb_effect(int eax_version);
#endif // !EAX_EFFECT_INCLUDED #endif // !EAX_EFFECT_INCLUDED

View File

@ -6,17 +6,14 @@
#include <string> #include <string>
EaxException::EaxException( EaxException::EaxException(const char *context, const char *message)
const char* context, : std::runtime_error{make_message(context, message)}
const char* message)
:
std::runtime_error{make_message(context, message)}
{ {
} }
EaxException::~EaxException() = default;
std::string EaxException::make_message(
const char* context, std::string EaxException::make_message(const char *context, const char *message)
const char* message)
{ {
const auto context_size = (context ? std::string::traits_type::length(context) : 0); const auto context_size = (context ? std::string::traits_type::length(context) : 0);
const auto has_contex = (context_size > 0); const auto has_contex = (context_size > 0);

View File

@ -6,19 +6,12 @@
#include <string> #include <string>
class EaxException : class EaxException : public std::runtime_error {
public std::runtime_error static std::string make_message(const char *context, const char *message);
{
public: public:
EaxException( EaxException(const char *context, const char *message);
const char* context, ~EaxException() override;
const char* message);
private:
static std::string make_message(
const char* context,
const char* message);
}; // EaxException }; // EaxException

View File

@ -28,11 +28,9 @@ public:
} // namespace } // namespace
void EaxFxSlots::initialize( void EaxFxSlots::initialize(ALCcontext& al_context)
const EaxCall& call,
ALCcontext& al_context)
{ {
initialize_fx_slots(call, al_context); initialize_fx_slots(al_context);
} }
void EaxFxSlots::uninitialize() noexcept void EaxFxSlots::uninitialize() noexcept
@ -57,12 +55,6 @@ ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index)
return *fx_slots_[index.value()]; return *fx_slots_[index.value()];
} }
void EaxFxSlots::unlock_legacy() noexcept
{
fx_slots_[0]->eax_unlock_legacy();
fx_slots_[1]->eax_unlock_legacy();
}
[[noreturn]] [[noreturn]]
void EaxFxSlots::fail( void EaxFxSlots::fail(
const char* message) const char* message)
@ -70,16 +62,14 @@ void EaxFxSlots::fail(
throw EaxFxSlotsException{message}; throw EaxFxSlotsException{message};
} }
void EaxFxSlots::initialize_fx_slots( void EaxFxSlots::initialize_fx_slots(ALCcontext& al_context)
const EaxCall& call,
ALCcontext& al_context)
{ {
auto fx_slot_index = EaxFxSlotIndexValue{}; auto fx_slot_index = EaxFxSlotIndexValue{};
for (auto& fx_slot : fx_slots_) for (auto& fx_slot : fx_slots_)
{ {
fx_slot = eax_create_al_effect_slot(al_context); fx_slot = eax_create_al_effect_slot(al_context);
fx_slot->eax_initialize(call, al_context, fx_slot_index); fx_slot->eax_initialize(al_context, fx_slot_index);
fx_slot_index += 1; fx_slot_index += 1;
} }
} }

View File

@ -14,9 +14,7 @@
class EaxFxSlots class EaxFxSlots
{ {
public: public:
void initialize( void initialize(ALCcontext& al_context);
const EaxCall& call,
ALCcontext& al_context);
void uninitialize() noexcept; void uninitialize() noexcept;
@ -33,9 +31,6 @@ public:
ALeffectslot& get( ALeffectslot& get(
EaxFxSlotIndex index); EaxFxSlotIndex index);
void unlock_legacy() noexcept;
private: private:
using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>; using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>;
@ -47,9 +42,7 @@ private:
static void fail( static void fail(
const char* message); const char* message);
void initialize_fx_slots( void initialize_fx_slots(ALCcontext& al_context);
const EaxCall& call,
ALCcontext& al_context);
}; // EaxFxSlots }; // EaxFxSlots

View File

@ -8,29 +8,19 @@
#include "core/logging.h" #include "core/logging.h"
void eax_log_exception( void eax_log_exception(const char *message) noexcept
const char* message) noexcept
{ {
const auto exception_ptr = std::current_exception(); const auto exception_ptr = std::current_exception();
assert(exception_ptr); assert(exception_ptr);
if (message) try {
{
ERR("%s\n", message);
}
try
{
std::rethrow_exception(exception_ptr); std::rethrow_exception(exception_ptr);
} }
catch (const std::exception& ex) catch(const std::exception& ex) {
{
const auto ex_message = ex.what(); const auto ex_message = ex.what();
ERR("%s\n", ex_message); ERR("%s %s\n", message ? message : "", ex_message);
} }
catch (...) catch(...) {
{ ERR("%s %s\n", message ? message : "", "Generic exception.");
ERR("%s\n", "Generic exception.");
} }
} }

View File

@ -6,12 +6,14 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
using EaxDirtyFlags = unsigned int;
struct EaxAlLowPassParam { struct EaxAlLowPassParam {
float gain; float gain;
float gain_hf; float gain_hf;
}; };
void eax_log_exception(const char* message = nullptr) noexcept; void eax_log_exception(const char *message) noexcept;
template<typename TException, typename TValue> template<typename TException, typename TValue>
void eax_validate_range( void eax_validate_range(

View File

@ -86,6 +86,7 @@ effect_exception::effect_exception(ALenum code, const char *msg, ...) : mErrorCo
setMessage(msg, args); setMessage(msg, args);
va_end(args); va_end(args);
} }
effect_exception::~effect_exception() = default;
namespace { namespace {
@ -139,7 +140,7 @@ const EffectPropsItem *getEffectPropsItemByType(ALenum type)
auto iter = std::find_if(std::begin(EffectPropsList), std::end(EffectPropsList), auto iter = std::find_if(std::begin(EffectPropsList), std::end(EffectPropsList),
[type](const EffectPropsItem &item) noexcept -> bool [type](const EffectPropsItem &item) noexcept -> bool
{ return item.Type == type; }); { return item.Type == type; });
return (iter != std::end(EffectPropsList)) ? std::addressof(*iter) : nullptr; return (iter != std::end(EffectPropsList)) ? al::to_address(iter) : nullptr;
} }
void InitEffectParams(ALeffect *effect, ALenum type) void InitEffectParams(ALeffect *effect, ALenum type)
@ -166,14 +167,14 @@ bool EnsureEffects(ALCdevice *device, size_t needed)
while(needed > count) while(needed > count)
{ {
if UNLIKELY(device->EffectList.size() >= 1<<25) if(device->EffectList.size() >= 1<<25) [[unlikely]]
return false; return false;
device->EffectList.emplace_back(); device->EffectList.emplace_back();
auto sublist = device->EffectList.end() - 1; auto sublist = device->EffectList.end() - 1;
sublist->FreeMask = ~0_u64; sublist->FreeMask = ~0_u64;
sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64)); sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64));
if UNLIKELY(!sublist->Effects) if(!sublist->Effects) [[unlikely]]
{ {
device->EffectList.pop_back(); device->EffectList.pop_back();
return false; return false;
@ -219,10 +220,10 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
const size_t lidx{(id-1) >> 6}; const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f}; const ALuint slidx{(id-1) & 0x3f};
if UNLIKELY(lidx >= device->EffectList.size()) if(lidx >= device->EffectList.size()) [[unlikely]]
return nullptr; return nullptr;
EffectSubList &sublist = device->EffectList[lidx]; EffectSubList &sublist = device->EffectList[lidx];
if UNLIKELY(sublist.FreeMask & (1_u64 << slidx)) if(sublist.FreeMask & (1_u64 << slidx)) [[unlikely]]
return nullptr; return nullptr;
return sublist.Effects + slidx; return sublist.Effects + slidx;
} }
@ -233,11 +234,11 @@ AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
if UNLIKELY(n < 0) if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Generating %d effects", n); context->setError(AL_INVALID_VALUE, "Generating %d effects", n);
if UNLIKELY(n <= 0) return; if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
@ -247,7 +248,7 @@ START_API_FUNC
return; return;
} }
if LIKELY(n == 1) if(n == 1) [[likely]]
{ {
/* Special handling for the easy and normal case. */ /* Special handling for the easy and normal case. */
ALeffect *effect{AllocEffect(device)}; ALeffect *effect{AllocEffect(device)};
@ -273,11 +274,11 @@ AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
if UNLIKELY(n < 0) if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Deleting %d effects", n); context->setError(AL_INVALID_VALUE, "Deleting %d effects", n);
if UNLIKELY(n <= 0) return; if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
@ -288,7 +289,7 @@ START_API_FUNC
const ALuint *effects_end = effects + n; const ALuint *effects_end = effects + n;
auto inveffect = std::find_if_not(effects, effects_end, validate_effect); auto inveffect = std::find_if_not(effects, effects_end, validate_effect);
if UNLIKELY(inveffect != effects_end) if(inveffect != effects_end) [[unlikely]]
{ {
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect);
return; return;
@ -308,7 +309,7 @@ AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if LIKELY(context) if(context) [[likely]]
{ {
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
@ -323,13 +324,13 @@ AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)}; ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else if(param == AL_EFFECT_TYPE) else if(param == AL_EFFECT_TYPE)
{ {
@ -373,13 +374,13 @@ START_API_FUNC
} }
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)}; ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try else try
{ {
@ -396,13 +397,13 @@ AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)}; ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try else try
{ {
@ -419,13 +420,13 @@ AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *v
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)}; ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try else try
{ {
@ -442,13 +443,13 @@ AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)}; const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else if(param == AL_EFFECT_TYPE) else if(param == AL_EFFECT_TYPE)
*value = aleffect->type; *value = aleffect->type;
@ -474,13 +475,13 @@ START_API_FUNC
} }
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)}; const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try else try
{ {
@ -497,13 +498,13 @@ AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)}; const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try else try
{ {
@ -520,13 +521,13 @@ AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *valu
START_API_FUNC START_API_FUNC
{ {
ContextRef context{GetContextRef()}; ContextRef context{GetContextRef()};
if UNLIKELY(!context) return; if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()}; ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock}; std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)}; const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect) if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try else try
{ {

View File

@ -127,7 +127,7 @@ public:
class EaxAutoWahEffect final : public EaxEffect4<EaxAutoWahEffectException, EAXAUTOWAHPROPERTIES> { class EaxAutoWahEffect final : public EaxEffect4<EaxAutoWahEffectException, EAXAUTOWAHPROPERTIES> {
public: public:
EaxAutoWahEffect(const EaxCall& call); EaxAutoWahEffect(int eax_version);
private: private:
struct AttackTimeValidator { struct AttackTimeValidator {
@ -197,8 +197,8 @@ private:
bool commit_props(const Props& props) override; bool commit_props(const Props& props) override;
}; // EaxAutoWahEffect }; // EaxAutoWahEffect
EaxAutoWahEffect::EaxAutoWahEffect(const EaxCall& call) EaxAutoWahEffect::EaxAutoWahEffect(int eax_version)
: EaxEffect4{AL_EFFECT_AUTOWAH, call} : EaxEffect4{AL_EFFECT_AUTOWAH, eax_version}
{} {}
void EaxAutoWahEffect::set_defaults(Props& props) void EaxAutoWahEffect::set_defaults(Props& props)
@ -310,9 +310,9 @@ bool EaxAutoWahEffect::commit_props(const Props& props)
} // namespace } // namespace
EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version)
{ {
return eax_create_eax4_effect<EaxAutoWahEffect>(call); return eax_create_eax4_effect<EaxAutoWahEffect>(eax_version);
} }
#endif // ALSOFT_EAX #endif // ALSOFT_EAX

View File

@ -31,8 +31,8 @@ inline al::optional<ChorusWaveform> WaveformFromEnum(ALenum type)
{ {
switch(type) switch(type)
{ {
case AL_CHORUS_WAVEFORM_SINUSOID: return al::make_optional(ChorusWaveform::Sinusoid); case AL_CHORUS_WAVEFORM_SINUSOID: return ChorusWaveform::Sinusoid;
case AL_CHORUS_WAVEFORM_TRIANGLE: return al::make_optional(ChorusWaveform::Triangle); case AL_CHORUS_WAVEFORM_TRIANGLE: return ChorusWaveform::Triangle;
} }
return al::nullopt; return al::nullopt;
} }
@ -149,7 +149,7 @@ void Chorus_getParamf(const EffectProps *props, ALenum param, float *val)
void Chorus_getParamfv(const EffectProps *props, ALenum param, float *vals) void Chorus_getParamfv(const EffectProps *props, ALenum param, float *vals)
{ Chorus_getParamf(props, param, vals); } { Chorus_getParamf(props, param, vals); }
const EffectProps genDefaultChorusProps() noexcept EffectProps genDefaultChorusProps() noexcept
{ {
EffectProps props{}; EffectProps props{};
props.Chorus.Waveform = *WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM); props.Chorus.Waveform = *WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM);
@ -433,8 +433,8 @@ public:
using typename Base::State; using typename Base::State;
using Base::defer; using Base::defer;
EaxChorusFlangerEffect(const EaxCall& call) EaxChorusFlangerEffect(int eax_version)
: Base{Traits::efx_effect(), call} : Base{Traits::efx_effect(), eax_version}
{} {}
private: private:
@ -712,23 +712,23 @@ private:
}; // EaxChorusFlangerEffect }; // EaxChorusFlangerEffect
template<typename TTraits> template<typename TTraits>
EaxEffectUPtr eax_create_eax_chorus_flanger_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax_chorus_flanger_effect(int eax_version)
{ {
return eax_create_eax4_effect<EaxChorusFlangerEffect<TTraits>>(call); return eax_create_eax4_effect<EaxChorusFlangerEffect<TTraits>>(eax_version);
} }
} // namespace } // namespace
// ========================================================================== // ==========================================================================
EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version)
{ {
return eax_create_eax_chorus_flanger_effect<EaxChorusTraits>(call); return eax_create_eax_chorus_flanger_effect<EaxChorusTraits>(eax_version);
} }
EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax_flanger_effect(int eax_version)
{ {
return eax_create_eax_chorus_flanger_effect<EaxFlangerTraits>(call); return eax_create_eax_chorus_flanger_effect<EaxFlangerTraits>(eax_version);
} }
#endif // ALSOFT_EAX #endif // ALSOFT_EAX

View File

@ -91,7 +91,7 @@ public:
class EaxCompressorEffect final : public EaxEffect4<EaxCompressorEffectException, EAXAGCCOMPRESSORPROPERTIES> class EaxCompressorEffect final : public EaxEffect4<EaxCompressorEffectException, EAXAGCCOMPRESSORPROPERTIES>
{ {
public: public:
EaxCompressorEffect(const EaxCall& call); EaxCompressorEffect(int eax_version);
private: private:
struct OnOffValidator { struct OnOffValidator {
@ -122,8 +122,8 @@ private:
bool commit_props(const Props& props) override; bool commit_props(const Props& props) override;
}; // EaxCompressorEffect }; // EaxCompressorEffect
EaxCompressorEffect::EaxCompressorEffect(const EaxCall& call) EaxCompressorEffect::EaxCompressorEffect(int eax_version)
: EaxEffect4{AL_EFFECT_COMPRESSOR, call} : EaxEffect4{AL_EFFECT_COMPRESSOR, eax_version}
{} {}
void EaxCompressorEffect::set_defaults(Props& props) void EaxCompressorEffect::set_defaults(Props& props)
@ -182,9 +182,9 @@ bool EaxCompressorEffect::commit_props(const Props& props)
} // namespace } // namespace
EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax_compressor_effect(int eax_version)
{ {
return eax_create_eax4_effect<EaxCompressorEffect>(call); return eax_create_eax4_effect<EaxCompressorEffect>(eax_version);
} }
#endif // ALSOFT_EAX #endif // ALSOFT_EAX

View File

@ -133,7 +133,7 @@ public:
class EaxDistortionEffect final : public EaxEffect4<EaxDistortionEffectException, EAXDISTORTIONPROPERTIES> class EaxDistortionEffect final : public EaxEffect4<EaxDistortionEffectException, EAXDISTORTIONPROPERTIES>
{ {
public: public:
EaxDistortionEffect(const EaxCall& call); EaxDistortionEffect(int eax_version);
private: private:
struct EdgeValidator { struct EdgeValidator {
@ -216,8 +216,8 @@ private:
bool commit_props(const Props& props) override; bool commit_props(const Props& props) override;
}; // EaxDistortionEffect }; // EaxDistortionEffect
EaxDistortionEffect::EaxDistortionEffect(const EaxCall& call) EaxDistortionEffect::EaxDistortionEffect(int eax_version)
: EaxEffect4{AL_EFFECT_DISTORTION, call} : EaxEffect4{AL_EFFECT_DISTORTION, eax_version}
{} {}
void EaxDistortionEffect::set_defaults(Props& props) void EaxDistortionEffect::set_defaults(Props& props)
@ -347,9 +347,9 @@ bool EaxDistortionEffect::commit_props(const Props& props)
} // namespace } // namespace
EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version)
{ {
return eax_create_eax4_effect<EaxDistortionEffect>(call); return eax_create_eax4_effect<EaxDistortionEffect>(eax_version);
} }
#endif // ALSOFT_EAX #endif // ALSOFT_EAX

View File

@ -130,7 +130,7 @@ public:
class EaxEchoEffect final : public EaxEffect4<EaxEchoEffectException, EAXECHOPROPERTIES> class EaxEchoEffect final : public EaxEffect4<EaxEchoEffectException, EAXECHOPROPERTIES>
{ {
public: public:
EaxEchoEffect(const EaxCall& call); EaxEchoEffect(int eax_version);
private: private:
struct DelayValidator { struct DelayValidator {
@ -213,8 +213,8 @@ private:
bool commit_props(const Props& props) override; bool commit_props(const Props& props) override;
}; // EaxEchoEffect }; // EaxEchoEffect
EaxEchoEffect::EaxEchoEffect(const EaxCall& call) EaxEchoEffect::EaxEchoEffect(int eax_version)
: EaxEffect4{AL_EFFECT_ECHO, call} : EaxEffect4{AL_EFFECT_ECHO, eax_version}
{} {}
void EaxEchoEffect::set_defaults(Props& props) void EaxEchoEffect::set_defaults(Props& props)
@ -344,9 +344,9 @@ bool EaxEchoEffect::commit_props(const Props& props)
} // namespace } // namespace
EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call) EaxEffectUPtr eax_create_eax_echo_effect(int eax_version)
{ {
return eax_create_eax4_effect<EaxEchoEffect>(call); return eax_create_eax4_effect<EaxEchoEffect>(eax_version);
} }
#endif // ALSOFT_EAX #endif // ALSOFT_EAX

Some files were not shown because too many files have changed in this diff Show More