1 | /************ Xobject C++ Functions Source Code File (.CPP) ************/ |
2 | /* Name: XOBJECT.CPP Version 2.5 */ |
3 | /* */ |
4 | /* (C) Copyright to the author Olivier BERTRAND 1998-2017 */ |
5 | /* */ |
6 | /* This file contains base XOBJECT class functions. */ |
7 | /* Also here is the implementation of the CONSTANT class. */ |
8 | /***********************************************************************/ |
9 | |
10 | /***********************************************************************/ |
11 | /* Include mariaDB header file. */ |
12 | /***********************************************************************/ |
13 | #include "my_global.h" |
14 | #include "m_string.h" |
15 | |
16 | /***********************************************************************/ |
17 | /* Include required application header files */ |
18 | /* global.h is header containing all global Plug declarations. */ |
19 | /* plgdbsem.h is header containing the DB applic. declarations. */ |
20 | /***********************************************************************/ |
21 | #include "global.h" |
22 | #include "plgdbsem.h" |
23 | #include "xobject.h" |
24 | |
25 | /***********************************************************************/ |
26 | /* Macro definitions. */ |
27 | /***********************************************************************/ |
28 | #if defined(_DEBUG) || defined(DEBTRACE) |
29 | #define ASSERT(B) assert(B); |
30 | #else |
31 | #define ASSERT(B) |
32 | #endif |
33 | |
34 | /***********************************************************************/ |
35 | /* The one and only needed void object. */ |
36 | /***********************************************************************/ |
37 | XVOID Xvoid; |
38 | PXOB const pXVOID = &Xvoid; // Pointer used by other classes |
39 | |
40 | /* ------------------------- Class XOBJECT --------------------------- */ |
41 | |
42 | /***********************************************************************/ |
43 | /* GetCharValue: returns the Result value as a char string. */ |
44 | /* Using GetCharValue provides no conversion from numeric types. */ |
45 | /***********************************************************************/ |
46 | PSZ XOBJECT::GetCharValue(void) |
47 | { |
48 | ASSERT(Value) |
49 | return Value->GetCharValue(); |
50 | } // end of GetCharValue() |
51 | |
52 | /***********************************************************************/ |
53 | /* GetShortValue: returns the Result value as a short integer. */ |
54 | /***********************************************************************/ |
55 | short XOBJECT::GetShortValue(void) |
56 | { |
57 | ASSERT(Value) |
58 | return Value->GetShortValue(); |
59 | } // end of GetShortValue |
60 | |
61 | /***********************************************************************/ |
62 | /* GetIntValue: returns the Result value as a int integer. */ |
63 | /***********************************************************************/ |
64 | int XOBJECT::GetIntValue(void) |
65 | { |
66 | ASSERT(Value) |
67 | return Value->GetIntValue(); |
68 | } // end of GetIntValue |
69 | |
70 | /***********************************************************************/ |
71 | /* GetFloatValue: returns the Result value as a double float. */ |
72 | /***********************************************************************/ |
73 | double XOBJECT::GetFloatValue(void) |
74 | { |
75 | ASSERT(Value) |
76 | return Value->GetFloatValue(); |
77 | } // end of GetFloatValue |
78 | |
79 | /* ------------------------- Class CONSTANT -------------------------- */ |
80 | |
81 | /***********************************************************************/ |
82 | /* CONSTANT public constructor. */ |
83 | /***********************************************************************/ |
84 | CONSTANT::CONSTANT(PGLOBAL g, void *value, short type) |
85 | { |
86 | if (!(Value = AllocateValue(g, value, (int)type))) |
87 | throw (int)TYPE_CONST; |
88 | |
89 | Constant = true; |
90 | } // end of CONSTANT constructor |
91 | |
92 | /***********************************************************************/ |
93 | /* CONSTANT public constructor. */ |
94 | /***********************************************************************/ |
95 | CONSTANT::CONSTANT(PGLOBAL g, int n) |
96 | { |
97 | if (!(Value = AllocateValue(g, &n, TYPE_INT))) |
98 | throw (int)TYPE_CONST; |
99 | |
100 | Constant = true; |
101 | } // end of CONSTANT constructor |
102 | |
103 | /***********************************************************************/ |
104 | /* GetLengthEx: returns an evaluation of the constant string length. */ |
105 | /* Note: When converting from token to string, length has to be */ |
106 | /* specified but we need the domain length, not the value length. */ |
107 | /***********************************************************************/ |
108 | int CONSTANT::GetLengthEx(void) |
109 | { |
110 | return Value->GetValLen(); |
111 | } // end of GetLengthEx |
112 | |
113 | /***********************************************************************/ |
114 | /* Convert a constant to the given type. */ |
115 | /***********************************************************************/ |
116 | void CONSTANT::Convert(PGLOBAL g, int newtype) |
117 | { |
118 | if (Value->GetType() != newtype) |
119 | if (!(Value = AllocateValue(g, Value, newtype))) |
120 | throw (int)TYPE_CONST; |
121 | |
122 | } // end of Convert |
123 | |
124 | /***********************************************************************/ |
125 | /* Compare: returns true if this object is equivalent to xp. */ |
126 | /***********************************************************************/ |
127 | bool CONSTANT::Compare(PXOB xp) |
128 | { |
129 | if (this == xp) |
130 | return true; |
131 | else if (xp->GetType() != TYPE_CONST) |
132 | return false; |
133 | else |
134 | return Value->IsEqual(xp->GetValue(), true); |
135 | |
136 | } // end of Compare |
137 | |
138 | #if 0 |
139 | /***********************************************************************/ |
140 | /* Rephrase: temporary implementation used by PlugRephraseSQL. */ |
141 | /***********************************************************************/ |
142 | bool CONSTANT::Rephrase(PGLOBAL g, PSZ work) |
143 | { |
144 | switch (Value->GetType()) { |
145 | case TYPE_STRING: |
146 | sprintf(work + strlen(work), "'%s'" , Value->GetCharValue()); |
147 | break; |
148 | case TYPE_SHORT: |
149 | sprintf(work + strlen(work), "%hd" , Value->GetShortValue()); |
150 | break; |
151 | case TYPE_INT: |
152 | case TYPE_DATE: |
153 | sprintf(work + strlen(work), "%d" , Value->GetIntValue()); |
154 | break; |
155 | case TYPE_DOUBLE: |
156 | sprintf(work + strlen(work), "%lf" , Value->GetFloatValue()); |
157 | break; |
158 | case TYPE_BIGINT: |
159 | sprintf(work + strlen(work), "%lld" , Value->GetBigintValue()); |
160 | break; |
161 | case TYPE_TINY: |
162 | sprintf(work + strlen(work), "%d" , Value->GetTinyValue()); |
163 | break; |
164 | default: |
165 | sprintf(g->Message, MSG(BAD_CONST_TYPE), Value->GetType()); |
166 | return false; |
167 | } // endswitch |
168 | |
169 | return false; |
170 | } // end of Rephrase |
171 | #endif // 0 |
172 | |
173 | /***********************************************************************/ |
174 | /* Make file output of a constant object. */ |
175 | /***********************************************************************/ |
176 | void CONSTANT::Printf(PGLOBAL g, FILE *f, uint n) |
177 | { |
178 | Value->Printf(g, f, n); |
179 | } /* end of Printf */ |
180 | |
181 | /***********************************************************************/ |
182 | /* Make string output of a constant object. */ |
183 | /***********************************************************************/ |
184 | void CONSTANT::Prints(PGLOBAL g, char *ps, uint z) |
185 | { |
186 | Value->Prints(g, ps, z); |
187 | } /* end of Prints */ |
188 | |
189 | /* -------------------------- Class STRING --------------------------- */ |
190 | |
191 | /***********************************************************************/ |
192 | /* STRING public constructor for new char values. Alloc Size must be */ |
193 | /* calculated because PlugSubAlloc rounds up size to multiple of 8. */ |
194 | /***********************************************************************/ |
195 | STRING::STRING(PGLOBAL g, uint n, PCSZ str) |
196 | { |
197 | G = g; |
198 | Length = (str) ? strlen(str) : 0; |
199 | |
200 | if ((Strp = (PSZ)PlgDBSubAlloc(g, NULL, MY_MAX(n, Length) + 1))) { |
201 | if (str) |
202 | strcpy(Strp, str); |
203 | else |
204 | *Strp = 0; |
205 | |
206 | Next = GetNext(); |
207 | Size = (int)(Next - Strp); |
208 | Trc = false; |
209 | } else { |
210 | // This should normally never happen |
211 | Next = NULL; |
212 | Size = 0; |
213 | Trc = true; |
214 | } // endif Strp |
215 | |
216 | } // end of STRING constructor |
217 | |
218 | /***********************************************************************/ |
219 | /* Reallocate the string memory and return the (new) position. */ |
220 | /* If Next is equal to GetNext() this means that no new suballocation */ |
221 | /* has been done. Then we can just increase the size of the current */ |
222 | /* allocation and the Strp will remain pointing to the same memory. */ |
223 | /***********************************************************************/ |
224 | char *STRING::Realloc(uint len) |
225 | { |
226 | char *p; |
227 | bool b = (Next == GetNext()); |
228 | |
229 | p = (char*)PlgDBSubAlloc(G, NULL, b ? len - Size : len); |
230 | |
231 | if (!p) { |
232 | // No more room in Sarea; this is very unlikely |
233 | strcpy(G->Message, "No more room in work area" ); |
234 | Trc = true; |
235 | return NULL; |
236 | } // endif p |
237 | |
238 | if (b) |
239 | p = Strp; |
240 | |
241 | Next = GetNext(); |
242 | Size = (int)(Next - p); |
243 | return p; |
244 | } // end of Realloc |
245 | |
246 | /***********************************************************************/ |
247 | /* Set a STRING new PSZ value. */ |
248 | /***********************************************************************/ |
249 | bool STRING::Set(PCSZ s) |
250 | { |
251 | if (!s) |
252 | return false; |
253 | |
254 | uint len = strlen(s) + 1; |
255 | |
256 | if (len > Size) { |
257 | char *p = Realloc(len); |
258 | |
259 | if (!p) |
260 | return true; |
261 | else |
262 | Strp = p; |
263 | |
264 | } // endif n |
265 | |
266 | strcpy(Strp, s); |
267 | Length = len - 1; |
268 | return false; |
269 | } // end of Set |
270 | |
271 | /***********************************************************************/ |
272 | /* Set a STRING new PSZ value. */ |
273 | /***********************************************************************/ |
274 | bool STRING::Set(char *s, uint n) |
275 | { |
276 | if (!s) |
277 | return false; |
278 | |
279 | uint len = strnlen(s, n) + 1; |
280 | |
281 | if (len > Size) { |
282 | char *p = Realloc(len); |
283 | |
284 | if (!p) |
285 | return true; |
286 | else |
287 | Strp = p; |
288 | |
289 | } // endif n |
290 | |
291 | strncpy(Strp, s, n); |
292 | Length = len - 1; |
293 | return false; |
294 | } // end of Set |
295 | |
296 | /***********************************************************************/ |
297 | /* Append a char* to a STRING. */ |
298 | /***********************************************************************/ |
299 | bool STRING::Append(const char *s, uint ln, bool nq) |
300 | { |
301 | if (!s) |
302 | return false; |
303 | |
304 | uint i, len = Length + ln + 1; |
305 | |
306 | if (len > Size) { |
307 | char *p = Realloc(len); |
308 | |
309 | if (!p) |
310 | return true; |
311 | else if (p != Strp) { |
312 | strcpy(p, Strp); |
313 | Strp = p; |
314 | } // endif p |
315 | |
316 | } // endif n |
317 | |
318 | if (nq) { |
319 | for (i = 0; i < ln; i++) |
320 | switch (s[i]) { |
321 | case '\\': Strp[Length++] = '\\'; Strp[Length++] = '\\'; break; |
322 | case '\0': Strp[Length++] = '\\'; Strp[Length++] = '0'; break; |
323 | case '\'': Strp[Length++] = '\\'; Strp[Length++] = '\''; break; |
324 | case '\n': Strp[Length++] = '\\'; Strp[Length++] = 'n'; break; |
325 | case '\r': Strp[Length++] = '\\'; Strp[Length++] = 'r'; break; |
326 | case '\032': Strp[Length++] = '\\'; Strp[Length++] = 'Z'; break; |
327 | default: Strp[Length++] = s[i]; |
328 | } // endswitch s[i] |
329 | |
330 | } else |
331 | for (i = 0; i < ln && s[i]; i++) |
332 | Strp[Length++] = s[i]; |
333 | |
334 | Strp[Length] = 0; |
335 | return false; |
336 | } // end of Append |
337 | |
338 | /***********************************************************************/ |
339 | /* Append a PCSZ to a STRING. */ |
340 | /***********************************************************************/ |
341 | bool STRING::Append(PCSZ s) |
342 | { |
343 | if (!s) |
344 | return false; |
345 | |
346 | uint len = Length + strlen(s) + 1; |
347 | |
348 | if (len > Size) { |
349 | char *p = Realloc(len); |
350 | |
351 | if (!p) |
352 | return true; |
353 | else if (p != Strp) { |
354 | strcpy(p, Strp); |
355 | Strp = p; |
356 | } // endif p |
357 | |
358 | } // endif n |
359 | |
360 | strcpy(Strp + Length, s); |
361 | Length = len - 1; |
362 | return false; |
363 | } // end of Append |
364 | |
365 | /***********************************************************************/ |
366 | /* Append a STRING to a STRING. */ |
367 | /***********************************************************************/ |
368 | bool STRING::Append(STRING &str) |
369 | { |
370 | return Append(str.GetStr()); |
371 | } // end of Append |
372 | |
373 | /***********************************************************************/ |
374 | /* Append a char to a STRING. */ |
375 | /***********************************************************************/ |
376 | bool STRING::Append(char c) |
377 | { |
378 | if (Length + 2 > Size) { |
379 | char *p = Realloc(Length + 2); |
380 | |
381 | if (!p) |
382 | return true; |
383 | else if (p != Strp) { |
384 | strcpy(p, Strp); |
385 | Strp = p; |
386 | } // endif p |
387 | |
388 | } // endif n |
389 | |
390 | Strp[Length++] = c; |
391 | Strp[Length] = 0; |
392 | return false; |
393 | } // end of Append |
394 | |
395 | /***********************************************************************/ |
396 | /* Append a quoted PSZ to a STRING. */ |
397 | /***********************************************************************/ |
398 | bool STRING::Append_quoted(PCSZ s) |
399 | { |
400 | bool b = Append('\''); |
401 | |
402 | if (s) for (const char *p = s; !b && *p; p++) |
403 | switch (*p) { |
404 | case '\'': |
405 | case '\\': |
406 | case '\t': |
407 | case '\n': |
408 | case '\r': |
409 | case '\b': |
410 | case '\f': b |= Append('\\'); |
411 | // fall through |
412 | default: |
413 | b |= Append(*p); |
414 | break; |
415 | } // endswitch *p |
416 | |
417 | return (b |= Append('\'')); |
418 | } // end of Append_quoted |
419 | |
420 | /***********************************************************************/ |
421 | /* Resize to given length but only when last suballocated. */ |
422 | /* New size should be greater than string length. */ |
423 | /***********************************************************************/ |
424 | bool STRING::Resize(uint newsize) |
425 | { |
426 | if (Next == GetNext() && newsize > Length) { |
427 | uint nsz = (((signed)newsize + 7) / 8) * 8; |
428 | int diff = (signed)Size - (signed)nsz; |
429 | PPOOLHEADER pp = (PPOOLHEADER)G->Sarea; |
430 | |
431 | if ((signed)pp->FreeBlk + diff < 0) |
432 | return true; // Out of memory |
433 | |
434 | pp->To_Free -= diff; |
435 | pp->FreeBlk += diff; |
436 | Size = nsz; |
437 | return false; |
438 | } else |
439 | return newsize > Size; |
440 | |
441 | } // end of Resize |
442 | |