joy

Dependencies:   mbed USBDevice USBJoystick_

Revision:
2:d9f806076779
--- /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_ */