1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #include "dbJournalLog.h"
34 
35 #include <string>
36 
37 namespace odb {
38 
39 #define DEBUG_JOURNAL_LOG
40 
41 #ifdef DEBUG_JOURNAL_LOG
42 #define SET_TYPE(TYPE) _data.push_back((char) TYPE)
43 #define CHECK_TYPE(TYPE)                   \
44   LogDataType type = (LogDataType) next(); \
45   ZASSERT(type == TYPE)
46 #else
47 #define SET_TYPE(TYPE)
48 #define CHECK_TYPE(TYPE)
49 #endif
50 
51 enum LogDataType
52 {
53   LOG_BOOL,
54   LOG_CHAR,
55   LOG_UCHAR,
56   LOG_INT,
57   LOG_UINT,
58   LOG_FLOAT,
59   LOG_DOUBLE,
60   LOG_STRING
61 };
62 
dbJournalLog()63 dbJournalLog::dbJournalLog() : _idx(0), _debug(0)
64 {
65 #ifdef DEBUG_JOURNAL_LOG
66   _debug = 1;
67 #endif
68 }
69 
~dbJournalLog()70 dbJournalLog::~dbJournalLog()
71 {
72   clear();
73 }
74 
push(bool value)75 void dbJournalLog::push(bool value)
76 {
77   SET_TYPE(LOG_BOOL);
78   _data.push_back((value == true) ? 1 : 0);
79 }
80 
push(char value)81 void dbJournalLog::push(char value)
82 {
83   SET_TYPE(LOG_CHAR);
84   _data.push_back(value);
85 }
86 
push(unsigned char value)87 void dbJournalLog::push(unsigned char value)
88 {
89   SET_TYPE(LOG_UCHAR);
90   _data.push_back(value);
91 }
92 
push(int value)93 void dbJournalLog::push(int value)
94 {
95   SET_TYPE(LOG_INT);
96   unsigned char* v = (unsigned char*) &value;
97   _data.push_back(v[0]);
98   _data.push_back(v[1]);
99   _data.push_back(v[2]);
100   _data.push_back(v[3]);
101 }
102 
push(unsigned int value)103 void dbJournalLog::push(unsigned int value)
104 {
105   SET_TYPE(LOG_UINT);
106   unsigned char* v = (unsigned char*) &value;
107   _data.push_back(v[0]);
108   _data.push_back(v[1]);
109   _data.push_back(v[2]);
110   _data.push_back(v[3]);
111 }
112 
push(float value)113 void dbJournalLog::push(float value)
114 {
115   SET_TYPE(LOG_FLOAT);
116   unsigned char* v = (unsigned char*) &value;
117   _data.push_back(v[0]);
118   _data.push_back(v[1]);
119   _data.push_back(v[2]);
120   _data.push_back(v[3]);
121 }
122 
push(double value)123 void dbJournalLog::push(double value)
124 {
125   SET_TYPE(LOG_DOUBLE);
126   unsigned char* v = (unsigned char*) &value;
127   _data.push_back(v[0]);
128   _data.push_back(v[1]);
129   _data.push_back(v[2]);
130   _data.push_back(v[3]);
131   _data.push_back(v[4]);
132   _data.push_back(v[5]);
133   _data.push_back(v[6]);
134   _data.push_back(v[7]);
135 }
136 
push(const char * value)137 void dbJournalLog::push(const char* value)
138 {
139   SET_TYPE(LOG_STRING);
140   if (value == NULL)
141     push(-1);
142   else {
143     int len = strlen(value);
144     push(len);
145 
146     for (; *value != '\0'; ++value)
147       _data.push_back(*value);
148   }
149 }
150 
pop(bool & value)151 void dbJournalLog::pop(bool& value)
152 {
153   CHECK_TYPE(LOG_BOOL);
154   value = (next() == 1) ? true : false;
155 }
156 
pop(char & value)157 void dbJournalLog::pop(char& value)
158 {
159   CHECK_TYPE(LOG_CHAR);
160   value = next();
161 }
162 
pop(unsigned char & value)163 void dbJournalLog::pop(unsigned char& value)
164 {
165   CHECK_TYPE(LOG_UCHAR);
166   value = next();
167 }
168 
pop(int & value)169 void dbJournalLog::pop(int& value)
170 {
171   CHECK_TYPE(LOG_INT);
172   unsigned char* v = (unsigned char*) &value;
173   v[0] = next();
174   v[1] = next();
175   v[2] = next();
176   v[3] = next();
177 }
178 
pop(unsigned int & value)179 void dbJournalLog::pop(unsigned int& value)
180 {
181   CHECK_TYPE(LOG_UINT);
182   unsigned char* v = (unsigned char*) &value;
183   v[0] = next();
184   v[1] = next();
185   v[2] = next();
186   v[3] = next();
187 }
188 
pop(float & value)189 void dbJournalLog::pop(float& value)
190 {
191   CHECK_TYPE(LOG_FLOAT);
192   unsigned char* v = (unsigned char*) &value;
193   v[0] = next();
194   v[1] = next();
195   v[2] = next();
196   v[3] = next();
197 }
198 
pop(double & value)199 void dbJournalLog::pop(double& value)
200 {
201   CHECK_TYPE(LOG_DOUBLE);
202   unsigned char* v = (unsigned char*) &value;
203   v[0] = next();
204   v[1] = next();
205   v[2] = next();
206   v[3] = next();
207   v[4] = next();
208   v[5] = next();
209   v[6] = next();
210   v[7] = next();
211 }
212 
pop(char * & value)213 void dbJournalLog::pop(char*& value)
214 {
215   CHECK_TYPE(LOG_STRING);
216   int len;
217   pop(len);
218 
219   if (len == -1) {
220     value = NULL;
221     return;
222   }
223 
224   value = (char*) malloc(len + 1);
225 
226   int i;
227   for (i = 0; i < len; ++i)
228     value[i] = next();
229 
230   value[i] = '\0';
231 }
232 
pop(std::string & value)233 void dbJournalLog::pop(std::string& value)
234 {
235   CHECK_TYPE(LOG_STRING);
236   int len;
237   pop(len);
238 
239   if (len == -1) {
240     value = "";
241     return;
242   }
243 
244   value.reserve(len + 1);
245   value = "";
246 
247   int i;
248   for (i = 0; i < len; ++i)
249     value.push_back(next());
250 }
251 
operator >>(dbIStream & stream,dbJournalLog & log)252 dbIStream& operator>>(dbIStream& stream, dbJournalLog& log)
253 {
254   uint debug;
255   stream >> debug;
256   assert((int) debug == log._debug);  // debug mismatch
257   stream >> log._data;
258   return stream;
259 }
260 
operator <<(dbOStream & stream,const dbJournalLog & log)261 dbOStream& operator<<(dbOStream& stream, const dbJournalLog& log)
262 {
263   stream << log._debug;
264   stream << log._data;
265   return stream;
266 }
267 
268 }  // namespace odb
269