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 /***********************************************************************/
GetCharValue(void)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 /***********************************************************************/
GetShortValue(void)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 /***********************************************************************/
GetIntValue(void)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 /***********************************************************************/
GetFloatValue(void)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 /***********************************************************************/
CONSTANT(PGLOBAL g,void * value,short type)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 /***********************************************************************/
CONSTANT(PGLOBAL g,int n)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 /***********************************************************************/
GetLengthEx(void)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 /***********************************************************************/
Convert(PGLOBAL g,int newtype)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 /***********************************************************************/
Compare(PXOB xp)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 /***********************************************************************/
Printf(PGLOBAL g,FILE * f,uint n)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 /***********************************************************************/
Prints(PGLOBAL g,char * ps,uint z)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 /***********************************************************************/
STRING(PGLOBAL g,uint n,PCSZ str)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 /***********************************************************************/
Realloc(uint len)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 /***********************************************************************/
Set(PCSZ s)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 /***********************************************************************/
Set(char * s,uint n)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 /***********************************************************************/
Append(const char * s,uint ln,bool nq)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 /***********************************************************************/
Append(PCSZ s)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 /***********************************************************************/
Append(STRING & str)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 /***********************************************************************/
Append(char c)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 /***********************************************************************/
Append_quoted(PCSZ s)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 /***********************************************************************/
Resize(uint newsize)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