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/***********************************************************************/
37XVOID Xvoid;
38PXOB 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/***********************************************************************/
46PSZ 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/***********************************************************************/
55short 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/***********************************************************************/
64int 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/***********************************************************************/
73double 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/***********************************************************************/
84CONSTANT::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/***********************************************************************/
95CONSTANT::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/***********************************************************************/
108int CONSTANT::GetLengthEx(void)
109 {
110 return Value->GetValLen();
111 } // end of GetLengthEx
112
113/***********************************************************************/
114/* Convert a constant to the given type. */
115/***********************************************************************/
116void 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/***********************************************************************/
127bool 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/***********************************************************************/
142bool 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/***********************************************************************/
176void 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/***********************************************************************/
184void 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/***********************************************************************/
195STRING::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/***********************************************************************/
224char *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/***********************************************************************/
249bool 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/***********************************************************************/
274bool 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/***********************************************************************/
299bool 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/***********************************************************************/
341bool 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/***********************************************************************/
368bool STRING::Append(STRING &str)
369{
370 return Append(str.GetStr());
371} // end of Append
372
373/***********************************************************************/
374/* Append a char to a STRING. */
375/***********************************************************************/
376bool 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/***********************************************************************/
398bool 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/***********************************************************************/
424bool 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