1 /************* Value C++ Functions Source Code File (.CPP) *************/
2 /* Name: VALUE.CPP Version 2.9 */
3 /* */
4 /* (C) Copyright to the author Olivier BERTRAND 2001-2019 */
5 /* */
6 /* This file contains the VALUE and derived classes family functions. */
7 /* These classes contain values of different types. They are used so */
8 /* new object types can be defined and added to the processing simply */
9 /* (hopefully) adding their specific functions in this file. */
10 /* First family is VALUE that represent single typed objects. It is */
11 /* used by columns (COLBLK), SELECT and FILTER (derived) objects. */
12 /* Second family is VALBLK, representing simple suballocated arrays */
13 /* of values treated sequentially by FIX, BIN and VCT tables and */
14 /* columns, as well for min/max blocks as for VCT column blocks. */
15 /* Q&A: why not using only one family ? Simple values are arrays that */
16 /* have only one element and arrays could have functions for all kind */
17 /* of processing. The answer is a-because historically it was simpler */
18 /* to do that way, b-because of performance on single values, and c- */
19 /* to avoid too complicated classes and unuseful duplication of many */
20 /* functions used on one family only. The drawback is that for new */
21 /* types of objects, we shall have more classes to update. */
22 /* Currently the only implemented types are STRING, INT, SHORT, TINY, */
23 /* DATE and LONGLONG. Recently we added some UNSIGNED types. */
24 /***********************************************************************/
25
26 /***********************************************************************/
27 /* Include relevant MariaDB header file. */
28 /***********************************************************************/
29 #include "my_global.h"
30 #include "sql_class.h"
31 #include "sql_time.h"
32
33 #if defined(_WIN32)
34 //#include <windows.h>
35 #else // !_WIN32
36 #include <string.h>
37 #endif // !_WIN32
38
39 #include <math.h>
40
41 #undef DOMAIN // Was defined in math.h
42
43 /***********************************************************************/
44 /* Include required application header files */
45 /* global.h is header containing all global Plug declarations. */
46 /* plgdbsem.h is header containing the DB applic. declarations. */
47 /***********************************************************************/
48 #include "global.h"
49 #include "plgdbsem.h"
50 #include "preparse.h" // For DATPAR
51 #include "valblk.h"
52 #define NO_FUNC // Already defined in ODBConn
53 #include "plgcnx.h" // For DB types
54 #include "osutil.h"
55
56 /***********************************************************************/
57 /* Check macro's. */
58 /***********************************************************************/
59 #if defined(_DEBUG)
60 #define CheckType(V) if (Type != V->GetType()) { \
61 PGLOBAL& g = Global; \
62 strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \
63 throw Type;
64 #else
65 #define CheckType(V)
66 #endif
67
68 #define FOURYEARS 126230400 // Four years in seconds (1 leap)
69
70 /***********************************************************************/
71 /* Initialize the DTVAL static member. */
72 /***********************************************************************/
73 int DTVAL::Shift = 0;
74
75 /***********************************************************************/
76 /* Routines called externally. */
77 /***********************************************************************/
78 bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
79
80 #if !defined(_WIN32)
81 extern "C" {
82 PSZ strupr(PSZ s);
83 PSZ strlwr(PSZ s);
84 }
85 #endif // !_WIN32
86
87 /***********************************************************************/
88 /* Get a long long number from its character representation. */
89 /* IN p: Pointer to the numeric string */
90 /* IN n: The string length */
91 /* IN maxval: The number max value */
92 /* IN un: True if the number must be unsigned */
93 /* OUT rc: Set to TRUE for out of range value */
94 /* OUT minus: Set to true if the number is negative */
95 /* Returned val: The resulting number */
96 /***********************************************************************/
CharToNumber(const char * p,int n,ulonglong maxval,bool un,bool * minus,bool * rc)97 ulonglong CharToNumber(const char *p, int n, ulonglong maxval,
98 bool un, bool *minus, bool *rc)
99 {
100 const char *p2;
101 uchar c;
102 ulonglong val;
103
104 if (minus) *minus = false;
105 if (rc) *rc = false;
106 if (n <= 0) return 0LL;
107
108 // Eliminate leading blanks or 0
109 for (p2 = p + n; p < p2 && (*p == ' ' || *p == '0'); p++) ;
110
111 // Get an eventual sign character
112 switch (*p) {
113 case '-':
114 if (un) {
115 if (rc) *rc = true;
116 return 0;
117 } else {
118 maxval++;
119 if (minus) *minus = true;
120 } // endif Unsigned
121
122 // Fall through
123 case '+':
124 p++;
125 break;
126 } // endswitch *p
127
128 for (val = 0; p < p2 && (c = (uchar)(*p - '0')) < 10; p++)
129 if (val > (maxval - c) / 10) {
130 val = maxval;
131 if (rc) *rc = true;
132 break;
133 } else
134 val = val * 10 + c;
135
136 return val;
137 } // end of CharToNumber
138
139 /***********************************************************************/
140 /* GetTypeName: returns the PlugDB internal type name. */
141 /***********************************************************************/
GetTypeName(int type)142 PCSZ GetTypeName(int type)
143 {
144 PCSZ name;
145
146 switch (type) {
147 case TYPE_STRING: name = "CHAR"; break;
148 case TYPE_SHORT: name = "SMALLINT"; break;
149 case TYPE_INT: name = "INTEGER"; break;
150 case TYPE_BIGINT: name = "BIGINT"; break;
151 case TYPE_DATE: name = "DATE"; break;
152 case TYPE_DOUBLE: name = "DOUBLE"; break;
153 case TYPE_TINY: name = "TINY"; break;
154 case TYPE_DECIM: name = "DECIMAL"; break;
155 case TYPE_BIN: name = "BINARY"; break;
156 case TYPE_PCHAR: name = "PCHAR"; break;
157 default: name = "UNKNOWN"; break;
158 } // endswitch type
159
160 return name;
161 } // end of GetTypeName
162
163 /***********************************************************************/
164 /* GetTypeSize: returns the PlugDB internal type size. */
165 /***********************************************************************/
GetTypeSize(int type,int len)166 int GetTypeSize(int type, int len)
167 {
168 switch (type) {
169 case TYPE_DECIM:
170 case TYPE_BIN:
171 case TYPE_STRING: len = len * sizeof(char); break;
172 case TYPE_SHORT: len = sizeof(short); break;
173 case TYPE_INT: len = sizeof(int); break;
174 case TYPE_BIGINT: len = sizeof(longlong); break;
175 case TYPE_DATE: len = sizeof(int); break;
176 case TYPE_DOUBLE: len = sizeof(double); break;
177 case TYPE_TINY: len = sizeof(char); break;
178 case TYPE_PCHAR: len = sizeof(char*); break;
179 default: len = -1;
180 } // endswitch type
181
182 return len;
183 } // end of GetTypeSize
184
185 /***********************************************************************/
186 /* GetFormatType: returns the FORMAT character(s) according to type. */
187 /***********************************************************************/
GetFormatType(int type)188 const char *GetFormatType(int type)
189 {
190 const char *c = "X";
191
192 switch (type) {
193 case TYPE_STRING: c = "C"; break;
194 case TYPE_SHORT: c = "S"; break;
195 case TYPE_INT: c = "N"; break;
196 case TYPE_BIGINT: c = "L"; break;
197 case TYPE_DOUBLE: c = "F"; break;
198 case TYPE_DATE: c = "D"; break;
199 case TYPE_TINY: c = "T"; break;
200 case TYPE_DECIM: c = "F"; break;
201 case TYPE_BIN: c = "B"; break;
202 case TYPE_PCHAR: c = "P"; break;
203 } // endswitch type
204
205 return c;
206 } // end of GetFormatType
207
208 /***********************************************************************/
209 /* GetFormatType: returns the FORMAT type according to character. */
210 /***********************************************************************/
GetFormatType(char c)211 int GetFormatType(char c)
212 {
213 int type = TYPE_ERROR;
214
215 switch (c) {
216 case 'C': type = TYPE_STRING; break;
217 case 'S': type = TYPE_SHORT; break;
218 case 'N': type = TYPE_INT; break;
219 case 'L': type = TYPE_BIGINT; break;
220 case 'F': type = TYPE_DOUBLE; break;
221 case 'D': type = TYPE_DATE; break;
222 case 'T': type = TYPE_TINY; break;
223 case 'M': type = TYPE_DECIM; break;
224 case 'B': type = TYPE_BIN; break;
225 case 'P': type = TYPE_PCHAR; break;
226 } // endswitch type
227
228 return type;
229 } // end of GetFormatType
230
231 /***********************************************************************/
232 /* IsTypeChar: returns true for character type(s). */
233 /***********************************************************************/
IsTypeChar(int type)234 bool IsTypeChar(int type)
235 {
236 switch (type) {
237 case TYPE_STRING:
238 case TYPE_DECIM:
239 case TYPE_BIN:
240 return true;
241 } // endswitch type
242
243 return false;
244 } // end of IsTypeChar
245
246 /***********************************************************************/
247 /* IsTypeNum: returns true for numeric types. */
248 /***********************************************************************/
IsTypeNum(int type)249 bool IsTypeNum(int type)
250 {
251 switch (type) {
252 case TYPE_INT:
253 case TYPE_BIGINT:
254 case TYPE_DATE:
255 case TYPE_DOUBLE:
256 case TYPE_SHORT:
257 case TYPE_NUM:
258 case TYPE_TINY:
259 case TYPE_DECIM:
260 return true;
261 } // endswitch type
262
263 return false;
264 } // end of IsTypeNum
265
266 /***********************************************************************/
267 /* GetFmt: returns the format to use with a typed value. */
268 /***********************************************************************/
GetFmt(int type,bool un)269 const char *GetFmt(int type, bool un)
270 {
271 const char *fmt;
272
273 switch (type) {
274 case TYPE_DECIM:
275 case TYPE_STRING: fmt = "%s"; break;
276 case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break;
277 case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
278 case TYPE_DOUBLE: fmt = "%.*lf"; break;
279 case TYPE_BIN: fmt = "%*x"; break;
280 default: fmt = (un) ? "%u" : "%d"; break;
281 } // endswitch Type
282
283 return fmt;
284 } // end of GetFmt
285
286 /***********************************************************************/
287 /* ConvertType: what this function does is to determine the type to */
288 /* which should be converted a value so no precision would be lost. */
289 /* This can be a numeric type if num is true or non numeric if false. */
290 /* Note: this is an ultra simplified version of this function that */
291 /* should become more and more complex as new types are added. */
292 /* Not evaluated types (TYPE_VOID or TYPE_UNDEF) return false from */
293 /* IsType... functions so match does not prevent correct setting. */
294 /***********************************************************************/
ConvertType(int target,int type,CONV kind,bool match)295 int ConvertType(int target, int type, CONV kind, bool match)
296 {
297 switch (kind) {
298 case CNV_CHAR:
299 if (match && (!IsTypeChar(target) || !IsTypeChar(type)))
300 return TYPE_ERROR;
301
302 return TYPE_STRING;
303 case CNV_NUM:
304 if (match && (!IsTypeNum(target) || !IsTypeNum(type)))
305 return TYPE_ERROR;
306
307 return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
308 : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
309 : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
310 : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
311 : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
312 : TYPE_TINY;
313 default:
314 if (target == TYPE_ERROR || target == type)
315 return type;
316
317 if (match && ((IsTypeChar(target) && !IsTypeChar(type)) ||
318 (IsTypeNum(target) && !IsTypeNum(type))))
319 return TYPE_ERROR;
320
321 return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
322 : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
323 : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
324 : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
325 : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
326 : (target == TYPE_STRING || type == TYPE_STRING) ? TYPE_STRING
327 : (target == TYPE_TINY || type == TYPE_TINY) ? TYPE_TINY
328 : TYPE_ERROR;
329 } // endswitch kind
330
331 } // end of ConvertType
332
333 /***********************************************************************/
334 /* AllocateConstant: allocates a constant Value. */
335 /***********************************************************************/
AllocateValue(PGLOBAL g,void * value,short type,short prec)336 PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
337 {
338 PVAL valp;
339
340 if (trace(1))
341 htrc("AllocateConstant: value=%p type=%hd\n", value, type);
342
343 switch (type) {
344 case TYPE_STRING:
345 valp = new(g) TYPVAL<PSZ>((PSZ)value, prec);
346 break;
347 case TYPE_SHORT:
348 valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT);
349 break;
350 case TYPE_INT:
351 valp = new(g) TYPVAL<int>(*(int*)value, TYPE_INT);
352 break;
353 case TYPE_BIGINT:
354 valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
355 break;
356 case TYPE_DOUBLE:
357 valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, prec);
358 break;
359 case TYPE_TINY:
360 valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
361 break;
362 default:
363 sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
364 return NULL;
365 } // endswitch Type
366
367 valp->SetGlobal(g);
368 return valp;
369 } // end of AllocateValue
370
371 /***********************************************************************/
372 /* Allocate a variable Value according to type, length and precision. */
373 /***********************************************************************/
AllocateValue(PGLOBAL g,int type,int len,int prec,bool uns,PCSZ fmt)374 PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
375 bool uns, PCSZ fmt)
376 {
377 PVAL valp;
378
379 switch (type) {
380 case TYPE_STRING:
381 valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec);
382 break;
383 case TYPE_DATE:
384 valp = new(g) DTVAL(g, len, prec, fmt);
385 break;
386 case TYPE_INT:
387 if (uns)
388 valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true);
389 else
390 valp = new(g) TYPVAL<int>((int)0, TYPE_INT);
391
392 break;
393 case TYPE_BIGINT:
394 if (uns)
395 valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true);
396 else
397 valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT);
398
399 break;
400 case TYPE_SHORT:
401 if (uns)
402 valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true);
403 else
404 valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT);
405
406 break;
407 case TYPE_DOUBLE:
408 valp = new(g) TYPVAL<double>(0.0, TYPE_DOUBLE, prec);
409 break;
410 case TYPE_TINY:
411 if (uns)
412 valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
413 else
414 valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
415
416 break;
417 case TYPE_DECIM:
418 valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns);
419 break;
420 case TYPE_BIN:
421 valp = new(g) BINVAL(g, (void*)NULL, len, prec);
422 break;
423 default:
424 sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
425 return NULL;
426 } // endswitch type
427
428 valp->SetGlobal(g);
429 return valp;
430 } // end of AllocateValue
431
432 /***********************************************************************/
433 /* Allocate a constant Value converted to newtype. */
434 /* Can also be used to copy a Value eventually converted. */
435 /***********************************************************************/
AllocateValue(PGLOBAL g,PVAL valp,int newtype,int uns)436 PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
437 {
438 PSZ p, sp;
439 bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
440 PVAL vp;
441
442 if (!valp)
443 return NULL;
444
445 if (newtype == TYPE_VOID) // Means allocate a value of the same type
446 newtype = valp->GetType();
447
448 switch (newtype) {
449 case TYPE_STRING:
450 p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
451
452 if ((sp = valp->GetCharString(p)) != p && sp)
453 strcpy(p, sp);
454
455 vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
456 break;
457 case TYPE_SHORT:
458 if (un)
459 vp = new(g) TYPVAL<ushort>(valp->GetUShortValue(),
460 TYPE_SHORT, 0, true);
461 else
462 vp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT);
463
464 break;
465 case TYPE_INT:
466 if (un)
467 vp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true);
468 else
469 vp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT);
470
471 break;
472 case TYPE_BIGINT:
473 if (un)
474 vp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(),
475 TYPE_BIGINT, 0, true);
476 else
477 vp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT);
478
479 break;
480 case TYPE_DATE:
481 vp = new(g) DTVAL(valp->GetIntValue());
482 break;
483 case TYPE_DOUBLE:
484 vp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
485 (uns) ? uns : valp->GetValPrec());
486 break;
487 case TYPE_TINY:
488 if (un)
489 vp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(),
490 TYPE_TINY, 0, true);
491 else
492 vp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY);
493
494 break;
495 default:
496 sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
497 return NULL;
498 } // endswitch type
499
500 vp->SetNullable(valp->GetNullable());
501 vp->SetNull(valp->IsNull());
502 vp->SetGlobal(g);
503 return vp;
504 } // end of AllocateValue
505
506 /* -------------------------- Class VALUE ---------------------------- */
507
508 /***********************************************************************/
509 /* Class VALUE protected constructor. */
510 /***********************************************************************/
VALUE(int type,bool un)511 VALUE::VALUE(int type, bool un) : Type(type)
512 {
513 Null = false;
514 Nullable = false;
515 Unsigned = un;
516 Clen = 0;
517 Prec = 0;
518 Fmt = GetFmt(Type, Unsigned);
519 Xfmt = GetXfmt();
520 } // end of VALUE constructor
521
522 /***********************************************************************/
523 /* VALUE GetXfmt: returns the extended format to use with typed value. */
524 /***********************************************************************/
GetXfmt(void)525 const char *VALUE::GetXfmt(void)
526 {
527 const char *fmt;
528
529 switch (Type) {
530 case TYPE_DECIM:
531 case TYPE_STRING: fmt = "%*s"; break;
532 case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break;
533 case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
534 case TYPE_DOUBLE: fmt = "%*.*lf"; break;
535 case TYPE_BIN: fmt = "%*x"; break;
536 default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
537 } // endswitch Type
538
539 return fmt;
540 } // end of GetXFmt
541
542 /***********************************************************************/
543 /* Returns a BYTE indicating the comparison between two values. */
544 /* Bit 1 indicates equality, Bit 2 less than, and Bit3 greater than. */
545 /* More than 1 bit can be set only in the case of TYPE_LIST. */
546 /***********************************************************************/
TestValue(PVAL vp)547 BYTE VALUE::TestValue(PVAL vp)
548 {
549 int n = CompareValue(vp);
550
551 return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01;
552 } // end of TestValue
553
554 /***********************************************************************/
555 /* Compute a function on a string. */
556 /***********************************************************************/
Compute(PGLOBAL g,PVAL *,int,OPVAL)557 bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL)
558 {
559 strcpy(g->Message, "Compute not implemented for this value type");
560 return true;
561 } // end of Compute
562
563 /***********************************************************************/
564 /* Make file output of an object value. */
565 /***********************************************************************/
Printf(PGLOBAL g,FILE * f,uint n)566 void VALUE::Printf(PGLOBAL g, FILE *f, uint n)
567 {
568 char m[64], buf[64];
569
570 memset(m, ' ', n); /* Make margin string */
571 m[n] = '\0';
572
573 if (Null)
574 fprintf(f, "%s<null>\n", m);
575 else
576 fprintf(f, "%s%s\n", m, GetCharString(buf));
577
578 } /* end of Printf */
579
580 /***********************************************************************/
581 /* Make string output of an object value. */
582 /***********************************************************************/
Prints(PGLOBAL g,char * ps,uint z)583 void VALUE::Prints(PGLOBAL g, char *ps, uint z)
584 {
585 char *p, buf[64];
586
587 if (Null)
588 p = strcpy(buf, "<null>");
589 else
590 p = GetCharString(buf);
591
592 strncpy(ps, p, z);
593 } // end of Prints
594
595 /* -------------------------- Class TYPVAL ---------------------------- */
596
597 /***********************************************************************/
598 /* TYPVAL public constructor from a constant typed value. */
599 /***********************************************************************/
600 template <class TYPE>
TYPVAL(TYPE n,int type,int prec,bool un)601 TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un)
602 : VALUE(type, un)
603 {
604 Tval = n;
605 Clen = sizeof(TYPE);
606 Prec = prec;
607 } // end of TYPVAL constructor
608
609 /***********************************************************************/
610 /* Return unsigned max value for the type. */
611 /***********************************************************************/
612 template <class TYPE>
MaxVal(void)613 ulonglong TYPVAL<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;}
614
615 template <>
MaxVal(void)616 ulonglong TYPVAL<short>::MaxVal(void) {return INT_MAX16;}
617
618 template <>
MaxVal(void)619 ulonglong TYPVAL<ushort>::MaxVal(void) {return UINT_MAX16;}
620
621 template <>
MaxVal(void)622 ulonglong TYPVAL<int>::MaxVal(void) {return INT_MAX32;}
623
624 template <>
MaxVal(void)625 ulonglong TYPVAL<uint>::MaxVal(void) {return UINT_MAX32;}
626
627 template <>
MaxVal(void)628 ulonglong TYPVAL<char>::MaxVal(void) {return INT_MAX8;}
629
630 template <>
MaxVal(void)631 ulonglong TYPVAL<uchar>::MaxVal(void) {return UINT_MAX8;}
632
633 template <>
MaxVal(void)634 ulonglong TYPVAL<longlong>::MaxVal(void) {return INT_MAX64;}
635
636 template <>
MaxVal(void)637 ulonglong TYPVAL<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
638
639 /***********************************************************************/
640 /* TYPVAL GetValLen: returns the print length of the typed object. */
641 /***********************************************************************/
642 template <class TYPE>
GetValLen(void)643 int TYPVAL<TYPE>::GetValLen(void)
644 {
645 char c[32];
646
647 return snprintf(c, 32, Fmt, Tval);
648 } // end of GetValLen
649
650 template <>
GetValLen(void)651 int TYPVAL<double>::GetValLen(void)
652 {
653 char c[32];
654
655 return snprintf(c, 32, Fmt, Prec, Tval);
656 } // end of GetValLen
657
658 /***********************************************************************/
659 /* TYPVAL SetValue: copy the value of another Value object. */
660 /* This function allows conversion if chktype is false. */
661 /***********************************************************************/
662 template <class TYPE>
SetValue_pval(PVAL valp,bool chktype)663 bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
664 {
665 if (valp != this) {
666 if (chktype && Type != valp->GetType())
667 return true;
668
669 if (!(Null = (valp->IsNull() && Nullable)))
670 Tval = GetTypedValue(valp);
671 else
672 Reset();
673
674 } // endif valp
675
676 return false;
677 } // end of SetValue
678
679 template <>
GetTypedValue(PVAL valp)680 short TYPVAL<short>::GetTypedValue(PVAL valp)
681 {return valp->GetShortValue();}
682
683 template <>
GetTypedValue(PVAL valp)684 ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
685 {return valp->GetUShortValue();}
686
687 template <>
GetTypedValue(PVAL valp)688 int TYPVAL<int>::GetTypedValue(PVAL valp)
689 {return valp->GetIntValue();}
690
691 template <>
GetTypedValue(PVAL valp)692 uint TYPVAL<uint>::GetTypedValue(PVAL valp)
693 {return valp->GetUIntValue();}
694
695 template <>
GetTypedValue(PVAL valp)696 longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
697 {return valp->GetBigintValue();}
698
699 template <>
GetTypedValue(PVAL valp)700 ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
701 {return valp->GetUBigintValue();}
702
703 template <>
GetTypedValue(PVAL valp)704 double TYPVAL<double>::GetTypedValue(PVAL valp)
705 {return valp->GetFloatValue();}
706
707 template <>
GetTypedValue(PVAL valp)708 char TYPVAL<char>::GetTypedValue(PVAL valp)
709 {return valp->GetTinyValue();}
710
711 template <>
GetTypedValue(PVAL valp)712 uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
713 {return valp->GetUTinyValue();}
714
715 /***********************************************************************/
716 /* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
717 /***********************************************************************/
718 template <class TYPE>
SetValue_char(const char * p,int n)719 bool TYPVAL<TYPE>::SetValue_char(const char *p, int n)
720 {
721 bool rc, minus;
722 ulonglong maxval = MaxVal();
723 ulonglong val = CharToNumber(p, n, maxval, Unsigned, &minus, &rc);
724
725 if (minus && val < maxval)
726 Tval = (TYPE)(-(signed)val);
727 else
728 Tval = (TYPE)val;
729
730 if (trace(2)) {
731 char buf[64];
732 htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
733 GetTypeName(Type), Tval);
734 } // endif trace
735
736 Null = false;
737 return rc;
738 } // end of SetValue
739
740 template <>
SetValue_char(const char * p,int n)741 bool TYPVAL<double>::SetValue_char(const char *p, int n)
742 {
743 if (p && n > 0) {
744 char buf[64];
745
746 for (; n > 0 && *p == ' '; p++)
747 n--;
748
749 memcpy(buf, p, MY_MIN(n, 31));
750 buf[n] = '\0';
751 Tval = atof(buf);
752
753 if (trace(2))
754 htrc(" setting double: '%s' -> %lf\n", buf, Tval);
755
756 Null = false;
757 } else {
758 Reset();
759 Null = Nullable;
760 } // endif p
761
762 return false;
763 } // end of SetValue
764
765 /***********************************************************************/
766 /* TYPVAL SetValue: fill a typed value from a string. */
767 /***********************************************************************/
768 template <class TYPE>
SetValue_psz(PCSZ s)769 void TYPVAL<TYPE>::SetValue_psz(PCSZ s)
770 {
771 if (s) {
772 SetValue_char(s, (int)strlen(s));
773 Null = false;
774 } else {
775 Reset();
776 Null = Nullable;
777 } // endif p
778
779 } // end of SetValue
780
781 /***********************************************************************/
782 /* TYPVAL SetValue: set value with a TYPE extracted from a block. */
783 /***********************************************************************/
784 template <class TYPE>
SetValue_pvblk(PVBLK blk,int n)785 void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n)
786 {
787 Tval = GetTypedValue(blk, n);
788 Null = false;
789 } // end of SetValue
790
791 template <>
GetTypedValue(PVBLK blk,int n)792 int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
793 {return blk->GetIntValue(n);}
794
795 template <>
GetTypedValue(PVBLK blk,int n)796 uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
797 {return blk->GetUIntValue(n);}
798
799 template <>
GetTypedValue(PVBLK blk,int n)800 short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
801 {return blk->GetShortValue(n);}
802
803 template <>
GetTypedValue(PVBLK blk,int n)804 ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
805 {return blk->GetUShortValue(n);}
806
807 template <>
GetTypedValue(PVBLK blk,int n)808 longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
809 {return blk->GetBigintValue(n);}
810
811 template <>
GetTypedValue(PVBLK blk,int n)812 ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
813 {return blk->GetUBigintValue(n);}
814
815 template <>
GetTypedValue(PVBLK blk,int n)816 double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
817 {return blk->GetFloatValue(n);}
818
819 template <>
GetTypedValue(PVBLK blk,int n)820 char TYPVAL<char>::GetTypedValue(PVBLK blk, int n)
821 {return blk->GetTinyValue(n);}
822
823 template <>
GetTypedValue(PVBLK blk,int n)824 uchar TYPVAL<uchar>::GetTypedValue(PVBLK blk, int n)
825 {return blk->GetUTinyValue(n);}
826
827 /***********************************************************************/
828 /* TYPVAL SetBinValue: with bytes extracted from a line. */
829 /* Currently only used reading column of binary files. */
830 /***********************************************************************/
831 template <class TYPE>
SetBinValue(void * p)832 void TYPVAL<TYPE>::SetBinValue(void *p)
833 {
834 #if defined(UNALIGNED_OK)
835 // x86 can cast non-aligned memory directly
836 Tval = *(TYPE *)p;
837 #else
838 // Prevent unaligned memory access on MIPS and ArmHF platforms.
839 // Make use of memcpy instead of straight pointer dereferencing.
840 // Currently only used by WriteColumn of binary files.
841 // From original author: Vicentiu Ciorbaru <vicentiu@mariadb.org>
842 memcpy(&Tval, p, sizeof(TYPE));
843 #endif
844 Null = false;
845 } // end of SetBinValue
846
847 /***********************************************************************/
848 /* GetBinValue: fill a buffer with the internal binary value. */
849 /* This function checks whether the buffer length is enough and */
850 /* returns true if not. Actual filling occurs only if go is true. */
851 /* Currently only used writing column of binary files. */
852 /***********************************************************************/
853 template <class TYPE>
GetBinValue(void * buf,int buflen,bool go)854 bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
855 {
856 // Test on length was removed here until a variable in column give the
857 // real field length. For BIN files the field length logically cannot
858 // be different from the variable length because no conversion is done.
859 // Therefore this test is useless anyway.
860 //#if defined(_DEBUG)
861 // if (sizeof(TYPE) > buflen)
862 // return true;
863 //#endif
864
865 if (go)
866 #if defined(UNALIGNED_OK)
867 // x86 can cast non-aligned memory directly
868 *(TYPE *)buf = Tval;
869 #else
870 // Prevent unaligned memory access on MIPS and ArmHF platforms.
871 // Make use of memcpy instead of straight pointer dereferencing.
872 // Currently only used by WriteColumn of binary files.
873 // From original author: Vicentiu Ciorbaru <vicentiu@mariadb.org>
874 memcpy(buf, &Tval, sizeof(TYPE));
875 #endif
876
877 Null = false;
878 return false;
879 } // end of GetBinValue
880
881 /***********************************************************************/
882 /* TYPVAL ShowValue: get string representation of a typed value. */
883 /***********************************************************************/
884 template <class TYPE>
ShowValue(char * buf,int len)885 int TYPVAL<TYPE>::ShowValue(char *buf, int len)
886 {
887 return snprintf(buf, len + 1, Xfmt, len, Tval);
888 } // end of ShowValue
889
890 template <>
ShowValue(char * buf,int len)891 int TYPVAL<double>::ShowValue(char *buf, int len)
892 {
893 // TODO: use a more appropriate format to avoid possible truncation
894 return snprintf(buf, len + 1, Xfmt, len, Prec, Tval);
895 } // end of ShowValue
896
897 /***********************************************************************/
898 /* TYPVAL GetCharString: get string representation of a typed value. */
899 /***********************************************************************/
900 template <class TYPE>
GetCharString(char * p)901 char *TYPVAL<TYPE>::GetCharString(char *p)
902 {
903 sprintf(p, Fmt, Tval);
904 return p;
905 } // end of GetCharString
906
907 template <>
GetCharString(char * p)908 char *TYPVAL<double>::GetCharString(char *p)
909 {
910 // Most callers use a 32 long buffer
911 snprintf(p, 32, Fmt, Prec, Tval);
912 return p;
913 } // end of GetCharString
914
915 #if 0
916 /***********************************************************************/
917 /* TYPVAL GetShortString: get short representation of a typed value. */
918 /***********************************************************************/
919 template <class TYPE>
920 char *TYPVAL<TYPE>::GetShortString(char *p, int n)
921 {
922 sprintf(p, "%*hd", n, (short)Tval);
923 return p;
924 } // end of GetShortString
925
926 /***********************************************************************/
927 /* TYPVAL GetIntString: get int representation of a typed value. */
928 /***********************************************************************/
929 template <class TYPE>
930 char *TYPVAL<TYPE>::GetIntString(char *p, int n)
931 {
932 sprintf(p, "%*d", n, (int)Tval);
933 return p;
934 } // end of GetIntString
935
936 /***********************************************************************/
937 /* TYPVAL GetBigintString: get big int representation of a TYPE value.*/
938 /***********************************************************************/
939 template <class TYPE>
940 char *TYPVAL<TYPE>::GetBigintString(char *p, int n)
941 {
942 sprintf(p, "%*lld", n, (longlong)Tval);
943 return p;
944 } // end of GetBigintString
945
946 /***********************************************************************/
947 /* TYPVAL GetFloatString: get double representation of a typed value. */
948 /***********************************************************************/
949 template <class TYPE>
950 char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec)
951 {
952 sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval);
953 return p;
954 } // end of GetFloatString
955
956 /***********************************************************************/
957 /* TYPVAL GetTinyString: get char representation of a typed value. */
958 /***********************************************************************/
959 template <class TYPE>
960 char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
961 {
962 sprintf(p, "%*d", n, (int)(char)Tval);
963 return p;
964 } // end of GetIntString
965 #endif // 0
966
967 /***********************************************************************/
968 /* TYPVAL compare value with another Value. */
969 /***********************************************************************/
970 template <class TYPE>
IsEqual(PVAL vp,bool chktype)971 bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
972 {
973 if (this == vp)
974 return true;
975 else if (chktype && Type != vp->GetType())
976 return false;
977 else if (chktype && Unsigned != vp->IsUnsigned())
978 return false;
979 else if (Null || vp->IsNull())
980 return false;
981 else
982 return (Tval == GetTypedValue(vp));
983
984 } // end of IsEqual
985
986 /***********************************************************************/
987 /* Compare values and returns 1, 0 or -1 according to comparison. */
988 /* This function is used for evaluation of numeric filters. */
989 /***********************************************************************/
990 template <class TYPE>
CompareValue(PVAL vp)991 int TYPVAL<TYPE>::CompareValue(PVAL vp)
992 {
993 //assert(vp->GetType() == Type);
994
995 // Process filtering on numeric values.
996 TYPE n = GetTypedValue(vp);
997
998 //if (trace(1))
999 // htrc(" Comparing: val=%d,%d\n", Tval, n);
1000
1001 return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
1002 } // end of CompareValue
1003
1004 /***********************************************************************/
1005 /* Return max type value if b is true, else min type value. */
1006 /***********************************************************************/
1007 template <>
MinMaxVal(bool b)1008 short TYPVAL<short>::MinMaxVal(bool b)
1009 {return (b) ? INT_MAX16 : INT_MIN16;}
1010
1011 template <>
MinMaxVal(bool b)1012 ushort TYPVAL<ushort>::MinMaxVal(bool b)
1013 {return (b) ? UINT_MAX16 : 0;}
1014
1015 template <>
MinMaxVal(bool b)1016 int TYPVAL<int>::MinMaxVal(bool b)
1017 {return (b) ? INT_MAX32 : INT_MIN32;}
1018
1019 template <>
MinMaxVal(bool b)1020 uint TYPVAL<uint>::MinMaxVal(bool b)
1021 {return (b) ? UINT_MAX32 : 0;}
1022
1023 template <>
MinMaxVal(bool b)1024 longlong TYPVAL<longlong>::MinMaxVal(bool b)
1025 {return (b) ? INT_MAX64 : INT_MIN64;}
1026
1027 template <>
MinMaxVal(bool b)1028 ulonglong TYPVAL<ulonglong>::MinMaxVal(bool b)
1029 {return (b) ? 0xFFFFFFFFFFFFFFFFLL : 0;}
1030
1031 template <>
MinMaxVal(bool)1032 double TYPVAL<double>::MinMaxVal(bool)
1033 {assert(false); return 0.0;}
1034
1035 template <>
MinMaxVal(bool b)1036 char TYPVAL<char>::MinMaxVal(bool b)
1037 {return (b) ? INT_MAX8 : INT_MIN8;}
1038
1039 template <>
MinMaxVal(bool b)1040 uchar TYPVAL<uchar>::MinMaxVal(bool b)
1041 {return (b) ? UINT_MAX8 : 0;}
1042
1043 /***********************************************************************/
1044 /* SafeAdd: adds a value and test whether overflow/underflow occurred. */
1045 /***********************************************************************/
1046 template <class TYPE>
SafeAdd(TYPE n1,TYPE n2)1047 TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
1048 {
1049 PGLOBAL& g = Global;
1050 TYPE n = n1 + n2;
1051
1052 if ((n2 > 0) && (n < n1)) {
1053 // Overflow
1054 strcpy(g->Message, MSG(FIX_OVFLW_ADD));
1055 throw 138;
1056 } else if ((n2 < 0) && (n > n1)) {
1057 // Underflow
1058 strcpy(g->Message, MSG(FIX_UNFLW_ADD));
1059 throw 138;
1060 } // endif's n2
1061
1062 return n;
1063 } // end of SafeAdd
1064
1065 template <>
SafeAdd(double n1,double n2)1066 inline double TYPVAL<double>::SafeAdd(double n1, double n2)
1067 {
1068 return n1 + n2;
1069 } // end of SafeAdd
1070
1071 /***********************************************************************/
1072 /* SafeMult: multiply values and test whether overflow occurred. */
1073 /***********************************************************************/
1074 template <class TYPE>
SafeMult(TYPE n1,TYPE n2)1075 TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2)
1076 {
1077 PGLOBAL& g = Global;
1078 double n = (double)n1 * (double)n2;
1079
1080 if (n > MinMaxVal(true)) {
1081 // Overflow
1082 strcpy(g->Message, MSG(FIX_OVFLW_TIMES));
1083 throw 138;
1084 } else if (n < MinMaxVal(false)) {
1085 // Underflow
1086 strcpy(g->Message, MSG(FIX_UNFLW_TIMES));
1087 throw 138;
1088 } // endif's n2
1089
1090 return (TYPE)n;
1091 } // end of SafeMult
1092
1093 template <>
SafeMult(double n1,double n2)1094 inline double TYPVAL<double>::SafeMult(double n1, double n2)
1095 {
1096 return n1 * n2;
1097 } // end of SafeMult
1098
1099 /***********************************************************************/
1100 /* Compute defined functions for the type. */
1101 /***********************************************************************/
1102 template <class TYPE>
Compute(PGLOBAL g,PVAL * vp,int np,OPVAL op)1103 bool TYPVAL<TYPE>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1104 {
1105 bool rc = false;
1106 TYPE val[2];
1107
1108 assert(np == 2);
1109
1110 for (int i = 0; i < np; i++)
1111 val[i] = GetTypedValue(vp[i]);
1112
1113 switch (op) {
1114 case OP_ADD:
1115 Tval = SafeAdd(val[0], val[1]);
1116 break;
1117 case OP_MULT:
1118 Tval = SafeMult(val[0], val[1]);
1119 break;
1120 case OP_DIV:
1121 if (!val[1]) {
1122 strcpy(g->Message, MSG(ZERO_DIVIDE));
1123 return true;
1124 } // endif
1125
1126 Tval = val[0] / val[1];
1127 break;
1128 default:
1129 rc = Compall(g, vp, np, op);
1130 break;
1131 } // endswitch op
1132
1133 return rc;
1134 } // end of Compute
1135
1136 template <>
Compute(PGLOBAL g,PVAL * vp,int np,OPVAL op)1137 bool TYPVAL<double>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1138 {
1139 bool rc = false;
1140 double val[2];
1141
1142 assert(np == 2);
1143
1144 for (int i = 0; i < np; i++)
1145 val[i] = vp[i]->GetFloatValue();
1146
1147 switch (op) {
1148 case OP_ADD:
1149 Tval = val[0] + val[1];
1150 break;
1151 case OP_MULT:
1152 Tval = val[0] * val[1];
1153 break;
1154 default:
1155 rc = Compall(g, vp, np, op);
1156 } // endswitch op
1157
1158 return rc;
1159 } // end of Compute
1160
1161 /***********************************************************************/
1162 /* Compute a function for all types. */
1163 /***********************************************************************/
1164 template <class TYPE>
Compall(PGLOBAL g,PVAL * vp,int np,OPVAL op)1165 bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1166 {
1167 TYPE val[2];
1168
1169 for (int i = 0; i < np; i++)
1170 val[i] = GetTypedValue(vp[i]);
1171
1172 switch (op) {
1173 case OP_DIV:
1174 if (val[0]) {
1175 if (!val[1]) {
1176 strcpy(g->Message, MSG(ZERO_DIVIDE));
1177 return true;
1178 } // endif
1179
1180 Tval = val[0] / val[1];
1181 } else
1182 Tval = 0;
1183
1184 break;
1185 case OP_MIN:
1186 Tval = MY_MIN(val[0], val[1]);
1187 break;
1188 case OP_MAX:
1189 Tval = MY_MAX(val[0], val[1]);
1190 break;
1191 default:
1192 // sprintf(g->Message, MSG(BAD_EXP_OPER), op);
1193 strcpy(g->Message, "Function not supported");
1194 return true;
1195 } // endswitch op
1196
1197 return false;
1198 } // end of Compall
1199
1200 /***********************************************************************/
1201 /* FormatValue: This function set vp (a STRING value) to the string */
1202 /* constructed from its own value formated using the fmt format. */
1203 /* This function assumes that the format matches the value type. */
1204 /***********************************************************************/
1205 template <class TYPE>
FormatValue(PVAL vp,PCSZ fmt)1206 bool TYPVAL<TYPE>::FormatValue(PVAL vp, PCSZ fmt)
1207 {
1208 // This function is wrong and should never be called
1209 assert(false);
1210 char *buf = (char*)vp->GetTo_Val(); // Not big enough
1211 int n = sprintf(buf, fmt, Tval);
1212
1213 return (n > vp->GetValLen());
1214 } // end of FormatValue
1215
1216 /***********************************************************************/
1217 /* TYPVAL SetFormat function (used to set SELECT output format). */
1218 /***********************************************************************/
1219 template <class TYPE>
SetConstFormat(PGLOBAL g,FORMAT & fmt)1220 bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
1221 {
1222 char c[32];
1223
1224 fmt.Type[0] = *GetFormatType(Type);
1225 fmt.Length = sprintf(c, Fmt, Tval);
1226 fmt.Prec = Prec;
1227 return false;
1228 } // end of SetConstFormat
1229
1230 /* -------------------------- Class STRING --------------------------- */
1231
1232 /***********************************************************************/
1233 /* STRING public constructor from a constant string. */
1234 /***********************************************************************/
TYPVAL(PSZ s,short c)1235 TYPVAL<PSZ>::TYPVAL(PSZ s, short c) : VALUE(TYPE_STRING)
1236 {
1237 Strp = s;
1238 Len = strlen(s);
1239 Clen = Len;
1240 Ci = (c == 1);
1241 } // end of STRING constructor
1242
1243 /***********************************************************************/
1244 /* STRING public constructor from char. */
1245 /***********************************************************************/
TYPVAL(PGLOBAL g,PSZ s,int n,int c)1246 TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
1247 : VALUE(TYPE_STRING)
1248 {
1249 Len = (g) ? n : (s) ? strlen(s) : 0;
1250
1251 if (!s) {
1252 if (g) {
1253 if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
1254 memset(Strp, 0, Len + 1);
1255 else
1256 Len = 0;
1257
1258 } else
1259 assert(false);
1260
1261 } else
1262 Strp = s;
1263
1264 Clen = Len;
1265 Ci = (c != 0);
1266 } // end of STRING constructor
1267
1268 /***********************************************************************/
1269 /* Get the tiny value represented by the Strp string. */
1270 /***********************************************************************/
GetTinyValue(void)1271 char TYPVAL<PSZ>::GetTinyValue(void)
1272 {
1273 bool m;
1274 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX8, false, &m);
1275
1276 return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
1277 } // end of GetTinyValue
1278
1279 /***********************************************************************/
1280 /* Get the unsigned tiny value represented by the Strp string. */
1281 /***********************************************************************/
GetUTinyValue(void)1282 uchar TYPVAL<PSZ>::GetUTinyValue(void)
1283 {
1284 return (uchar)CharToNumber(Strp, strlen(Strp), UINT_MAX8, true);
1285 } // end of GetUTinyValue
1286
1287 /***********************************************************************/
1288 /* Get the short value represented by the Strp string. */
1289 /***********************************************************************/
GetShortValue(void)1290 short TYPVAL<PSZ>::GetShortValue(void)
1291 {
1292 bool m;
1293 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX16, false, &m);
1294
1295 return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
1296 } // end of GetShortValue
1297
1298 /***********************************************************************/
1299 /* Get the unsigned short value represented by the Strp string. */
1300 /***********************************************************************/
GetUShortValue(void)1301 ushort TYPVAL<PSZ>::GetUShortValue(void)
1302 {
1303 return (ushort)CharToNumber(Strp, strlen(Strp), UINT_MAX16, true);
1304 } // end of GetUshortValue
1305
1306 /***********************************************************************/
1307 /* Get the integer value represented by the Strp string. */
1308 /***********************************************************************/
GetIntValue(void)1309 int TYPVAL<PSZ>::GetIntValue(void)
1310 {
1311 bool m;
1312 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX32, false, &m);
1313
1314 return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
1315 } // end of GetIntValue
1316
1317 /***********************************************************************/
1318 /* Get the unsigned integer value represented by the Strp string. */
1319 /***********************************************************************/
GetUIntValue(void)1320 uint TYPVAL<PSZ>::GetUIntValue(void)
1321 {
1322 return (uint)CharToNumber(Strp, strlen(Strp), UINT_MAX32, true);
1323 } // end of GetUintValue
1324
1325 /***********************************************************************/
1326 /* Get the big integer value represented by the Strp string. */
1327 /***********************************************************************/
GetBigintValue(void)1328 longlong TYPVAL<PSZ>::GetBigintValue(void)
1329 {
1330 bool m;
1331 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX64, false, &m);
1332
1333 return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
1334 } // end of GetBigintValue
1335
1336 /***********************************************************************/
1337 /* Get the unsigned big integer value represented by the Strp string. */
1338 /***********************************************************************/
GetUBigintValue(void)1339 ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
1340 {
1341 return CharToNumber(Strp, strlen(Strp), ULONGLONG_MAX, true);
1342 } // end of GetUBigintValue
1343
1344 /***********************************************************************/
1345 /* STRING SetValue: copy the value of another Value object. */
1346 /***********************************************************************/
SetValue_pval(PVAL valp,bool chktype)1347 bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
1348 {
1349 if (valp != this) {
1350 if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
1351 return true;
1352
1353 char buf[64];
1354
1355 if (!(Null = (valp->IsNull() && Nullable)))
1356 strncpy(Strp, valp->GetCharString(buf), Len);
1357 else
1358 Reset();
1359
1360 } // endif valp
1361
1362 return false;
1363 } // end of SetValue_pval
1364
1365 /***********************************************************************/
1366 /* STRING SetValue: fill string with chars extracted from a line. */
1367 /***********************************************************************/
SetValue_char(const char * cp,int n)1368 bool TYPVAL<PSZ>::SetValue_char(const char *cp, int n)
1369 {
1370 bool rc = false;
1371
1372 if (!cp || n == 0) {
1373 Reset();
1374 Null = (cp) ? false : Nullable;
1375 } else if (cp != Strp) {
1376 const char *p = cp + n - 1;
1377
1378 for (; p >= cp; p--, n--)
1379 if (*p && *p != ' ')
1380 break;
1381
1382 rc = n > Len;
1383
1384 if ((n = MY_MIN(n, Len))) {
1385 strncpy(Strp, cp, n);
1386 Strp[n] = '\0';
1387
1388 if (trace(2))
1389 htrc(" Setting string to: '%s'\n", Strp);
1390
1391 } else
1392 Reset();
1393
1394 Null = false;
1395 } // endif cp
1396
1397 return rc;
1398 } // end of SetValue_char
1399
1400 /***********************************************************************/
1401 /* STRING SetValue: fill string with another string. */
1402 /***********************************************************************/
SetValue_psz(PCSZ s)1403 void TYPVAL<PSZ>::SetValue_psz(PCSZ s)
1404 {
1405 if (!s) {
1406 Reset();
1407 Null = Nullable;
1408 } else if (s != Strp) {
1409 strncpy(Strp, s, Len);
1410 Null = false;
1411 } // endif s
1412
1413 } // end of SetValue_psz
1414
1415 /***********************************************************************/
1416 /* STRING SetValue: fill string with a string extracted from a block. */
1417 /***********************************************************************/
SetValue_pvblk(PVBLK blk,int n)1418 void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
1419 {
1420 // STRBLK's can return a NULL pointer
1421 PSZ vp = blk->GetCharString(Strp, n);
1422
1423 if (vp != Strp)
1424 SetValue_psz(vp);
1425
1426 } // end of SetValue_pvblk
1427
1428 /***********************************************************************/
1429 /* STRING SetValue: get the character representation of an integer. */
1430 /***********************************************************************/
SetValue(int n)1431 void TYPVAL<PSZ>::SetValue(int n)
1432 {
1433 char buf[16];
1434 PGLOBAL& g = Global;
1435 int k = sprintf(buf, "%d", n);
1436
1437 if (k > Len) {
1438 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1439 throw 138;
1440 } else
1441 SetValue_psz(buf);
1442
1443 Null = false;
1444 } // end of SetValue
1445
1446 /***********************************************************************/
1447 /* STRING SetValue: get the character representation of an uint. */
1448 /***********************************************************************/
SetValue(uint n)1449 void TYPVAL<PSZ>::SetValue(uint n)
1450 {
1451 char buf[16];
1452 PGLOBAL& g = Global;
1453 int k = sprintf(buf, "%u", n);
1454
1455 if (k > Len) {
1456 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1457 throw 138;
1458 } else
1459 SetValue_psz(buf);
1460
1461 Null = false;
1462 } // end of SetValue
1463
1464 /***********************************************************************/
1465 /* STRING SetValue: get the character representation of a short int. */
1466 /***********************************************************************/
SetValue(short i)1467 void TYPVAL<PSZ>::SetValue(short i)
1468 {
1469 SetValue((int)i);
1470 Null = false;
1471 } // end of SetValue
1472
1473 /***********************************************************************/
1474 /* STRING SetValue: get the character representation of a ushort int. */
1475 /***********************************************************************/
SetValue(ushort i)1476 void TYPVAL<PSZ>::SetValue(ushort i)
1477 {
1478 SetValue((uint)i);
1479 Null = false;
1480 } // end of SetValue
1481
1482 /***********************************************************************/
1483 /* STRING SetValue: get the character representation of a big integer.*/
1484 /***********************************************************************/
SetValue(longlong n)1485 void TYPVAL<PSZ>::SetValue(longlong n)
1486 {
1487 char buf[24];
1488 PGLOBAL& g = Global;
1489 int k = sprintf(buf, "%lld", n);
1490
1491 if (k > Len) {
1492 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1493 throw 138;
1494 } else
1495 SetValue_psz(buf);
1496
1497 Null = false;
1498 } // end of SetValue
1499
1500 /***********************************************************************/
1501 /* STRING SetValue: get the character representation of a big integer.*/
1502 /***********************************************************************/
SetValue(ulonglong n)1503 void TYPVAL<PSZ>::SetValue(ulonglong n)
1504 {
1505 char buf[24];
1506 PGLOBAL& g = Global;
1507 int k = sprintf(buf, "%llu", n);
1508
1509 if (k > Len) {
1510 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1511 throw 138;
1512 } else
1513 SetValue_psz(buf);
1514
1515 Null = false;
1516 } // end of SetValue
1517
1518 /***********************************************************************/
1519 /* STRING SetValue: get the character representation of a double. */
1520 /***********************************************************************/
SetValue(double f)1521 void TYPVAL<PSZ>::SetValue(double f)
1522 {
1523 char *p, buf[64];
1524 PGLOBAL& g = Global;
1525 int k = sprintf(buf, "%lf", f);
1526
1527 for (p = buf + k - 1; p >= buf; p--)
1528 if (*p == '0') {
1529 *p = 0;
1530 k--;
1531 } else
1532 break;
1533
1534 if (k > Len) {
1535 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1536 throw 138;
1537 } else
1538 SetValue_psz(buf);
1539
1540 Null = false;
1541 } // end of SetValue
1542
1543 /***********************************************************************/
1544 /* STRING SetValue: get the character representation of a tiny int. */
1545 /***********************************************************************/
SetValue(char c)1546 void TYPVAL<PSZ>::SetValue(char c)
1547 {
1548 SetValue((int)c);
1549 Null = false;
1550 } // end of SetValue
1551
1552 /***********************************************************************/
1553 /* STRING SetValue: get the character representation of a tiny int. */
1554 /***********************************************************************/
SetValue(uchar c)1555 void TYPVAL<PSZ>::SetValue(uchar c)
1556 {
1557 SetValue((uint)c);
1558 Null = false;
1559 } // end of SetValue
1560
1561 /***********************************************************************/
1562 /* STRING SetBinValue: fill string with chars extracted from a line. */
1563 /***********************************************************************/
SetBinValue(void * p)1564 void TYPVAL<PSZ>::SetBinValue(void *p)
1565 {
1566 SetValue_char((const char *)p, Len);
1567 } // end of SetBinValue
1568
1569 /***********************************************************************/
1570 /* GetBinValue: fill a buffer with the internal binary value. */
1571 /* This function checks whether the buffer length is enough and */
1572 /* returns true if not. Actual filling occurs only if go is true. */
1573 /* Currently used by WriteColumn of binary files. */
1574 /***********************************************************************/
GetBinValue(void * buf,int buflen,bool go)1575 bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
1576 {
1577 int len = (Null) ? 0 : strlen(Strp);
1578
1579 if (len > buflen)
1580 return true;
1581 else if (go) {
1582 memset(buf, ' ', buflen);
1583 memcpy(buf, Strp, len);
1584 } // endif go
1585
1586 return false;
1587 } // end of GetBinValue
1588
1589 /***********************************************************************/
1590 /* STRING ShowValue: get string representation of a char value. */
1591 /***********************************************************************/
ShowValue(char * buf,int buflen)1592 int TYPVAL<PSZ>::ShowValue(char *buf, int buflen)
1593 {
1594 int len = (Null) ? 0 : strlen(Strp);
1595
1596 if (buf && buf != Strp) {
1597 memset(buf, ' ', (size_t)buflen + 1);
1598 memcpy(buf, Strp, MY_MIN(len, buflen));
1599 } // endif buf
1600
1601 return len;
1602 } // end of ShowValue
1603
1604 /***********************************************************************/
1605 /* STRING GetCharString: get string representation of a char value. */
1606 /***********************************************************************/
GetCharString(char *)1607 char *TYPVAL<PSZ>::GetCharString(char *)
1608 {
1609 return Strp;
1610 } // end of GetCharString
1611
1612 /***********************************************************************/
1613 /* STRING compare value with another Value. */
1614 /***********************************************************************/
IsEqual(PVAL vp,bool chktype)1615 bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
1616 {
1617 if (this == vp)
1618 return true;
1619 else if (chktype && Type != vp->GetType())
1620 return false;
1621 else if (Null || vp->IsNull())
1622 return false;
1623
1624 char buf[64];
1625
1626 if (Ci || vp->IsCi())
1627 return !stricmp(Strp, vp->GetCharString(buf));
1628 else // (!Ci)
1629 return !strcmp(Strp, vp->GetCharString(buf));
1630
1631 } // end of IsEqual
1632
1633 /***********************************************************************/
1634 /* Compare values and returns 1, 0 or -1 according to comparison. */
1635 /* This function is used for evaluation of numeric filters. */
1636 /***********************************************************************/
CompareValue(PVAL vp)1637 int TYPVAL<PSZ>::CompareValue(PVAL vp)
1638 {
1639 int n;
1640 //assert(vp->GetType() == Type);
1641
1642 if (trace(1))
1643 htrc(" Comparing: val='%s','%s'\n", Strp, vp->GetCharValue());
1644
1645 // Process filtering on character strings.
1646 if (Ci || vp->IsCi())
1647 n = stricmp(Strp, vp->GetCharValue());
1648 else
1649 n = strcmp(Strp, vp->GetCharValue());
1650
1651 #if defined(_WIN32)
1652 if (n == _NLSCMPERROR)
1653 return n; // Here we should raise an error
1654 #endif // _WIN32
1655
1656 return (n > 0) ? 1 : (n < 0) ? -1 : 0;
1657 } // end of CompareValue
1658
1659 /***********************************************************************/
1660 /* Compute a function on a string. */
1661 /***********************************************************************/
Compute(PGLOBAL g,PVAL * vp,int np,OPVAL op)1662 bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1663 {
1664 char *p[2], val[2][32];
1665 int i;
1666
1667 if (trace(1))
1668 htrc("Compute: np=%d op=%d\n", np, op);
1669
1670 for (i = 0; i < np; i++)
1671 if (!vp[i]->IsNull()) {
1672 p[i] = vp[i]->GetCharString(val[i]);
1673
1674 if (trace(1))
1675 htrc("p[%d]=%s\n", i, p[i]);
1676
1677 } else
1678 return false;
1679
1680 switch (op) {
1681 case OP_CNC:
1682 assert(np == 1 || np == 2);
1683
1684 if (np == 2)
1685 SetValue_psz(p[0]);
1686
1687 if ((i = Len - (signed)strlen(Strp)) > 0)
1688 strncat(Strp, p[np - 1], i);
1689
1690 if (trace(1))
1691 htrc("Strp=%s\n", Strp);
1692
1693 break;
1694 case OP_MIN:
1695 assert(np == 2);
1696 SetValue_psz((strcmp(p[0], p[1]) < 0) ? p[0] : p[1]);
1697 break;
1698 case OP_MAX:
1699 assert(np == 2);
1700 SetValue_psz((strcmp(p[0], p[1]) > 0) ? p[0] : p[1]);
1701 break;
1702 default:
1703 // sprintf(g->Message, MSG(BAD_EXP_OPER), op);
1704 strcpy(g->Message, "Function not supported");
1705 return true;
1706 } // endswitch op
1707
1708 Null = false;
1709 return false;
1710 } // end of Compute
1711
1712 /***********************************************************************/
1713 /* FormatValue: This function set vp (a STRING value) to the string */
1714 /* constructed from its own value formated using the fmt format. */
1715 /* This function assumes that the format matches the value type. */
1716 /***********************************************************************/
FormatValue(PVAL vp,PCSZ fmt)1717 bool TYPVAL<PSZ>::FormatValue(PVAL vp, PCSZ fmt)
1718 {
1719 char *buf = (char*)vp->GetTo_Val(); // Should be big enough
1720 int n = sprintf(buf, fmt, Strp);
1721
1722 return (n > vp->GetValLen());
1723 } // end of FormatValue
1724
1725 /***********************************************************************/
1726 /* STRING SetFormat function (used to set SELECT output format). */
1727 /***********************************************************************/
SetConstFormat(PGLOBAL,FORMAT & fmt)1728 bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL, FORMAT& fmt)
1729 {
1730 fmt.Type[0] = 'C';
1731 fmt.Length = Len;
1732 fmt.Prec = 0;
1733 return false;
1734 } // end of SetConstFormat
1735
1736 /***********************************************************************/
1737 /* Make string output of an object value. */
1738 /***********************************************************************/
Prints(PGLOBAL g,char * ps,uint z)1739 void TYPVAL<PSZ>::Prints(PGLOBAL g, char *ps, uint z)
1740 {
1741 if (Null)
1742 strncpy(ps, "null", z);
1743 else
1744 strcat(strncat(strncpy(ps, "\"", z), Strp, z-2), "\"");
1745
1746 } // end of Prints
1747
1748 /* -------------------------- Class DECIMAL -------------------------- */
1749
1750 /***********************************************************************/
1751 /* DECIMAL public constructor from a constant string. */
1752 /***********************************************************************/
DECVAL(PSZ s)1753 DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s)
1754 {
1755 if (s) {
1756 char *p = strchr(Strp, '.');
1757
1758 Prec = (p) ? (int)(Len - (p - Strp)) : 0;
1759 } // endif s
1760
1761 Type = TYPE_DECIM;
1762 } // end of DECVAL constructor
1763
1764 /***********************************************************************/
1765 /* DECIMAL public constructor from char. */
1766 /***********************************************************************/
DECVAL(PGLOBAL g,PSZ s,int n,int prec,bool uns)1767 DECVAL::DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns)
1768 : TYPVAL<PSZ>(g, s, n + (prec ? 1 : 0) + (uns ? 0 : 1), 0)
1769 {
1770 Prec = prec;
1771 Unsigned = uns;
1772 Type = TYPE_DECIM;
1773 } // end of DECVAL constructor
1774
1775 /***********************************************************************/
1776 /* DECIMAL: Check whether the numerica value is equal to 0. */
1777 /***********************************************************************/
IsZero(void)1778 bool DECVAL::IsZero(void)
1779 {
1780 for (int i = 0; Strp[i]; i++)
1781 if (!strchr("0 +-.", Strp[i]))
1782 return false;
1783
1784 return true;
1785 } // end of IsZero
1786
1787 /***********************************************************************/
1788 /* DECIMAL: Reset value to zero. */
1789 /***********************************************************************/
Reset(void)1790 void DECVAL::Reset(void)
1791 {
1792 int i = 0;
1793
1794 Strp[i++] = '0';
1795
1796 if (Prec) {
1797 Strp[i++] = '.';
1798
1799 do {
1800 Strp[i++] = '0';
1801 } while (i < Prec + 2);
1802
1803 } // endif Prec
1804
1805 Strp[i] = 0;
1806 } // end of Reset
1807
1808 /***********************************************************************/
1809 /* DECIMAL ShowValue: get string representation right justified. */
1810 /***********************************************************************/
ShowValue(char * buf,int len)1811 int DECVAL::ShowValue(char *buf, int len)
1812 {
1813 return snprintf(buf, len + 1, Xfmt, len, Strp);
1814 } // end of ShowValue
1815
1816 /***********************************************************************/
1817 /* GetBinValue: fill a buffer with the internal binary value. */
1818 /* This function checks whether the buffer length is enough and */
1819 /* returns true if not. Actual filling occurs only if go is true. */
1820 /* Currently used by WriteColumn of binary files. */
1821 /***********************************************************************/
GetBinValue(void * buf,int buflen,bool go)1822 bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
1823 {
1824 int len = (Null) ? 0 : strlen(Strp);
1825
1826 if (len > buflen)
1827 return true;
1828 else if (go) {
1829 memset(buf, ' ', buflen - len);
1830 memcpy((char*)buf + buflen - len, Strp, len);
1831 } // endif go
1832
1833 return false;
1834 } // end of GetBinValue
1835
1836 /***********************************************************************/
1837 /* DECIMAL compare value with another Value. */
1838 /***********************************************************************/
IsEqual(PVAL vp,bool chktype)1839 bool DECVAL::IsEqual(PVAL vp, bool chktype)
1840 {
1841 if (this == vp)
1842 return true;
1843 else if (chktype && Type != vp->GetType())
1844 return false;
1845 else if (Null || vp->IsNull())
1846 return false;
1847
1848 char buf[64];
1849
1850 return !strcmp(Strp, vp->GetCharString(buf));
1851 } // end of IsEqual
1852
1853 /***********************************************************************/
1854 /* Compare values and returns 1, 0 or -1 according to comparison. */
1855 /* This function is used for evaluation of numeric filters. */
1856 /***********************************************************************/
CompareValue(PVAL vp)1857 int DECVAL::CompareValue(PVAL vp)
1858 {
1859 //assert(vp->GetType() == Type);
1860
1861 // Process filtering on numeric values.
1862 double f = atof(Strp), n = vp->GetFloatValue();
1863
1864 //if (trace(1))
1865 // htrc(" Comparing: val=%d,%d\n", f, n);
1866
1867 return (f > n) ? 1 : (f < n) ? (-1) : 0;
1868 } // end of CompareValue
1869
1870 /* -------------------------- Class BINVAL --------------------------- */
1871
1872 /***********************************************************************/
1873 /* BINVAL public constructor from bytes. */
1874 /***********************************************************************/
BINVAL(PGLOBAL g,void * p,int cl,int n)1875 BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
1876 {
1877 assert(g);
1878 Len = n;
1879 Clen = cl;
1880 Binp = PlugSubAlloc(g, NULL, Clen + 1);
1881 memset(Binp, 0, Clen + 1);
1882
1883 if (p)
1884 memcpy(Binp, p, MY_MIN(Len,Clen));
1885
1886 Chrp = NULL;
1887 } // end of BINVAL constructor
1888
1889 /***********************************************************************/
1890 /* BINVAL: Check whether the hexadecimal value is equal to 0. */
1891 /***********************************************************************/
IsZero(void)1892 bool BINVAL::IsZero(void)
1893 {
1894 for (int i = 0; i < Len; i++)
1895 if (((char*)Binp)[i] != 0)
1896 return false;
1897
1898 return true;
1899 } // end of IsZero
1900
1901 /***********************************************************************/
1902 /* BINVAL: Reset value to zero. */
1903 /***********************************************************************/
Reset(void)1904 void BINVAL::Reset(void)
1905 {
1906 memset(Binp, 0, Clen);
1907 Len = 0;
1908 } // end of Reset
1909
1910 /***********************************************************************/
1911 /* Get the tiny value pointed by Binp. */
1912 /***********************************************************************/
GetTinyValue(void)1913 char BINVAL::GetTinyValue(void)
1914 {
1915 return *(char*)Binp;
1916 } // end of GetTinyValue
1917
1918 /***********************************************************************/
1919 /* Get the unsigned tiny value pointed by Binp. */
1920 /***********************************************************************/
GetUTinyValue(void)1921 uchar BINVAL::GetUTinyValue(void)
1922 {
1923 return *(uchar*)Binp;
1924 } // end of GetUTinyValue
1925
1926 /***********************************************************************/
1927 /* Get the short value pointed by Binp. */
1928 /***********************************************************************/
GetShortValue(void)1929 short BINVAL::GetShortValue(void)
1930 {
1931 if (Len >= 2)
1932 return *(short*)Binp;
1933 else
1934 return (short)GetTinyValue();
1935
1936 } // end of GetShortValue
1937
1938 /***********************************************************************/
1939 /* Get the unsigned short value pointed by Binp. */
1940 /***********************************************************************/
GetUShortValue(void)1941 ushort BINVAL::GetUShortValue(void)
1942 {
1943 return (ushort)GetShortValue();
1944 } // end of GetUshortValue
1945
1946 /***********************************************************************/
1947 /* Get the integer value pointed by Binp. */
1948 /***********************************************************************/
GetIntValue(void)1949 int BINVAL::GetIntValue(void)
1950 {
1951 if (Len >= 4)
1952 return *(int*)Binp;
1953 else
1954 return (int)GetShortValue();
1955
1956 } // end of GetIntValue
1957
1958 /***********************************************************************/
1959 /* Get the unsigned integer value pointed by Binp. */
1960 /***********************************************************************/
GetUIntValue(void)1961 uint BINVAL::GetUIntValue(void)
1962 {
1963 return (uint)GetIntValue();
1964 } // end of GetUintValue
1965
1966 /***********************************************************************/
1967 /* Get the big integer value pointed by Binp. */
1968 /***********************************************************************/
GetBigintValue(void)1969 longlong BINVAL::GetBigintValue(void)
1970 {
1971 if (Len >= 8)
1972 return *(longlong*)Binp;
1973 else
1974 return (longlong)GetIntValue();
1975
1976 } // end of GetBigintValue
1977
1978 /***********************************************************************/
1979 /* Get the unsigned big integer value pointed by Binp. */
1980 /***********************************************************************/
GetUBigintValue(void)1981 ulonglong BINVAL::GetUBigintValue(void)
1982 {
1983 return (ulonglong)GetBigintValue();
1984 } // end of GetUBigintValue
1985
1986 /***********************************************************************/
1987 /* Get the double value pointed by Binp. */
1988 /***********************************************************************/
GetFloatValue(void)1989 double BINVAL::GetFloatValue(void)
1990 {
1991 if (Len >= 8)
1992 return *(double*)Binp;
1993 else if (Len >= 4)
1994 return (double)(*(float*)Binp);
1995 else
1996 return 0.0;
1997
1998 } // end of GetFloatValue
1999
2000 /***********************************************************************/
2001 /* BINVAL SetValue: copy the value of another Value object. */
2002 /***********************************************************************/
SetValue_pval(PVAL valp,bool chktype)2003 bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
2004 {
2005 bool rc = false;
2006
2007 if (valp != this) {
2008 if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
2009 return true;
2010
2011 if (!(Null = valp->IsNull() && Nullable)) {
2012 int len = Len;
2013
2014 if ((rc = (Len = valp->GetSize()) > Clen))
2015 Len = Clen;
2016 else if (len > Len)
2017 memset(Binp, 0, len);
2018
2019 memcpy(Binp, valp->GetTo_Val(), Len);
2020 ((char*)Binp)[Len] = 0;
2021 } else
2022 Reset();
2023
2024 } // endif valp
2025
2026 return rc;
2027 } // end of SetValue_pval
2028
2029 /***********************************************************************/
2030 /* BINVAL SetValue: fill value with chars extracted from a line. */
2031 /***********************************************************************/
SetValue_char(const char * p,int n)2032 bool BINVAL::SetValue_char(const char *p, int n)
2033 {
2034 bool rc;
2035
2036 if (p && n > 0) {
2037 int len = Len;
2038
2039 if (len > (Len = MY_MIN(n, Clen)))
2040 memset(Binp, 0, len);
2041
2042 memcpy(Binp, p, Len);
2043 ((char*)Binp)[Len] = 0;
2044 rc = n > Clen;
2045 Null = false;
2046 } else {
2047 rc = false;
2048 Reset();
2049 Null = Nullable;
2050 } // endif p
2051
2052 return rc;
2053 } // end of SetValue_char
2054
2055 /***********************************************************************/
2056 /* BINVAL SetValue: fill value with another string. */
2057 /***********************************************************************/
SetValue_psz(PCSZ s)2058 void BINVAL::SetValue_psz(PCSZ s)
2059 {
2060 if (s) {
2061 int len = Len;
2062
2063 if (len > (Len = MY_MIN(Clen, (signed)strlen(s))))
2064 memset(Binp, 0, len);
2065
2066 memcpy(Binp, s, Len);
2067 ((char*)Binp)[Len] = 0;
2068 Null = false;
2069 } else {
2070 Reset();
2071 Null = Nullable;
2072 } // endif s
2073
2074 } // end of SetValue_psz
2075
2076 /***********************************************************************/
2077 /* BINVAL SetValue: fill value with bytes extracted from a block. */
2078 /***********************************************************************/
SetValue_pvblk(PVBLK blk,int n)2079 void BINVAL::SetValue_pvblk(PVBLK blk, int n)
2080 {
2081 // STRBLK's can return a NULL pointer
2082 void *vp = blk->GetValPtrEx(n);
2083
2084 if (!vp || blk->IsNull(n)) {
2085 Reset();
2086 Null = Nullable;
2087 } else if (vp != Binp) {
2088 int len = Len;
2089
2090 if (blk->GetType() == TYPE_STRING)
2091 Len = strlen((char*)vp);
2092 else
2093 Len = blk->GetVlen();
2094
2095 if (len > (Len = MY_MIN(Clen, Len)))
2096 memset(Binp, 0, len);
2097
2098 memcpy(Binp, vp, Len);
2099 ((char*)Binp)[Len] = 0;
2100 Null = false;
2101 } // endif vp
2102
2103 } // end of SetValue_pvblk
2104
2105 /***********************************************************************/
2106 /* BINVAL SetValue: get the binary representation of an integer. */
2107 /***********************************************************************/
SetValue(int n)2108 void BINVAL::SetValue(int n)
2109 {
2110 if (Clen >= 4) {
2111 if (Len > 4)
2112 memset(Binp, 0, Len);
2113
2114 *((int*)Binp) = n;
2115 Len = 4;
2116 } else
2117 SetValue((short)n);
2118
2119 } // end of SetValue
2120
2121 /***********************************************************************/
2122 /* BINVAL SetValue: get the binary representation of an uint. */
2123 /***********************************************************************/
SetValue(uint n)2124 void BINVAL::SetValue(uint n)
2125 {
2126 if (Clen >= 4) {
2127 if (Len > 4)
2128 memset(Binp, 0, Len);
2129
2130 *((uint*)Binp) = n;
2131 Len = 4;
2132 } else
2133 SetValue((ushort)n);
2134
2135 } // end of SetValue
2136
2137 /***********************************************************************/
2138 /* BINVAL SetValue: get the binary representation of a short int. */
2139 /***********************************************************************/
SetValue(short i)2140 void BINVAL::SetValue(short i)
2141 {
2142 if (Clen >= 2) {
2143 if (Len > 2)
2144 memset(Binp, 0, Len);
2145
2146 *((int*)Binp) = i;
2147 Len = 2;
2148 } else
2149 SetValue((char)i);
2150
2151 } // end of SetValue
2152
2153 /***********************************************************************/
2154 /* BINVAL SetValue: get the binary representation of a ushort int. */
2155 /***********************************************************************/
SetValue(ushort i)2156 void BINVAL::SetValue(ushort i)
2157 {
2158 if (Clen >= 2) {
2159 if (Len > 2)
2160 memset(Binp, 0, Len);
2161
2162 *((uint*)Binp) = i;
2163 Len = 2;
2164 } else
2165 SetValue((uchar)i);
2166
2167 } // end of SetValue
2168
2169 /***********************************************************************/
2170 /* BINVAL SetValue: get the binary representation of a big integer. */
2171 /***********************************************************************/
SetValue(longlong n)2172 void BINVAL::SetValue(longlong n)
2173 {
2174 if (Clen >= 8) {
2175 if (Len > 8)
2176 memset(Binp, 0, Len);
2177
2178 *((longlong*)Binp) = n;
2179 Len = 8;
2180 } else
2181 SetValue((int)n);
2182
2183 } // end of SetValue
2184
2185 /***********************************************************************/
2186 /* BINVAL SetValue: get the binary representation of a big integer. */
2187 /***********************************************************************/
SetValue(ulonglong n)2188 void BINVAL::SetValue(ulonglong n)
2189 {
2190 if (Clen >= 8) {
2191 if (Len > 8)
2192 memset(Binp, 0, Len);
2193
2194 *((ulonglong*)Binp) = n;
2195 Len = 8;
2196 } else
2197 SetValue((uint)n);
2198
2199 } // end of SetValue
2200
2201 /***********************************************************************/
2202 /* BINVAL SetValue: get the binary representation of a double. */
2203 /***********************************************************************/
SetValue(double n)2204 void BINVAL::SetValue(double n)
2205 {
2206 if (Len > 8)
2207 memset(Binp, 0, Len);
2208
2209 if (Clen >= 8) {
2210 *((double*)Binp) = n;
2211 Len = 8;
2212 } else if (Clen >= 4) {
2213 *((float*)Binp) = (float)n;
2214 Len = 4;
2215 } else
2216 Len = 0;
2217
2218 } // end of SetValue
2219
2220 /***********************************************************************/
2221 /* BINVAL SetValue: get the character binary of a tiny int. */
2222 /***********************************************************************/
SetValue(char c)2223 void BINVAL::SetValue(char c)
2224 {
2225 if (Len > 1)
2226 memset(Binp, 0, Len);
2227
2228 *((char*)Binp) = c;
2229 Len = 1;
2230 } // end of SetValue
2231
2232 /***********************************************************************/
2233 /* BINVAL SetValue: get the binary representation of a tiny int. */
2234 /***********************************************************************/
SetValue(uchar c)2235 void BINVAL::SetValue(uchar c)
2236 {
2237 if (Len > 1)
2238 memset(Binp, 0, Len);
2239
2240 *((uchar*)Binp) = c;
2241 Len = 1;
2242 } // end of SetValue
2243
2244 /***********************************************************************/
2245 /* BINVAL SetBinValue: fill string with bytes extracted from a line. */
2246 /***********************************************************************/
SetBinValue(void * p)2247 void BINVAL::SetBinValue(void *p)
2248 {
2249 memcpy(Binp, p, Clen);
2250 Len = Clen;
2251 } // end of SetBinValue
2252
2253 /***********************************************************************/
2254 /* BINVAL SetBinValue: fill string with len bytes. */
2255 /***********************************************************************/
SetBinValue(void * p,ulong len)2256 void BINVAL::SetBinValue(void* p, ulong len)
2257 {
2258 memcpy(Binp, p, len);
2259 Len = len;
2260 } // end of SetBinValue
2261
2262 /***********************************************************************/
2263 /* GetBinValue: fill a buffer with the internal binary value. */
2264 /* This function checks whether the buffer length is enough and */
2265 /* returns true if not. Actual filling occurs only if go is true. */
2266 /* Currently used by WriteColumn of binary files. */
2267 /***********************************************************************/
GetBinValue(void * buf,int buflen,bool go)2268 bool BINVAL::GetBinValue(void *buf, int buflen, bool go)
2269 {
2270 if (Len > buflen)
2271 return true;
2272 else if (go) {
2273 memset(buf, 0, buflen);
2274 memcpy(buf, Binp, Len);
2275 } // endif go
2276
2277 return false;
2278 } // end of GetBinValue
2279
2280 /***********************************************************************/
2281 /* BINVAL ShowValue: get string representation of a binary value. */
2282 /***********************************************************************/
ShowValue(char * buf,int len)2283 int BINVAL::ShowValue(char *buf, int len)
2284 {
2285 memset(buf, 0, len + 1);
2286 memcpy(buf, Binp, MY_MIN(len, Len));
2287 return Len;
2288 } // end of ShowValue
2289
2290 /***********************************************************************/
2291 /* BINVAL GetCharString: get string representation of a binary value. */
2292 /***********************************************************************/
GetCharString(char *)2293 char *BINVAL::GetCharString(char *)
2294 {
2295 if (!Chrp)
2296 Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1);
2297
2298 sprintf(Chrp, GetXfmt(), Len, Binp);
2299 return Chrp;
2300 } // end of GetCharString
2301
2302 /***********************************************************************/
2303 /* BINVAL compare value with another Value. */
2304 /***********************************************************************/
IsEqual(PVAL vp,bool chktype)2305 bool BINVAL::IsEqual(PVAL vp, bool chktype)
2306 {
2307 if (this == vp)
2308 return true;
2309 else if (chktype && Type != vp->GetType())
2310 return false;
2311 else if (Null || vp->IsNull())
2312 return false;
2313 else if (Len != vp->GetSize())
2314 return false;
2315
2316 char *v1 = (char*)Binp;
2317 char *v2 = (char*)vp->GetTo_Val();
2318
2319 for (int i = 0; i < Len; i++)
2320 if (v1[i] != v2[i])
2321 return false;
2322
2323 return true;
2324 } // end of IsEqual
2325
2326 /***********************************************************************/
2327 /* FormatValue: This function set vp (a STRING value) to the string */
2328 /* constructed from its own value formated using the fmt format. */
2329 /* This function assumes that the format matches the value type. */
2330 /***********************************************************************/
FormatValue(PVAL vp,PCSZ fmt)2331 bool BINVAL::FormatValue(PVAL vp, PCSZ fmt)
2332 {
2333 char *buf = (char*)vp->GetTo_Val(); // Should be big enough
2334 int n = sprintf(buf, fmt, Len, Binp);
2335
2336 return (n > vp->GetValLen());
2337 } // end of FormatValue
2338
2339 /***********************************************************************/
2340 /* BINVAL SetFormat function (used to set SELECT output format). */
2341 /***********************************************************************/
SetConstFormat(PGLOBAL,FORMAT & fmt)2342 bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
2343 {
2344 fmt.Type[0] = 'B';
2345 fmt.Length = Clen;
2346 fmt.Prec = 0;
2347 return false;
2348 } // end of SetConstFormat
2349
2350 /* -------------------------- Class DTVAL ---------------------------- */
2351
2352 /***********************************************************************/
2353 /* DTVAL public constructor for new void values. */
2354 /***********************************************************************/
DTVAL(PGLOBAL g,int n,int prec,PCSZ fmt)2355 DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
2356 : TYPVAL<int>((int)0, TYPE_DATE)
2357 {
2358 if (!fmt) {
2359 Pdtp = NULL;
2360 Sdate = NULL;
2361 DefYear = 0;
2362 Len = n;
2363 } else
2364 SetFormat(g, fmt, n, prec);
2365
2366 //Type = TYPE_DATE;
2367 } // end of DTVAL constructor
2368
2369 /***********************************************************************/
2370 /* DTVAL public constructor from int. */
2371 /***********************************************************************/
DTVAL(int n)2372 DTVAL::DTVAL(int n) : TYPVAL<int>(n, TYPE_DATE)
2373 {
2374 Pdtp = NULL;
2375 Len = 19;
2376 //Type = TYPE_DATE;
2377 Sdate = NULL;
2378 DefYear = 0;
2379 } // end of DTVAL constructor
2380
2381 /***********************************************************************/
2382 /* Set format so formatted dates can be converted on input/output. */
2383 /***********************************************************************/
SetFormat(PGLOBAL g,PCSZ fmt,int len,int year)2384 bool DTVAL::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year)
2385 {
2386 Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
2387 Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
2388 DefYear = (int)((year > 9999) ? (year - 10000) : year);
2389 Len = len;
2390 return false;
2391 } // end of SetFormat
2392
2393 /***********************************************************************/
2394 /* Set format from the format of another date value. */
2395 /***********************************************************************/
SetFormat(PGLOBAL g,PVAL valp)2396 bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
2397 {
2398 DTVAL *vp;
2399
2400 if (valp->GetType() != TYPE_DATE) {
2401 sprintf(g->Message, MSG(NO_FORMAT_TYPE), valp->GetType());
2402 return true;
2403 } else
2404 vp = (DTVAL*)valp;
2405
2406 Len = vp->Len;
2407 Pdtp = vp->Pdtp;
2408 Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
2409 DefYear = vp->DefYear;
2410 return false;
2411 } // end of SetFormat
2412
2413 /***********************************************************************/
2414 /* We need TimeShift because the mktime C function does a correction */
2415 /* for local time zone that we want to override for DB operations. */
2416 /***********************************************************************/
SetTimeShift(void)2417 void DTVAL::SetTimeShift(void)
2418 {
2419 struct tm dtm;
2420 memset(&dtm, 0, sizeof(dtm));
2421 dtm.tm_mday=2;
2422 dtm.tm_mon=0;
2423 dtm.tm_year=70;
2424
2425 Shift = (int)mktime(&dtm) - 86400;
2426
2427 if (trace(1))
2428 htrc("DTVAL Shift=%d\n", Shift);
2429
2430 } // end of SetTimeShift
2431
2432 // Added by Alexander Barkov
TIME_to_localtime(struct tm * tm,const MYSQL_TIME * ltime)2433 static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
2434 {
2435 bzero(tm, sizeof(*tm));
2436 tm->tm_year= ltime->year - 1900;
2437 tm->tm_mon= ltime->month - 1;
2438 tm->tm_mday= ltime->day;
2439 mktime(tm); // set tm->tm_wday tm->yday fields to get proper day name (OB)
2440 tm->tm_hour= ltime->hour;
2441 tm->tm_min= ltime->minute;
2442 tm->tm_sec= ltime->second;
2443 } // end of TIME_to_localtime
2444
2445 // Added by Alexander Barkov
gmtime_mysql(const time_t * timep,struct tm * tm)2446 static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
2447 {
2448 MYSQL_TIME ltime;
2449 thd_gmt_sec_to_TIME(current_thd, <ime, (my_time_t) *timep);
2450 TIME_to_localtime(tm, <ime);
2451 return tm;
2452 } // end of gmtime_mysql
2453
2454 /***********************************************************************/
2455 /* GetGmTime: returns a pointer to a static tm structure obtained */
2456 /* though the gmtime C function. The purpose of this function is to */
2457 /* extend the range of valid dates by accepting negative time values. */
2458 /***********************************************************************/
GetGmTime(struct tm * tm_buffer)2459 struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
2460 {
2461 struct tm *datm;
2462 time_t t = (time_t)Tval;
2463
2464 if (Tval < 0) {
2465 int n;
2466
2467 for (n = 0; t < 0; n += 4)
2468 t += FOURYEARS;
2469
2470 datm = gmtime_mysql(&t, tm_buffer);
2471
2472 if (datm)
2473 datm->tm_year -= n;
2474
2475 } else
2476 datm = gmtime_mysql(&t, tm_buffer);
2477
2478 return datm;
2479 } // end of GetGmTime
2480
2481 // Added by Alexander Barkov
mktime_mysql(struct tm * ptm)2482 static time_t mktime_mysql(struct tm *ptm)
2483 {
2484 MYSQL_TIME ltime;
2485 localtime_to_TIME(<ime, ptm);
2486 ltime.time_type= MYSQL_TIMESTAMP_DATETIME;
2487 uint error_code;
2488 time_t t= TIME_to_timestamp(current_thd, <ime, &error_code);
2489 return error_code ? (time_t) -1 : t;
2490 }
2491
2492 /***********************************************************************/
2493 /* MakeTime: calculates a date value from a tm structures using the */
2494 /* mktime C function. The purpose of this function is to extend the */
2495 /* range of valid dates by accepting to set negative time values. */
2496 /***********************************************************************/
MakeTime(struct tm * ptm)2497 bool DTVAL::MakeTime(struct tm *ptm)
2498 {
2499 int n, y = ptm->tm_year;
2500 time_t t = mktime_mysql(ptm);
2501
2502 if (trace(2))
2503 htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n",
2504 ptm->tm_year, ptm->tm_mon, ptm->tm_mday,
2505 ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
2506
2507 if (t == -1) {
2508 if (y < 1 || y > 71)
2509 return true;
2510
2511 for (n = 0; t == -1 && n < 20; n++) {
2512 ptm->tm_year += 4;
2513 t = mktime_mysql(ptm);
2514 } // endfor t
2515
2516 if (t == -1)
2517 return true;
2518
2519 if ((t -= (n * FOURYEARS)) > 2000000000)
2520 return true;
2521
2522 } // endif t
2523
2524 Tval= (int) t;
2525
2526 if (trace(2))
2527 htrc("MakeTime Ival=%d\n", Tval);
2528
2529 return false;
2530 } // end of MakeTime
2531
2532 /***********************************************************************/
2533 /* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */
2534 /***********************************************************************/
MakeDate(PGLOBAL g,int * val,int nval)2535 bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
2536 {
2537 int i, m;
2538 int n;
2539 bool rc = false;
2540 struct tm datm;
2541 bzero(&datm, sizeof(datm));
2542 datm.tm_mday=1;
2543 datm.tm_mon=0;
2544 datm.tm_year=70;
2545
2546 if (trace(2))
2547 htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n",
2548 val[0], val[1], val[2], val[3], val[4], val[5], nval);
2549
2550 for (i = 0; i < nval; i++) {
2551 n = val[i];
2552
2553 // if (trace(2))
2554 // htrc("i=%d n=%d\n", i, n);
2555
2556 switch (i) {
2557 case 0:
2558 if (n >= 1900)
2559 n -= 1900;
2560
2561 datm.tm_year = n;
2562
2563 // if (trace(2))
2564 // htrc("n=%d tm_year=%d\n", n, datm.tm_year);
2565
2566 break;
2567 case 1:
2568 // If mktime handles apparently correctly large or negative
2569 // day values, it is not the same for months. Therefore we
2570 // do the ajustment here, thus mktime has not to do it.
2571 if (n > 0) {
2572 m = (n - 1) % 12;
2573 n = (n - 1) / 12;
2574 } else {
2575 m = 11 + n % 12;
2576 n = n / 12 - 1;
2577 } // endfi n
2578
2579 datm.tm_mon = m;
2580 datm.tm_year += n;
2581
2582 // if (trace(2))
2583 // htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
2584
2585 break;
2586 case 2:
2587 // For days, big or negative values may also cause problems
2588 m = n % 1461;
2589 n = 4 * (n / 1461);
2590
2591 if (m < 0) {
2592 m += 1461;
2593 n -= 4;
2594 } // endif m
2595
2596 datm.tm_mday = m;
2597 datm.tm_year += n;
2598
2599 // if (trace(2))
2600 // htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
2601
2602 break;
2603 case 3: datm.tm_hour = n; break;
2604 case 4: datm.tm_min = n; break;
2605 case 5: datm.tm_sec = n; break;
2606 } // endswitch i
2607
2608 } // endfor i
2609
2610 if (trace(2))
2611 htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
2612 datm.tm_year, datm.tm_mon, datm.tm_mday,
2613 datm.tm_hour, datm.tm_min, datm.tm_sec);
2614
2615 // Pass g to have an error return or NULL to set invalid dates to 0
2616 if (MakeTime(&datm))
2617 {
2618 if (g) {
2619 strcpy(g->Message, MSG(BAD_DATETIME));
2620 rc = true;
2621 } else
2622 Tval = 0;
2623 }
2624 return rc;
2625 } // end of MakeDate
2626
2627 /***********************************************************************/
2628 /* DTVAL SetValue: copy the value of another Value object. */
2629 /* This function allows conversion if chktype is false. */
2630 /***********************************************************************/
SetValue_pval(PVAL valp,bool chktype)2631 bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
2632 {
2633 if (valp != this) {
2634 if (chktype && Type != valp->GetType())
2635 return true;
2636
2637 if (!(Null = valp->IsNull() && Nullable)) {
2638 if (Pdtp && !valp->IsTypeNum()) {
2639 int ndv;
2640 int dval[6];
2641
2642 ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
2643 MakeDate(NULL, dval, ndv);
2644 } else if (valp->GetType() == TYPE_BIGINT &&
2645 !(valp->GetBigintValue() % 1000)) {
2646 // Assuming that this timestamp is in milliseconds
2647 SetValue((int)(valp->GetBigintValue() / 1000));
2648 } else
2649 SetValue(valp->GetIntValue());
2650
2651 } else
2652 Reset();
2653
2654 } // endif valp
2655
2656 return false;
2657 } // end of SetValue
2658
2659 /***********************************************************************/
2660 /* SetValue: convert chars extracted from a line to date value. */
2661 /***********************************************************************/
SetValue_char(const char * p,int n)2662 bool DTVAL::SetValue_char(const char *p, int n)
2663 {
2664 bool rc= 0;
2665
2666 if (Pdtp) {
2667 const char *p2;
2668 int ndv;
2669 int dval[6];
2670
2671 if (n > 0) {
2672 // Trim trailing blanks
2673 for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--);
2674
2675 if ((rc = (n = (int)(p2 - p + 1)) > Len))
2676 n = Len;
2677
2678 memcpy(Sdate, p, n);
2679 } // endif n
2680
2681 Sdate[n] = '\0';
2682
2683 ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
2684 MakeDate(NULL, dval, ndv);
2685
2686 if (trace(2))
2687 htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
2688
2689 Null = (Nullable && ndv == 0);
2690 } else {
2691 rc = TYPVAL<int>::SetValue_char(p, n);
2692 Null = (Nullable && Tval == 0);
2693 } // endif Pdtp
2694
2695 return rc;
2696 } // end of SetValue
2697
2698 /***********************************************************************/
2699 /* SetValue: convert a char string to date value. */
2700 /***********************************************************************/
SetValue_psz(PCSZ p)2701 void DTVAL::SetValue_psz(PCSZ p)
2702 {
2703 if (Pdtp) {
2704 int ndv;
2705 int dval[6];
2706
2707 strncpy(Sdate, p, Len);
2708 Sdate[Len] = '\0';
2709
2710 ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
2711 MakeDate(NULL, dval, ndv);
2712
2713 if (trace(2))
2714 htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
2715
2716 Null = (Nullable && ndv == 0);
2717 } else {
2718 TYPVAL<int>::SetValue_psz(p);
2719 Null = (Nullable && Tval == 0);
2720 } // endif Pdtp
2721
2722 } // end of SetValue
2723
2724 /***********************************************************************/
2725 /* DTVAL SetValue: set value with a value extracted from a block. */
2726 /***********************************************************************/
SetValue_pvblk(PVBLK blk,int n)2727 void DTVAL::SetValue_pvblk(PVBLK blk, int n)
2728 {
2729 if (Pdtp && !::IsTypeNum(blk->GetType())) {
2730 int ndv;
2731 int dval[6];
2732
2733 ndv = ExtractDate(blk->GetCharValue(n), Pdtp, DefYear, dval);
2734 MakeDate(NULL, dval, ndv);
2735 } else
2736 Tval = blk->GetIntValue(n);
2737
2738 } // end of SetValue
2739
2740 /***********************************************************************/
2741 /* DTVAL SetValue: get date as an integer. */
2742 /***********************************************************************/
SetValue(int n)2743 void DTVAL::SetValue(int n)
2744 {
2745 Tval = n;
2746
2747 if (Pdtp) {
2748 size_t slen = (size_t)Len + 1;
2749 struct tm tm, *ptm= GetGmTime(&tm);
2750
2751 if (ptm)
2752 strftime(Sdate, slen, Pdtp->OutFmt, ptm);
2753
2754 } // endif Pdtp
2755
2756 } // end of SetValue
2757
2758 /***********************************************************************/
2759 /* DTVAL GetCharString: get string representation of a date value. */
2760 /***********************************************************************/
GetCharString(char * p)2761 char *DTVAL::GetCharString(char *p)
2762 {
2763 if (Pdtp) {
2764 size_t n = 0, slen = (size_t)Len + 1;
2765 struct tm tm, *ptm= GetGmTime(&tm);
2766
2767 if (ptm)
2768 n = strftime(Sdate, slen, Pdtp->OutFmt, ptm);
2769
2770 if (!n) {
2771 *Sdate = '\0';
2772 strncat(Sdate, "Error", slen);
2773 } // endif n
2774
2775 return Sdate;
2776 } else
2777 sprintf(p, "%d", Tval);
2778
2779 //Null = false; ??????????????
2780 return p;
2781 } // end of GetCharString
2782
2783 /***********************************************************************/
2784 /* DTVAL ShowValue: get string representation of a date value. */
2785 /***********************************************************************/
ShowValue(char * buf,int len)2786 int DTVAL::ShowValue(char *buf, int len)
2787 {
2788 int rv = 0;
2789
2790 if (Pdtp) {
2791 if (!Null) {
2792 size_t n = 0, m = len + 1;
2793 struct tm tm, *ptm = GetGmTime(&tm);
2794
2795 if (ptm)
2796 n = strftime(buf, m, Pdtp->OutFmt, ptm);
2797
2798 if (!n) {
2799 *buf = '\0';
2800 strncat(buf, "Error", m);
2801 rv = 5;
2802 } else
2803 rv = (int)n;
2804
2805 } else
2806 *buf = '\0'; // DEFAULT VALUE ???
2807
2808 } else
2809 rv = TYPVAL<int>::ShowValue(buf, len);
2810
2811 return rv;
2812 } // end of ShowValue
2813
2814 #if 0 // Not used by CONNECT
2815 /***********************************************************************/
2816 /* Returns a member of the struct tm representation of the date. */
2817 /***********************************************************************/
2818 bool DTVAL::GetTmMember(OPVAL op, int& mval)
2819 {
2820 bool rc = false;
2821 struct tm tm, *ptm = GetGmTime(&tm);
2822
2823 switch (op) {
2824 case OP_MDAY: mval = ptm->tm_mday; break;
2825 case OP_MONTH: mval = ptm->tm_mon + 1; break;
2826 case OP_YEAR: mval = ptm->tm_year + 1900; break;
2827 case OP_WDAY: mval = ptm->tm_wday + 1; break;
2828 case OP_YDAY: mval = ptm->tm_yday + 1; break;
2829 case OP_QUART: mval = ptm->tm_mon / 3 + 1; break;
2830 default:
2831 rc = true;
2832 } // endswitch op
2833
2834 return rc;
2835 } // end of GetTmMember
2836
2837 /***********************************************************************/
2838 /* Calculates the week number of the year for the internal date value.*/
2839 /* The International Standard ISO 8601 has decreed that Monday shall */
2840 /* be the first day of the week. A week that lies partly in one year */
2841 /* and partly in another is assigned a number in the year in which */
2842 /* most of its days lie. That means that week number 1 of any year is */
2843 /* the week that contains the January 4th. */
2844 /***********************************************************************/
2845 bool DTVAL::WeekNum(PGLOBAL g, int& nval)
2846 {
2847 // w is the start of the week SUN=0, MON=1, etc.
2848 int m, n, w = nval % 7;
2849 struct tm tm, *ptm = GetGmTime(&tm);
2850
2851 // Which day is January 4th of this year?
2852 m = (367 + ptm->tm_wday - ptm->tm_yday) % 7;
2853
2854 // When does the first week begins?
2855 n = 3 - (7 + m - w) % 7;
2856
2857 // Now calculate the week number
2858 if (!(nval = (7 + ptm->tm_yday - n) / 7))
2859 nval = 52;
2860
2861 // Everything should be Ok
2862 return false;
2863 } // end of WeekNum
2864 #endif // 0
2865
2866 /***********************************************************************/
2867 /* FormatValue: This function set vp (a STRING value) to the string */
2868 /* constructed from its own value formated using the fmt format. */
2869 /* This function assumes that the format matches the value type. */
2870 /***********************************************************************/
FormatValue(PVAL vp,PCSZ fmt)2871 bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
2872 {
2873 char *buf = (char*)vp->GetTo_Val(); // Should be big enough
2874 struct tm tm, *ptm = GetGmTime(&tm);
2875
2876 if (trace(2))
2877 htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
2878
2879 if (ptm) {
2880 size_t n = strftime(buf, vp->GetValLen(), fmt, ptm);
2881
2882 if (trace(2))
2883 htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???");
2884
2885 return (n == 0);
2886 } else
2887 return true;
2888
2889 } // end of FormatValue
2890
2891 /* -------------------------- End of Value --------------------------- */
2892