]> git.xonotic.org Git - xonotic/netradiant.git/blob - libs/util/buffer.h
Implement buffer operations
[xonotic/netradiant.git] / libs / util / buffer.h
1 #ifndef INCLUDED_BUFFER_H
2 #define INCLUDED_BUFFER_H
3
4 #include <cstdarg>
5 #include <cstdio>
6 #include <cstring>
7
8 namespace u {
9
10     using byte = char;
11
12     using cstring = const char *;
13
14     namespace details {
15         struct Reference {
16         private:
17             int m_size;
18             byte *m_data;
19         public:
20             Reference(int m_size, byte *m_data)
21                     : m_size(m_size), m_data(m_data) {}
22
23             int size() const {
24                 return m_size;
25             }
26
27             const byte *data() const {
28                 return m_data;
29             }
30
31             byte *data() {
32                 return m_data;
33             }
34         };
35
36         template<int sz>
37         struct Value {
38             byte m_data[sz];
39
40             int size() const {
41                 return sz;
42             }
43
44             const byte *data() const {
45                 return m_data;
46             }
47
48             byte *data() {
49                 return m_data;
50             }
51         };
52     }
53
54     template<class Self>
55     class IBuffer : Self {
56         using Self::Self;
57     public:
58         operator const IBuffer<details::Reference>() const {
59             return IBuffer<details::Reference>{this->size(), const_cast<byte *>(this->data())};
60         }
61
62         cstring c_str() const {
63             return this->data();
64         }
65
66         operator cstring() const {
67             return c_str();
68         }
69
70         std::size_t strlen() const {
71             return ::strlen(c_str());
72         }
73
74         byte *mut() {
75             return this->data();
76         }
77
78 //        operator byte *() {
79 //            return mut();
80 //        }
81
82         void terminate(long offset = -1) {
83             if (offset < 0) {
84                 offset += this->size();
85             }
86             mut()[offset] = '\0';
87         }
88
89         void copy(cstring str, unsigned int offset = 0, unsigned int limit = 0) {
90             if (!limit) {
91                 limit = this->size() - offset;
92             }
93             strncpy(mut() + offset, str, limit);
94         }
95
96         __attribute__((format(printf, 2, 3)))
97         void sprintf(const char *format, ...) {
98             // todo: check for overflow
99             va_list argptr;
100             va_start(argptr, format);
101             vsprintf(this->data(), format, argptr);
102             va_end(argptr);
103         }
104     };
105
106     template<int sz>
107     using BufferVal = IBuffer<details::Value<sz>>;
108
109     using Buffer = IBuffer<details::Reference>;
110
111     template<int sz>
112     BufferVal<sz> buffer() {
113         return BufferVal<sz>();
114     }
115
116 }
117
118 #endif