joy
Dependencies: mbed USBDevice USBJoystick_
Diff: buffer_builder.hpp
- Revision:
- 2:d9f806076779
diff -r 1ec4525ad0cf -r d9f806076779 buffer_builder.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/buffer_builder.hpp Sun Aug 01 17:36:27 2021 +0000 @@ -0,0 +1,262 @@ +/* + * buffer_builder.hpp + * + * Created on: Nov 25, 2011 + * Author: premmers + */ + +#ifndef BUFFER_BUILDER_HPP_ +#define BUFFER_BUILDER_HPP_ + +#include <vector> +#include <assert.h> +#include <stdint.h> +#include <string.h> + +//#include "utilities.h" + +class buffer_builder +{ +public: + static inline void put(uint8_t *&p, uint8_t &bitoffset, uint8_t fieldlen, uint32_t value) { + + assert(bitoffset < 8); + assert(fieldlen <= 32); + + uint32_t mask = (1U<<fieldlen)-1; + value &= mask; + + uint8_t b; + + // first byte + if (bitoffset > 0) + { + uint8_t remaining_bits = 8-bitoffset; + int8_t unused_bits = int8_t(remaining_bits - fieldlen); + if (unused_bits > 0) + { + b = *p; + b &= ~(mask << unused_bits); + b |= value << unused_bits; + *p = b; + bitoffset += fieldlen; + return; + } + + // all the remaining bits in first byte are in use + fieldlen -= remaining_bits; + b = *p; + b &= ~(mask >> fieldlen); + b |= value >> fieldlen; + *p++ = b; + bitoffset = 0; + } + + // middle section (whole bytes) + while (fieldlen >= 8) + { + fieldlen -= 8; + *p++ = (value >> fieldlen) & 0xFF; + } + + // last byte + if (fieldlen > 0) + { + b = *p; + b &= 0xFFU >> fieldlen; + b |= value << (8-fieldlen); + *p = b; + bitoffset = fieldlen; + } + } + + static inline void put_u8(uint8_t *&p, uint8_t b) + { + *p++ = b; + } + static inline void put_u16(uint8_t *&p, uint16_t w) + { + *p++ = (uint8_t)(w>> 8); + *p++ = (uint8_t)(w); + } + static inline void put_u16le(uint8_t *&p, uint16_t w) + { + *p++ = (uint8_t)(w); + *p++ = (uint8_t)(w>> 8); + } + static inline void put_u32(uint8_t *&p, uint32_t d) + { + *p++ = (uint8_t)(d>>24); + *p++ = (uint8_t)(d>>16); + *p++ = (uint8_t)(d>> 8); + *p++ = (uint8_t)(d); + } + static inline void put_u32le(uint8_t *&p, uint32_t d) + { + *p++ = (uint8_t)(d); + *p++ = (uint8_t)(d>> 8); + *p++ = (uint8_t)(d>>16); + *p++ = (uint8_t)(d>>24); + } + static inline void put_u64(uint8_t *&p, uint64_t d) + { + *p++ = (uint8_t)(d>>56); + *p++ = (uint8_t)(d>>48); + *p++ = (uint8_t)(d>>40); + *p++ = (uint8_t)(d>>32); + *p++ = (uint8_t)(d>>24); + *p++ = (uint8_t)(d>>16); + *p++ = (uint8_t)(d>> 8); + *p++ = (uint8_t)(d); + } + static inline void put_u64le(uint8_t *&p, uint64_t d) + { + *p++ = (uint8_t)(d); + *p++ = (uint8_t)(d>> 8); + *p++ = (uint8_t)(d>>16); + *p++ = (uint8_t)(d>>24); + *p++ = (uint8_t)(d>>32); + *p++ = (uint8_t)(d>>40); + *p++ = (uint8_t)(d>>48); + *p++ = (uint8_t)(d>>56); + } + static inline void put(uint8_t *&p, const uint8_t *data, size_t len) + { + memcpy(p, data, len); + p += len; + } + + static inline void put_u8(std::vector<uint8_t> &v, uint8_t b) + { + v.push_back(b); + } + static inline void put_u16(std::vector<uint8_t> &v, uint16_t w) + { + v.push_back((uint8_t)(w>> 8)); + v.push_back((uint8_t)(w)); + } + static inline void put_u16le(std::vector<uint8_t> &v, uint16_t w) + { + v.push_back((uint8_t)(w)); + v.push_back((uint8_t)(w>> 8)); + } + static inline void put_u32(std::vector<uint8_t> &v, uint32_t d) + { + v.push_back((uint8_t)(d>>24)); + v.push_back((uint8_t)(d>>16)); + v.push_back((uint8_t)(d>> 8)); + v.push_back((uint8_t)(d)); + } + static inline void put_u32le(std::vector<uint8_t> &v, uint32_t d) + { + v.push_back((uint8_t)(d)); + v.push_back((uint8_t)(d>> 8)); + v.push_back((uint8_t)(d>>16)); + v.push_back((uint8_t)(d>>24)); + } + static inline void put_u64(std::vector<uint8_t> &v, uint64_t d) + { + v.push_back((uint8_t)(d>>56)); + v.push_back((uint8_t)(d>>48)); + v.push_back((uint8_t)(d>>40)); + v.push_back((uint8_t)(d>>32)); + v.push_back((uint8_t)(d>>24)); + v.push_back((uint8_t)(d>>16)); + v.push_back((uint8_t)(d>> 8)); + v.push_back((uint8_t)(d)); + } + static inline void put_u64le(std::vector<uint8_t> &v, uint64_t d) + { + v.push_back((uint8_t)(d)); + v.push_back((uint8_t)(d>> 8)); + v.push_back((uint8_t)(d>>16)); + v.push_back((uint8_t)(d>>24)); + v.push_back((uint8_t)(d>>32)); + v.push_back((uint8_t)(d>>40)); + v.push_back((uint8_t)(d>>48)); + v.push_back((uint8_t)(d>>56)); + } + static inline void put(std::vector<uint8_t> &v, const uint8_t *data, size_t len) + { + v.insert(v.end(), data, data+len); + } + + static inline void fill(std::vector<uint8_t> &v, uint8_t value, size_t len) + { + v.resize(v.size()+len, value); + } + + explicit buffer_builder(std::vector<uint8_t> &v) : data(v), initial_size(v.size()) {} + buffer_builder(const buffer_builder& rhs) : data(rhs.data), initial_size(rhs.data.size()) {} + + size_t written() const + { + return data.size() - initial_size; + } + void put_u8(uint8_t b) { put_u8(data, b); } + void put_u16(uint16_t w) { put_u16(data, w); } + void put_u16le(uint16_t w) { put_u16le(data, w); } + void put_u32(uint32_t w) { put_u32(data, w); } + void put_u32le(uint32_t w) { put_u32le(data, w); } + void put_u64(uint64_t w) { put_u64(data,w); } + void put_u64le(uint64_t w) { put_u64le(data,w); } +#ifdef __ADSPBLACKFIN__ + void put_float(float f) { put_u32(*(uint32_t*)&f); } + void put_floatle(float f) { put_u32le(*(uint32_t*)&f); } + void put_double(double d) { put_u64(*(uint64_t*)&d); } + void put_doublele(double d) { put_u64le(*(uint64_t*)&d); } + COMPILETIME_ASSERT(sizeof(double)==8); + COMPILETIME_ASSERT(sizeof(float)==4); +#endif + void put(const uint8_t *p, size_t len) { put(data, p, len); } + void put(const void *p, size_t len) { put(data, (const uint8_t*)p, len); } + void fill(uint8_t v, size_t len) { fill(data, v, len); } + uint8_t* putptr(size_t len) + { + size_t s = data.size(); + data.insert(data.end(), len, uint8_t()); + return &data[s]; + } + + template<typename T, void (*F)(uint8_t *&, T)> + class ref + { + public: + void operator=(T d) + { + uint8_t* p = &data[index]; + F(p, d); + } + private: + friend class buffer_builder; + ref(std::vector<uint8_t> &data, size_t index) : data(data), index(index) {} + std::vector<uint8_t> &data; + size_t index; + }; + + typedef ref<uint8_t, &buffer_builder::put_u8> ref_u8; + typedef ref<uint16_t, &buffer_builder::put_u16> ref_u16; + typedef ref<uint16_t, &buffer_builder::put_u16le> ref_u16le; + typedef ref<uint32_t, &buffer_builder::put_u32> ref_u32; + typedef ref<uint32_t, &buffer_builder::put_u32le> ref_u32le; + typedef ref<uint64_t, &buffer_builder::put_u64> ref_u64; + typedef ref<uint64_t, &buffer_builder::put_u64le> ref_u64le; + + ref_u8 put_ref_u8() { ref_u8 r(data, data.size()); put_u8(0); return r; } + ref_u16 put_ref_u16() { ref_u16 r(data, data.size()); put_u16(0); return r; } + ref_u16le put_ref_u16le() { ref_u16le r(data, data.size()); put_u16le(0); return r; } + ref_u32 put_ref_u32() { ref_u32 r(data, data.size()); put_u32(0); return r; } + ref_u32le put_ref_u32le() { ref_u32le r(data, data.size()); put_u32le(0); return r; } + ref_u64 put_ref_u64() { ref_u64 r(data, data.size()); put_u64(0); return r; } + ref_u64le put_ref_u64le() { ref_u64le r(data, data.size()); put_u64le(0); return r; } + + std::vector<uint8_t> &getData() { return data; } +private: + buffer_builder(); + std::vector<uint8_t> &data; + size_t initial_size; +}; + + + +#endif /* BUFFER_BUILDER_HPP_ */