123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- #pragma once
- #include "unaligned_mem.h"
- #include <utility>
- #ifndef _little_endian_
- #error "Not implemented"
- #endif
- namespace NHiLoPrivate {
- template <class TRepr>
- class TConstIntRef {
- public:
- explicit TConstIntRef(const char* ptr)
- : Ptr(ptr)
- {
- }
- TRepr Get() const {
- return ReadUnaligned<TRepr>(Ptr);
- }
- operator TRepr() const {
- return Get();
- }
- const char* GetPtr() const {
- return Ptr;
- }
- protected:
- const char* Ptr;
- };
- template <class TRepr>
- class TIntRef: public TConstIntRef<TRepr> {
- public:
- explicit TIntRef(char* ptr)
- : TConstIntRef<TRepr>(ptr)
- {
- }
- TIntRef& operator=(TRepr value) {
- WriteUnaligned<TRepr>(GetPtr(), value);
- return *this;
- }
- char* GetPtr() const {
- return const_cast<char*>(this->Ptr);
- }
- };
- template <class T>
- struct TReferenceType {
- using TType = T;
- };
- template <class T>
- struct TReferenceType<TConstIntRef<T>> {
- using TType = T;
- };
- template <class T>
- struct TReferenceType<TIntRef<T>> {
- using TType = T;
- };
- template <class TRepr>
- auto MakeIntRef(const char* ptr) {
- return TConstIntRef<TRepr>(ptr);
- }
- template <class TRepr>
- auto MakeIntRef(char* ptr) {
- return TIntRef<TRepr>(ptr);
- }
- template <class T>
- const char* CharPtrOf(const T& value) {
- return reinterpret_cast<const char*>(&value);
- }
- template <class T>
- char* CharPtrOf(T& value) {
- return reinterpret_cast<char*>(&value);
- }
- template <class T>
- const char* CharPtrOf(TConstIntRef<T> value) {
- return value.GetPtr();
- }
- template <class T>
- char* CharPtrOf(TIntRef<T> value) {
- return value.GetPtr();
- }
- template <bool IsLow, class TRepr, class T>
- auto MakeIntRef(T&& value) {
- using TRef = typename TReferenceType<typename std::decay<T>::type>::TType;
- static_assert(
- std::is_scalar<TRef>::value,
- "Hi* and Lo* functions can be applied only to scalar values");
- static_assert(sizeof(TRef) >= sizeof(TRepr), "Requested bit range is not within provided value");
- constexpr size_t offset = IsLow ? 0 : sizeof(TRef) - sizeof(TRepr);
- return MakeIntRef<TRepr>(CharPtrOf(std::forward<T>(value)) + offset);
- }
- } // namespace NHiLoPrivate
- /**
- * Return manipulator object that allows to get and set lower or higher bits of the value.
- *
- * @param value Must be a scalar value of sufficient size or a manipulator object obtained by
- * calling any of the other Hi/Lo functions.
- *
- * @{
- */
- template <class T>
- auto Lo32(T&& value) {
- return NHiLoPrivate::MakeIntRef<true, ui32>(std::forward<T>(value));
- }
- template <class T>
- auto Hi32(T&& value) {
- return NHiLoPrivate::MakeIntRef<false, ui32>(std::forward<T>(value));
- }
- template <class T>
- auto Lo16(T&& value) {
- return NHiLoPrivate::MakeIntRef<true, ui16>(std::forward<T>(value));
- }
- template <class T>
- auto Hi16(T&& value) {
- return NHiLoPrivate::MakeIntRef<false, ui16>(std::forward<T>(value));
- }
- template <class T>
- auto Lo8(T&& value) {
- return NHiLoPrivate::MakeIntRef<true, ui8>(std::forward<T>(value));
- }
- template <class T>
- auto Hi8(T&& value) {
- return NHiLoPrivate::MakeIntRef<false, ui8>(std::forward<T>(value));
- }
- /** @} */
|