diff --git a/include/bx/bx.h b/include/bx/bx.h index 36f40aa..63d726e 100644 --- a/include/bx/bx.h +++ b/include/bx/bx.h @@ -31,10 +31,13 @@ namespace bx { + /// Used to return successful execution of a program code. constexpr int32_t kExitSuccess = 0; + + /// Used to return unsuccessful execution of a program code. constexpr int32_t kExitFailure = 1; - /// + /// Returns true if type `Ty` is trivially copyable / POD type. template constexpr bool isTriviallyCopyable(); @@ -42,6 +45,10 @@ namespace bx template Ty* addressOf(Ty& _a); + /// Find the address of an object of a class that has an overloaded unary ampersand (&) operator. + template + const Ty* addressOf(const Ty& _a); + /// Swap two values. template void swap(Ty& _a, Ty& _b); @@ -57,23 +64,23 @@ namespace bx template constexpr Ty max(const Ty& _a, const Ty& _b); - /// Returns minimum of three values. - template - constexpr Ty min(const Ty& _a, const Ty& _b, const Ty& _c); + /// Returns minimum of three or more values. + template + constexpr Ty min(const Ty& _a, const Ty& _b, const Args&... _args); - /// Returns maximum of three values. - template - constexpr Ty max(const Ty& _a, const Ty& _b, const Ty& _c); + /// Returns maximum of three or more values. + template + constexpr Ty max(const Ty& _a, const Ty& _b, const Args&... _args); - /// Returns middle of three values. - template - constexpr Ty mid(const Ty& _a, const Ty& _b, const Ty& _c); + /// Returns middle of three or more values. + template + constexpr Ty mid(const Ty& _a, const Ty& _b, const Args&... _args); /// Returns clamped value between min/max. template constexpr Ty clamp(const Ty& _a, const Ty& _min, const Ty& _max); - /// Returns true if value is power of 2. + /// Returns true if value `_a` is power of 2. template constexpr bool isPowerOf2(Ty _a); @@ -94,7 +101,7 @@ namespace bx /// @param _src Source pointer. /// @param _srcStride Source stride. /// @param _stride Number of bytes per stride to copy. - /// @param _num Number of strides. + /// @param _numStrides Number of strides. /// /// @remark Source and destination memory blocks must not overlap. /// @@ -104,12 +111,31 @@ namespace bx , const void* _src , uint32_t _srcStride , uint32_t _stride - , uint32_t _num + , uint32_t _numStrides ); + /// Copy memory block. + /// + /// @param _dst Destination pointer. + /// @param _src Source pointer. + /// @param _numBytes Number of bytes to copy. + /// + /// @remark If source and destination memory blocks overlap memory will be copied in reverse + /// order. /// void memMove(void* _dst, const void* _src, size_t _numBytes); + /// Copy strided memory block. + /// + /// @param _dst Destination pointer. + /// @param _dstStride Destination stride. + /// @param _src Source pointer. + /// @param _srcStride Source stride. + /// @param _stride Number of bytes per stride to copy. + /// @param _numStrides Number of strides. + /// + /// @remark If source and destination memory blocks overlap memory will be copied in reverse + /// order. /// void memMove( void* _dst @@ -117,34 +143,73 @@ namespace bx , const void* _src , uint32_t _srcStride , uint32_t _stride - , uint32_t _num + , uint32_t _numStrides ); + /// Fill memory block to specified value `_ch`. + /// + /// @param _dst Destination pointer. + /// @param _ch Fill value. + /// @param _numBytes Number of bytes to copy. /// void memSet(void* _dst, uint8_t _ch, size_t _numBytes); + /// Fill strided memory block to specified value `_ch`. /// - void memSet(void* _dst, uint32_t _dstStride, uint8_t _ch, uint32_t _stride, uint32_t _num); + /// @param _dst Destination pointer. + /// @param _dstStride Destination stride. + /// @param _ch Fill value. + /// @param _stride Number of bytes per stride to copy. + /// @param _numStrides Number of strides. + /// + void memSet( + void* _dst + , uint32_t _dstStride + , uint8_t _ch + , uint32_t _stride + , uint32_t _numStrides + ); + /// Compare two memory blocks. + /// + /// @param _lhs Pointer to memory block. + /// @param _rhs Pointer to memory block. + /// @param _numBytes Number of bytes to compare. + /// + /// @returns 0 if two blocks are identical, positive value if first different byte in `_lhs` is + /// greater than corresponding byte in `_rhs`. /// int32_t memCmp(const void* _lhs, const void* _rhs, size_t _numBytes); + /// Gather data scattered throught memory into linear memory block. + /// + /// @param _dst Destination pointer. + /// @param _src Source pointer. + /// @param _stride Number of bytes per stride to copy. + /// @param _numStrides Number of strides. /// void gather( void* _dst , const void* _src , uint32_t _srcStride , uint32_t _stride - , uint32_t _num + , uint32_t _numStrides ); + /// Scatter data from linear memory block through memory. + /// + /// @param _dst Destination pointer. + /// @param _dstStride Destination stride. + /// @param _src Source pointer. + /// @param _stride Number of bytes per stride to copy. + /// @param _numStrides Number of strides. /// void scatter( void* _dst , uint32_t _dstStride , const void* _src , uint32_t _stride - , uint32_t _num + , uint32_t _numStrides ); } // namespace bx diff --git a/include/bx/inline/bx.inl b/include/bx/inline/bx.inl index fc527ec..625e171 100644 --- a/include/bx/inline/bx.inl +++ b/include/bx/inline/bx.inl @@ -43,6 +43,16 @@ namespace bx ); } + template + inline const Ty* addressOf(const Ty& _a) + { + return reinterpret_cast( + &const_cast( + reinterpret_cast(_a) + ) + ); + } + template inline void swap(Ty& _a, Ty& _b) { @@ -61,22 +71,22 @@ namespace bx return _a > _b ? _a : _b; } - template - inline constexpr Ty min(const Ty& _a, const Ty& _b, const Ty& _c) + template + inline constexpr Ty min(const Ty& _a, const Ty& _b, const Args&... _args) { - return min(min(_a, _b), _c); + return min(min(_a, _b), _args...); } - template - inline constexpr Ty max(const Ty& _a, const Ty& _b, const Ty& _c) + template + inline constexpr Ty max(const Ty& _a, const Ty& _b, const Args&... _args) { - return max(max(_a, _b), _c); + return max(max(_a, _b), _args...); } - template - inline constexpr Ty mid(const Ty& _a, const Ty& _b, const Ty& _c) + template + inline constexpr Ty mid(const Ty& _a, const Ty& _b, const Args&... _args) { - return max(min(_a, _b), min(max(_a, _b), _c) ); + return max(min(_a, _b), min(max(_a, _b), _args...) ); } template diff --git a/src/bx.cpp b/src/bx.cpp index d6bdbf0..3329d20 100644 --- a/src/bx.cpp +++ b/src/bx.cpp @@ -50,20 +50,20 @@ namespace bx , const void* _src , uint32_t _srcStride , uint32_t _stride - , uint32_t _num + , uint32_t _numStrides ) { if (_stride == _srcStride && _stride == _dstStride) { - memCopy(_dst, _src, _stride*_num); + memCopy(_dst, _src, _stride*_numStrides); return; } const uint8_t* src = (const uint8_t*)_src; uint8_t* dst = (uint8_t*)_dst; - for (uint32_t ii = 0; ii < _num; ++ii, src += _srcStride, dst += _dstStride) + for (uint32_t ii = 0; ii < _numStrides; ++ii, src += _srcStride, dst += _dstStride) { memCopy(dst, src, _stride); } @@ -108,20 +108,20 @@ namespace bx , const void* _src , uint32_t _srcStride , uint32_t _stride - , uint32_t _num + , uint32_t _numStrides ) { if (_stride == _srcStride && _stride == _dstStride) { - memMove(_dst, _src, _stride*_num); + memMove(_dst, _src, _stride*_numStrides); return; } const uint8_t* src = (const uint8_t*)_src; uint8_t* dst = (uint8_t*)_dst; - for (uint32_t ii = 0; ii < _num; ++ii, src += _srcStride, dst += _dstStride) + for (uint32_t ii = 0; ii < _numStrides; ++ii, src += _srcStride, dst += _dstStride) { memMove(dst, src, _stride); } @@ -186,15 +186,15 @@ namespace bx } /// - void gather(void* _dst, const void* _src, uint32_t _srcStride, uint32_t _stride, uint32_t _num) + void gather(void* _dst, const void* _src, uint32_t _srcStride, uint32_t _stride, uint32_t _numStrides) { - memMove(_dst, _stride, _src, _srcStride, _stride, _num); + memMove(_dst, _stride, _src, _srcStride, _stride, _numStrides); } /// - void scatter(void* _dst, uint32_t _dstStride, const void* _src, uint32_t _stride, uint32_t _num) + void scatter(void* _dst, uint32_t _dstStride, const void* _src, uint32_t _stride, uint32_t _numStrides) { - memMove(_dst, _dstStride, _src, _stride, _num, _stride); + memMove(_dst, _dstStride, _src, _stride, _stride, _numStrides); } } // namespace bx diff --git a/tests/crt_test.cpp b/tests/crt_test.cpp index d402706..5f67bdd 100644 --- a/tests/crt_test.cpp +++ b/tests/crt_test.cpp @@ -41,3 +41,18 @@ TEST_CASE("memMove", "") bx::memSet(str, 'x', 4); REQUIRE(0 == bx::memCmp(str, orignal, 9) ); } + +TEST_CASE("scatter/gather", "") +{ + const char* str = "a\0b\0v\0g\0d"; + + char tmp0[64]; + bx::gather(tmp0, str, 2, 1, 5); + REQUIRE(0 == bx::memCmp(tmp0, "abvgd", 5) ); + + char tmp1[64]; + bx::scatter(tmp1, 2, tmp0, 1, 5); + bx::memSet(&tmp1[1], 2, 0, 1, 5); + REQUIRE(0 == bx::memCmp(tmp1, str, 5) ); + +}