1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef __BUFFER_HPP_INCLUDED__
26 #define __BUFFER_HPP_INCLUDED__
27 
28 #include <ndb_global.h>
29 
30 /* This class represents a buffer of binary data, where you can append
31  * data at the end, and later read the entire bunch.
32  * It will take care of the hairy details of realloc()ing the space
33  * for you
34  */
35 class UtilBuffer {
36 public:
UtilBuffer()37   UtilBuffer() { data = NULL; len = 0; alloc_size = 0; };
~UtilBuffer()38   ~UtilBuffer() { if(data) free(data); data = NULL; len = 0; alloc_size = 0; };
39 
40 
reallocate(size_t newsize)41   int reallocate(size_t newsize) {
42     if(newsize < len) {
43       errno = EINVAL;
44       return -1;
45     }
46     void *newdata;
47     if((newdata = realloc(data, newsize)) == NULL) {
48       errno = ENOMEM;
49       return -1;
50     }
51     alloc_size = newsize;
52     data = newdata;
53     return 0;
54   };
55 
grow(size_t l)56   int grow(size_t l) {
57     if(l > alloc_size)
58       return reallocate(l);
59     return 0;
60   };
61 
append(const void * d,size_t l)62   int append(const void *d, size_t l) {
63     int ret;
64     ret = grow(len+l);
65     if(ret != 0)
66       return ret;
67 
68     memcpy((char *)data+len, d, l);
69     len+=l;
70 
71     return 0;
72   };
73 
append(size_t l)74   void * append(size_t l){
75     if(grow(len+l) != 0)
76       return 0;
77 
78     void * ret = (char*)data+len;
79     len += l;
80     return ret;
81   }
82 
assign(const void * d,size_t l)83   int assign(const void * d, size_t l) {
84     /* Free the old data only after copying, in case d==data. */
85     void *old_data= data;
86     data = NULL;
87     len = 0;
88     alloc_size = 0;
89     int ret= append(d, l);
90     if (old_data)
91       free(old_data);
92     return ret;
93   }
94 
clear()95   void clear() {
96     len = 0;
97   }
98 
length() const99   int length() const { assert(Uint64(len) == Uint32(len)); return (int)len; }
100 
get_data() const101   void *get_data() const { return data; }
102 
empty() const103   bool empty () const { return len == 0; }
104 
equal(const UtilBuffer & cmp) const105   bool equal(const UtilBuffer &cmp) const {
106     if(len==0 && cmp.len==0)
107       return true;
108     else if(len!=cmp.len)
109       return false;
110     else
111       return (memcmp(get_data(), cmp.get_data(), len) == 0);
112   }
113 
assign(const UtilBuffer & buf)114   int assign(const UtilBuffer& buf) {
115     int ret = 0;
116     if(this != &buf) {
117       ret = assign(buf.get_data(), buf.length());
118     }
119     return ret;
120   }
121 private:
122   void *data;          /* Pointer to data storage */
123   size_t len;          /* Size of the stored data */
124   size_t alloc_size;   /* Size of the allocated space,
125 			*  i.e. len can grow to this size */
126 };
127 
128 #endif /* !__BUFFER_HPP_INCLUDED__ */
129