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