MCS  0.3.3-alpha7
Data.cc
1 // ----------------------------------------------------------------------^
2 // Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Giorgio Calderone
3 // (mailto: <gcalderone@ifc.inaf.it>)
4 //
5 // This file is part of MCS.
6 //
7 // MCS is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // MCS is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with MCS; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // ----------------------------------------------------------------------$
22 
23 #include "mcs.hh"
24 using namespace mcs;
25 
26 //CFITSIO include
27 #if ENABLE_CFITSIO
28 #include <fitsio.h>
29 #endif //ENABLE_CFITSIO
30 
31 
32 
33 
34 void copyTimeStruct(MYSQL_TIME mysql, struct tm* tm) {
35  tm->tm_sec = mysql.second;
36  tm->tm_min = mysql.minute;
37  tm->tm_hour = mysql.hour;
38  tm->tm_mday = mysql.day;
39  tm->tm_mon = mysql.month - 1;
40  tm->tm_year = mysql.year - 1900;
41 
42 }
43 
44 void copyTimeStruct(struct tm tm, MYSQL_TIME* mysql) {
45  mysql->second = tm.tm_sec ;
46  mysql->minute = tm.tm_min ;
47  mysql->hour = tm.tm_hour;
48  mysql->day = tm.tm_mday;
49  mysql->month = tm.tm_mon + 1;
50  mysql->year = tm.tm_year + 1900;
51 }
52 
53 
54 
55 
56 
57 
58 
59 
60 const char* mcs::DateTime::parseTime(const char* s, struct tm* tm)
61 {
62  int i;
63  const char* ret = NULL;
64 
65  static const char* templ[] = {
66  "%x%n%X",
67  "%x%n%T",
68  "%x%n%r",
69 
70  "%D%n%X",
71  "%D%n%T",
72  "%D%n%r",
73 
74  "%F%n%X",
75  "%F%n%T",
76  "%F%n%r",
77 
78  "%x", //The date using the locale's date format.
79  "%D", //Equivalent to `%m/%d/%y'
80  "%F", //Equivalent to `%Y-%m-%d'
81 
82  "%X", //The time using the locale's time format.
83  "%T", //Equivalent to the use of `%H:%M:%S' in this place.
84  "%r", //Complete time using the AM/PM format of the current locale.
85 
86  "%s", //number of seconds elapsed since epoch (1970-01-01 00:00:00 UTC).
87  };
88 
89  static const int ntempl = sizeof(templ) / sizeof(char*);
90 
91 
92 
93  memset(tm, '\0', sizeof (*tm));
94 
95  for (i=0; i<ntempl; i++) {
96  ret = strptime(s, templ[i], tm);
97 
98  if (ret != NULL) {
99  ret = templ[i];
100 
101  if (i < 15) {
102  if (i > 11) { //Only time
103  tm->tm_mday = 1;
104  tm->tm_mon = 0;
105  tm->tm_year = 70;
106  tm->tm_isdst = 0;
107  }
108  else if (i > 8) { //Only date
109  tm->tm_sec = 0;
110  tm->tm_min = 0;
111  tm->tm_hour = 0;
112  }
113  }
114  break;
115  }
116  }
117 
118  return ret;
119 }
120 
121 
122 
123 
125 {
126  if (mysql) {
127  struct tm tm;
128  switch(timemode) {
129  case UTC: gmtime_r(&time, &tm); break;
130  case LOCAL: localtime_r(&time, &tm);
131  }
132 
133  copyTimeStruct(tm, mysql);
134  }
135 }
136 
137 
138 
139 
141 {
142  time_t ret = time;
143 
144  if (mysql) {
145  struct tm tm;
146  memset(&tm, '\0', sizeof(tm));
147  copyTimeStruct(*mysql, &tm);
148 
149  switch(timemode) {
150  case UTC: ret = timegm(&tm); break;
151  case LOCAL: ret = my_timelocal(&tm);
152  }
153  }
154 
155  return ret;
156 }
157 
158 
159 
160 
162 {
163  timemode = UTC;
164  mysql = NULL;
165 }
166 
167 
168 void mcs::DateTime::setMysqlBuffer(MYSQL_TIME* mysql)
169 { this->mysql = mysql; }
170 
171 
173 {
174  timemode = tm;
175  to_MYSQL_TIME();
176 }
177 
178 
180 {
181  time = ::time(NULL);
182  to_MYSQL_TIME();
183 }
184 
185 
187 {
188  time = t;
189  to_MYSQL_TIME();
190 }
191 
192 
193 
194 
195 time_t mcs::my_timelocal(struct tm* tm) {
196  bool h2 = (tm->tm_hour == 2);
197  time_t time = timelocal(tm);
198 
199  //check for DST-related issues
200  if (tm->tm_isdst == 1) {
201  struct tm tm_before;
202  time_t t;
203 
204  t = time-3600;
205  localtime_r(&t, &tm_before);
206 
207  if (h2 && (tm_before.tm_isdst == 0))
208  cout << "DST Warning: given datetime does not exists!" << endl;
209 
210  if (tm_before.tm_isdst == 1)
211  time -= 3600;
212  }
213  else {
214  struct tm tm_after;
215  time_t t;
216 
217  t = time+3600;
218  localtime_r(&t, &tm_after);
219 
220  if (h2 && (tm_after.tm_isdst == 0))
221  cout << "DST Warning: given datetime is ambiguous!" << endl;
222  }
223 
224  return time;
225 }
226 
227 
228 
230 {
231  struct tm tm;
232  parseTime(s.c_str(), &tm);
233 
234  switch(timemode) {
235  case UTC: time = timegm(&tm); break;
236  case LOCAL: time = my_timelocal(&tm); break;
237  }
238 
239  to_MYSQL_TIME();
240 }
241 
242 
243 
244 void mcs::DateTime::settmval(struct tm& ltm)
245 {
246  //Note: the timelocal function does not use tm_isdst flag to compute
247  //return value, thus we use our wrapper my_timelocal to
248  //eventually take care of DST issues
249  struct tm tm = ltm;
250  switch(timemode) {
251  case UTC: time = timegm(&tm); break;
252  case LOCAL: time = my_timelocal(&tm); break;
253  }
254 
255  to_MYSQL_TIME();
256 }
257 
258 
259 
260 time_t mcs::DateTime::tval() const
261 {
262  return getTime();
263 }
264 
265 
266 struct tm mcs::DateTime::tmval() const
267 {
268  struct tm tm;
269  time_t time = getTime();
270 
271  switch(timemode) {
272  case UTC: gmtime_r(&time, &tm); break;
273  case LOCAL: localtime_r(&time, &tm); break;
274  }
275 
276  return tm;
277 }
278 
279 
281 string mcs::DateTime::sval() const
282 {
283  struct tm tm;
284  char buf[30];
285  time_t time = getTime();
286 
287  switch(timemode) {
288  case UTC: gmtime_r(&time, &tm); break;
289  case LOCAL: localtime_r(&time, &tm); break;
290  }
291 
292  strftime(buf, 30, "%F %T", &tm);
293 
294  return string(buf);
295 }
296 
297 
298 
299 
300 
301 
302 
303 
304 
305 
306 
307 
308 
309 
310 
311 
312 
313 string mcs::Types2Str(Types type, bool isunsigned)
314 {
315  string ret="";
316  if (isunsigned) ret = "UNSIGNED ";
317 
318  switch (type) {
319  case TINY:
320  ret += "TINY"; break;
321  case SMALL:
322  ret += "SMALL"; break;
323  case MEDIUM:
324  ret += "MEDIUM"; break;
325  case INT :
326  ret += "INT"; break;
327  case BIGINT:
328  ret += "BIGINT"; break;
329  case FLOAT:
330  ret = "FLOAT"; break;
331  case DOUBLE:
332  ret = "DOUBLE"; break;
333  case STRING:
334  ret = "STRING"; break;
335  case TIME:
336  ret = "TIME"; break;
337  case TINY_BLOB:
338  ret = "TINY_BLOB"; break;
339  case BLOB:
340  ret = "BLOB" ; break;
341  case POINTER:
342  ret = "PTR" ; break;
343  }
344 
345  return ret;
346 }
347 
348 
350 {
351  switch(type) {
352  case STRING:
353  return true; break;
354  case TINY_BLOB:
355  return true; break;
356  case BLOB:
357  return true; break;
358  default:
359  return false; break;
360  }
361 }
362 
363 
364 bool mcs::IntType(Types type)
365 {
366  if (
367  (type == TINY) ||
368  (type == SMALL) ||
369  (type == MEDIUM) ||
370  (type == INT) ||
371  (type == BIGINT)
372  )
373  return true;
374  else
375  return false;
376 }
377 
378 
380 {
381  if (
382  (type == FLOAT) ||
383  (type == DOUBLE)
384  )
385  return true;
386  else
387  return false;
388 }
389 
390 
391 
392 #if ENABLE_MYSQL
393 string mcs::MYSQL2Str(enum_field_types type)
394 {
395  string ret;
396 
397  switch (type) {
398  case MYSQL_TYPE_TINY:
399  ret = "TINYINT"; break;
400  case MYSQL_TYPE_SHORT:
401  ret = "SMALLINT"; break;
402  case MYSQL_TYPE_INT24:
403  ret = "MEDIUMINT"; break;
404  case MYSQL_TYPE_LONG:
405  ret = "INT"; break;
406  case MYSQL_TYPE_LONGLONG:
407  ret = "BIGINT"; break;
408  case MYSQL_TYPE_FLOAT:
409  ret = "FLOAT"; break;
410  case MYSQL_TYPE_DOUBLE:
411  ret = "DOUBLE"; break;
412  case MYSQL_TYPE_STRING:
413  ret = "CHAR"; break;
414  case MYSQL_TYPE_VAR_STRING:
415  ret = "CHAR"; break;
416  case MYSQL_TYPE_TIME:
417  ret = "TIME"; break;
418  case MYSQL_TYPE_DATE:
419  ret = "TIME"; break;
420  case MYSQL_TYPE_DATETIME:
421  ret = "TIME"; break;
422  case MYSQL_TYPE_TIMESTAMP:
423  ret = "TIME"; break;
424  case MYSQL_TYPE_TINY_BLOB:
425  ret = "TINYBLOB"; break;
426  case MYSQL_TYPE_BLOB:
427  ret = "BLOB"; break;
428  default:
429  ret ="";
430  }
431 
432  return ret;
433 }
434 
435 
436 bool mcs::MYSQL2Types(enum_field_types mtype, Types& type)
437 {
438  switch (mtype) {
439  case MYSQL_TYPE_TINY:
440  type = TINY; break;
441  case MYSQL_TYPE_SHORT:
442  type = SMALL; break;
443  case MYSQL_TYPE_INT24:
444  type = MEDIUM; break;
445  case MYSQL_TYPE_LONG:
446  type = INT; break;
447  case MYSQL_TYPE_LONGLONG:
448  type = BIGINT; break;
449  case MYSQL_TYPE_FLOAT:
450  type = FLOAT; break;
451  case MYSQL_TYPE_DOUBLE:
452  type = DOUBLE; break;
453  case MYSQL_TYPE_STRING:
454  type = STRING; break;
455  case MYSQL_TYPE_VAR_STRING:
456  type = STRING; break;
457  case MYSQL_TYPE_TIME:
458  type = TIME; break;
459  case MYSQL_TYPE_DATE:
460  type = TIME; break;
461  case MYSQL_TYPE_DATETIME:
462  type = TIME; break;
463  case MYSQL_TYPE_TIMESTAMP:
464  type = TIME; break;
465  case MYSQL_TYPE_TINY_BLOB:
466  type = TINY_BLOB; break;
467  case MYSQL_TYPE_BLOB:
468  type = BLOB; break;
469  default:
470  return false; break;
471  }
472 
473  return true;
474 }
475 
476 
477 bool mcs::Types2MYSQL(Types& type, enum_field_types& mtype)
478 {
479  switch (type) {
480  case TINY:
481  mtype = MYSQL_TYPE_TINY; break;
482  case SMALL:
483  mtype = MYSQL_TYPE_SHORT; break;
484  case MEDIUM:
485  mtype = MYSQL_TYPE_INT24; break;
486  case INT:
487  mtype = MYSQL_TYPE_LONG; break;
488  case BIGINT:
489  mtype = MYSQL_TYPE_LONGLONG; break;
490  case FLOAT:
491  mtype = MYSQL_TYPE_FLOAT; break;
492  case DOUBLE:
493  mtype = MYSQL_TYPE_DOUBLE; break;
494  case STRING:
495  mtype = MYSQL_TYPE_STRING; break;
496  case TIME:
497  mtype = MYSQL_TYPE_DATETIME; break;
498  case TINY_BLOB:
499  mtype = MYSQL_TYPE_TINY_BLOB; break;
500  case BLOB:
501  mtype = MYSQL_TYPE_BLOB; break;
502  default:
503  return false; break;
504  }
505 
506  return true;
507 }
508 
509 string mcs::Types2MYSQLStr(Types& type, bool isunsigned)
510 {
511  enum enum_field_types mtype;
512  string ret="";
513 
514  if (Types2MYSQL(type, mtype)) {
515  ret = MYSQL2Str(mtype);
516  }
517 
518  if (isunsigned)
519  ret += " UNSIGNED";
520 
521  return ret;
522 }
523 
524 
525 #if ENABLE_CFITSIO
526 bool mcs::FITS2Types(int fits, Types& dbt, bool& isunsigned)
527 {
528  isunsigned = false;
529  switch (fits) {
530  case TLOGICAL:
531  dbt = TINY; isunsigned = true ; break;
532  case TBYTE:
533  dbt = TINY; isunsigned = true ; break;
534  case TSBYTE:
535  dbt = TINY; ; break;
536  case TSHORT:
537  dbt = SMALL; ; break;
538  case TUSHORT:
539  dbt = SMALL; isunsigned = true ; break;
540  case TINT:
541  dbt = INT; ; break;
542  case TLONG:
543  dbt = INT; ; break;
544  case TUINT:
545  dbt = INT; isunsigned = true ; break;
546  case TULONG:
547  dbt = INT; isunsigned = true ; break;
548  case TLONGLONG:
549  dbt = BIGINT; ; break;
550  case TFLOAT:
551  dbt = FLOAT; break;
552  case TDOUBLE:
553  dbt = DOUBLE; break;
554  case TSTRING:
555  dbt = STRING; break;
556  default:
557  return false;
558  }
559 
560  return true;
561 }
562 
563 
564 bool mcs::Types2FITS(Types dbt, bool isunsigned, int& fits)
565 {
566  switch (dbt) {
567  case TINY:
568  if (isunsigned) fits = TBYTE;
569  else fits = TSHORT;
570  break;
571  case SMALL:
572  if (isunsigned) fits = TLONG;
573  else fits = TSHORT;
574  break;
575  case MEDIUM:
576  if (isunsigned) fits = TLONGLONG;
577  else fits = TLONG;
578  break;
579  case INT :
580  if (isunsigned) fits = TLONGLONG;
581  else fits = TLONG;
582  break;
583  case BIGINT:
584  if (isunsigned) return false;
585  else fits = TLONGLONG;
586  break;
587  case FLOAT:
588  fits = TFLOAT; break;
589  case DOUBLE:
590  fits = TDOUBLE; break;
591  case STRING:
592  fits = TSTRING; break;
593  case TIME: //Substitute blanks with 't'
594  fits = TSTRING; break;
595  default:
596  return false;
597  }
598 
599  return true;
600 }
601 
602 
603 bool mcs::Types2S_FITS(Types dbt, int len, bool isunsigned, string& fits)
604 {
605  switch (dbt) {
606 // case TINY:
607 // if (isunsigned) fits = "1B";
608 // else fits = "1S";
609 // break;
610 // case SMALL:
611 // if (isunsigned) fits = "1U";
612 // else fits = "1I";
613 // break;
614 // case INT :
615 // if (isunsigned) fits = "1V";
616 // else fits = "1J";
617 // break;
618  case TINY:
619  if (isunsigned) fits = "1B";
620  else fits = "1I";
621  break;
622  case SMALL:
623  if (isunsigned) fits = "1J";
624  else fits = "1I";
625  break;
626  case MEDIUM :
627  if (isunsigned) fits = "1K";
628  else fits = "1J";
629  case INT :
630  if (isunsigned) fits = "1K";
631  else fits = "1J";
632  break;
633  case BIGINT:
634  if (isunsigned) return false;
635  else fits = "1K"; break;
636  case FLOAT:
637  fits = "1E"; break;
638  case DOUBLE:
639  fits = "1D"; break;
640  case STRING:
641  fits = itos(len) + "A"; break;
642  case TIME:
643  fits = "20A"; break; //TODO: Implement
644  default:
645  return false;
646  }
647 
648  return true;
649 }
650 #endif
651 #endif
652 
653 
654 
655 
656 unsigned int mcs::Data::howManyDim()
657 { return ldimspec & 15; }
658 
659 
660 
661 unsigned int mcs::Data::varyingDim()
662 { return ldimspec >> 4; }
663 
664 
665 
666 string buildDimSpec(int ldimspec, const unsigned short int ldim[MCS_DATA_NDIM])
667 {
668  string s = "";
669  int i;
670  int howManyDim = ldimspec & 15;
671  int varyingDim = ldimspec >> 4;
672 
673  for (i=0; (i<howManyDim) || (i<varyingDim); i++) {
674  if (i > 0) s += "x";
675  s += itos(ldim[i]);
676  }
677 
678  if ((i > 0) &&
679  (i == varyingDim))
680  s += "*";
681 
682  return s;
683 }
684 
685 
686 //NOTE: If this method is called on a variable length based Data
687 //object the initial "maxLength" given in init() will be overrided
688 void mcs::Data::resize(string dimSpec)
689 {
690  string err = "";
691  unsigned int i;
692  unsigned char howManyDim, varyingDim;
693  howManyDim = 0;
694  varyingDim = 0;
695 
696  if (dimSpec == "")
697  return;
698 
699  //Multi-dimensional array are a VOTable feature, they're not allowed
700  //on the DB side.
701  if (lbind)
702  throw MCS_ERROR( MSG_CANT_BIND_AND_HAVE_DIMSPEC );
703 
704  //Initialize all dim-related variables
705  for (i=0; i<MCS_DATA_NDIM; i++)
706  ldim[i] = 1;
707 
708  ldimspec = 0;
709  arrsize = 1;
710  arrpos = 0;
711 
712  //Split the spec at "x"
713  vector<string> values = split(dimSpec, "x");
714  if (values.size() > MCS_DATA_NDIM)
715  throw MCS_ERROR( MSG_TOO_MANY_DIMSPEC, MCS_DATA_NDIM);
716 
717  //Analyze all dimension specs
718  for (i=0; i<values.size(); i++) {
719  string s = values[i];
720 
721  //In a dimension spec there can be a '*', meaning that effective
722  //size will be determined during data reading.
723  if (strchr(s.c_str(), '*')) {
724 
725  if (i != values.size() - 1)
726  throw MCS_ERROR( MSG_VARYING_MUST_BE_LAST );
727 
728  //So this dimension can change its size, set varyingDim...
729  varyingDim = i + 1;
730 
731  //If a number is present then it will be the maximum size,
732  //else the size is completely dynamic.
733  //Remove the '*'
734  s.replace(s.find("*", 0), 1, " ");
735 
736  ldim[i] = mcs::stoi(s, 1);
737  }
738  else
739  ldim[i] = mcs::stoi(s);
740 
741  howManyDim++;
742  }
743 
744 
745  if (VarLenType(ltype)) {
746  //If the type is a STRING then the first dimension is to be taken
747  //as "maxLength" (see VOTable docs)
748  if (ltype == STRING) {
749  lmaxlength = ldim[0];
750 
751  //Shift all other dimensions
752  for (i=0; i<MCS_DATA_NDIM-2; i++)
753  ldim[i] = ldim[i+1];
754 
755  ldim[MCS_DATA_NDIM-1] = 1;
756  howManyDim--;
757 
758  lmaxlength++; //Need to allocate space for NULL character
759  }
760  else
761  lmaxlength = 1; //Lengths are completely driven by dim spec
762  }
763 
764  reallocBuffer();
765 
766  if (ltype == STRING) //See analogous note in Data::init
767  lmaxlength--;
768 
769  llength = lmaxlength;
770 
771  ldimspec = (varyingDim << 4) + howManyDim;
772 
773  mult[0] = 1;
774  for (i=1; i<MCS_DATA_NDIM-1; i++)
775  mult[i] = mult[i-1] * ldim[i-1];
776 }
777 
778 
779 
781  const int i2,
782  const int i3,
783  const int i4,
784  const int i5,
785  const int i6,
786  const int i7,
787  const int i8,
788  const int i9,
789  const int i10,
790  const int i11,
791  const int i12,
792  const int i13,
793  const int i14,
794  const int i15)
795 {
796  array(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15);
797  return *this;
798 }
799 
800 
801 unsigned int mcs::Data::array(unsigned short int i1,
802  unsigned short int i2,
803  unsigned short int i3,
804  unsigned short int i4,
805  unsigned short int i5,
806  unsigned short int i6,
807  unsigned short int i7,
808  unsigned short int i8,
809  unsigned short int i9,
810  unsigned short int i10,
811  unsigned short int i11,
812  unsigned short int i12,
813  unsigned short int i13,
814  unsigned short int i14,
815  unsigned short int i15)
816 {
817  if (ldim[0] <= i1)
818  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 1, i1);
819 
820  if (ldim[1] <= i2)
821  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 2, i2);
822 
823  if (ldim[2] <= i3)
824  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 3, i3);
825 
826  if (ldim[3] <= i4)
827  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 4, i4);
828 
829  if (ldim[4] <= i5)
830  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 5, i5);
831 
832  if (ldim[5] <= i6)
833  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 6, i6);
834 
835  if (ldim[6] <= i7)
836  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 7, i7);
837 
838  if (ldim[7] <= i8)
839  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 8, i8);
840 
841  if (ldim[8] <= i9)
842  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 9, i9);
843 
844  if (ldim[9] <= i10)
845  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 10, i10);
846 
847  if (ldim[10] <= i11)
848  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 11, i11);
849 
850  if (ldim[11] <= i12)
851  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 12, i12);
852 
853  if (ldim[12] <= i13)
854  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 13, i13);
855 
856  if (ldim[13] <= i14)
857  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 14, i14);
858 
859  if (ldim[14] <= i15)
860  throw MCS_ERROR(MSG_WRONG_DIM_SPEC, 15, i15);
861 
862  arrpos =
863  i1 * mult[ 0] +
864  i2 * mult[ 1] +
865  i3 * mult[ 2] +
866  i4 * mult[ 3] +
867  i5 * mult[ 4] +
868  i6 * mult[ 5] +
869  i7 * mult[ 6] +
870  i8 * mult[ 7] +
871  i9 * mult[ 8] +
872  i10 * mult[ 9] +
873  i11 * mult[10] +
874  i12 * mult[11] +
875  i13 * mult[12] +
876  i14 * mult[13] +
877  i15 * mult[14];
878 
879 
880  //i1 +
881  // i2 * ldim[0 ] +
882  // i3 * ldim[0 ] * ldim[1 ] +
883  // i4 * ldim[0 ] * ldim[1 ] * ldim[2 ] +
884  // i5 * ldim[0 ] * ldim[1 ] * ldim[2 ] * ldim[3 ] +
885  // i6 * ldim[0 ] * ldim[1 ] * ldim[2 ] * ldim[3 ] * ldim[4 ] +
886 
887  return arrpos;
888 }
889 
890 
891 
892 
893 unsigned short int mcs::Data::dim(int d)
894 {
895  // 1 <= d <= MCS_DATA_NDIM
896  if (d < 1)
897  return 0;
898  else if (d > MCS_DATA_NDIM)
899  return 0;
900  else
901  return ldim[d-1];
902 }
903 
904 
905 unsigned int mcs::Data::arraySize()
906 {
907  return arrsize;
908 }
909 
910 
911 
912 
913 void mcs::Data::resizeVaryingDim(unsigned short int newsize)
914 {
915  if (newsize == 0)
916  return;
917 
918  if (varyingDim() == 0)
919  throw MCS_ERROR( MSG_NO_DIM_ALLOWED_TO_CHANGE );
920 
921  //Set new dimension
922  ldim[varyingDim() - 1] = newsize;
923 
924  reallocBuffer();
925 }
926 
927 
928 
929 void mcs::Data::reallocBuffer()
930 {
931  unsigned int old_bufsize = bufsize;
932 
933  //Calculate new array size
934  arrsize = 1;
935  for (int i=0; i<MCS_DATA_NDIM; i++)
936  arrsize *= ldim[i];
937 
938  bufsize = lmaxlength * arrsize;
939 
940  if (buf == NULL) { //First time
941  buf = (char*) malloc(bufsize);
942  memset(buf, 0, bufsize);
943  }
944  else {
945  buf = (char*) realloc(buf, bufsize);
946 
947  if (bufsize > old_bufsize) {
948  //Set newly allocated memory to zero
949  memset(buf + old_bufsize, 0, bufsize - old_bufsize);
950  }
951  }
952 }
953 
954 
955 
956 void mcs::Data::init(MYSQL_BIND* bind, Types type, const char* name,
957  unsigned short int maxLength, bool isunsigned,
958  unsigned int flags)
959 {
960  MCS_DEBUG_SETUP(0, "Data");
961 
962  buf = NULL;
963  bufsize = 0;
964  ltype = type;
965  lname = string(name);
966  lisunsigned = isunsigned;
967  lisnull = false;
968  lautoincr = (bool) (flags & AUTO_INCREMENT_FLAG);
969  lflags = flags;
970  tag = 0;
971  setSourceID(MCS_ID_UNKNOWN);
972  setDestID(MCS_ID_UNKNOWN);
973 
974 
975  //By default this object has no dimensions and no dimension should be varying
976  ldimspec = 0;
977  arrsize = 1;
978  arrpos = 0;
979  for (int i=0; i<MCS_DATA_NDIM; i++)
980  ldim[i] = 1;
981 
982 
983  switch (ltype) {
984  case TINY:
985  lmaxlength = sizeof(char); break;
986  case SMALL:
987  lmaxlength = sizeof(short int); break;
988  case MEDIUM:
989  lmaxlength = sizeof(int); break;
990  case INT :
991  lmaxlength = sizeof(int); break;
992  case BIGINT:
993  lmaxlength = sizeof(long long int); break;
994  case FLOAT:
995  lmaxlength = sizeof(float); break;
996  case DOUBLE:
997  lmaxlength = sizeof(double); break;
998  case STRING:
999  lmaxlength = sizeof(char) * maxLength;
1000  lmaxlength++; //Need to allocate space for NULL character
1001  break;
1002  case TIME:
1003  /*
1004  sizeof(MYSQL_TIME) is 36 on a 32bit processor, while it is 40 on
1005  a 64bit. This is due to the member <unsigned long second_part>
1006  of the structure, which will (not yet used) contain the
1007  fractional part of a second.
1008  */
1009  lmaxlength = sizeof(MYSQL_TIME);
1010  break;
1011  case TINY_BLOB:
1012  lmaxlength = sizeof(char) * maxLength;break;
1013  case BLOB:
1014  lmaxlength = sizeof(char) * maxLength;break;
1015  case POINTER:
1016  lmaxlength = sizeof(void*); break;
1017  default:
1018  throw MCS_ERROR(MSG_TYPE_NOT_HANDLED, 0, ltype);
1019  }
1020 
1021  reallocBuffer();
1022 
1023  if (ltype == STRING)
1024  lmaxlength--; //Consider only the buffer without the trailing NULL.
1025  //That's because the NULL is needed only on C side,
1026  //not on mysql or user side.
1027 
1028  if (ltype == TIME)
1029  dt.setMysqlBuffer((MYSQL_TIME*) buf);
1030 
1031 
1032  llength = lmaxlength;
1033 
1034 #if ENABLE_MYSQL
1035  enum_field_types mytype;
1036  Types2MYSQL(ltype, mytype);
1037 
1038  lbind = bind;
1039  if (lbind) {
1040  memset(lbind, 0, sizeof(MYSQL_BIND));
1041  lbind->buffer = buf;
1042 
1043  lbind->buffer_type =
1044  (mytype == MYSQL_TYPE_INT24 ? MYSQL_TYPE_LONG : mytype);
1045 
1046  lbind->buffer_length = lmaxlength;
1047  lbind->is_unsigned = lisunsigned;
1048  lbind->is_null = &lisnull;
1049  lbind->length = &llength;
1050  }
1051 #endif
1052 }
1053 
1054 
1055 
1056 mcs::Data::Data() : Serializable(MCS_SERIAL_BUFFER)
1057 {
1058  init(NULL, STRING);
1059  setNull();
1060  setTag(0);
1061 }
1062 
1063 
1064 mcs::Data::Data(MYSQL_BIND* bind, Types type, const char* name,
1065  unsigned short int maxLength, bool isunsigned,
1066  unsigned int flags, unsigned char tag)
1067  : Serializable(MCS_SERIAL_BUFFER)
1068 
1069 {
1070  init(bind, type, name, maxLength, isunsigned, flags);
1071  setTag(tag);
1072  MCS_DEBUG("-> " << sval());
1073 }
1074 
1075 
1076 mcs::Data::Data(Types type, unsigned short int maxLength, bool isunsigned,
1077  string dimSpec)
1078  : Serializable(MCS_SERIAL_BUFFER)
1079 {
1080  MCS_DEBUG("-> ");
1081  init(NULL, type, "", maxLength, isunsigned, 0);
1082  resize(dimSpec);
1083  MCS_DEBUG("<- ");
1084 }
1085 
1086 
1087 
1089  : Serializable(MCS_SERIAL_BUFFER)
1090 {
1091  MCS_DEBUG("-> ");
1092  //cout << endl << endl << "Copy Constructor" << endl << endl;
1093 
1094  init(0,
1095  from.ltype,
1096  (char*) from.lname.c_str(),
1097  from.lmaxlength,
1098  from.lisunsigned,
1099  from.lflags);
1100 
1101  resize(buildDimSpec(from.ldimspec, from.ldim));
1102 
1103  memcpy(buf, from.buf, lmaxlength * arrsize);
1104  llength = from.llength;
1105  setTag(from.tag);
1106  lisnull = from.lisnull;
1107  lautoincr = from.lautoincr;
1108  MCS_DEBUG("<-");
1109 }
1110 
1111 
1112 mcs::Data::Data(int v, unsigned char tag)
1113  : Serializable(MCS_SERIAL_BUFFER)
1114 {
1115  init(NULL, INT, "", 0, false, 0);
1116  setival(v);
1117  setTag(tag);
1118  MCS_DEBUG("-> " << sval());
1119 }
1120 
1121 
1122 mcs::Data::Data(long long int v, unsigned char tag)
1123  : Serializable(MCS_SERIAL_BUFFER)
1124 {
1125  init(NULL, BIGINT, "", 0, false, 0);
1126  setlval(v);
1127  setTag(tag);
1128  MCS_DEBUG("-> " << sval());
1129 }
1130 
1131 
1132 mcs::Data::Data(double v, unsigned char tag)
1133  : Serializable(MCS_SERIAL_BUFFER)
1134 {
1135  init(NULL, DOUBLE, "", 0, false, 0);
1136  setdval(v);
1137  setTag(tag);
1138  MCS_DEBUG("-> " << sval());
1139 }
1140 
1141 
1142 mcs::Data::Data(string v, unsigned char tag)
1143  : Serializable(MCS_SERIAL_BUFFER)
1144 {
1145  init(NULL, STRING, "", v.length(), false, 0);
1146  if (v.length())
1147  setsval(v);
1148  else
1149  setNull();
1150  setTag(tag);
1151  MCS_DEBUG("-> " << sval());
1152 }
1153 
1154 mcs::Data::Data(struct tm v, unsigned char tag)
1155  : Serializable(MCS_SERIAL_BUFFER)
1156 {
1157  init(NULL, TIME, "", 0, false, 0);
1158  settimeval(v);
1159  setTag(tag);
1160  MCS_DEBUG("-> " << sval());
1161 }
1162 
1163 mcs::Data::Data(time_t v, unsigned char tag)
1164  : Serializable(MCS_SERIAL_BUFFER)
1165 {
1166  init(NULL, TIME, "", 0, false, 0);
1167  settimeval(v);
1168  setTag(tag);
1169  MCS_DEBUG("-> " << sval());
1170 }
1171 
1172 
1173 
1175 {
1176  if (buf)
1177  free(buf);
1178 }
1179 
1181 { lname = ""; }
1182 
1183 
1184 const char* mcs::Data::ifmt = "%d";
1185 const char* mcs::Data::lfmt = "%ld";
1186 const char* mcs::Data::ffmt = "%f";
1187 const char* mcs::Data::dfmt = "%lf";
1188 const char* mcs::Data::dtfmt = "%04d-%02d-%02d %02d:%02d:%02g";
1189 const char* mcs::Data::dafmt = "%04d-%02d-%02d";
1190 const char* mcs::Data::tmfmt = "%02d:%02d:%02g";
1191 
1192 
1193 string mcs::Data::name() { return lname; }
1194 void mcs::Data::setName(string name) { lname = name; }
1195 //unsigned int mcs::Data::flags() { return lflags; }
1197 unsigned short int mcs::Data::maxLength() { return lmaxlength; }
1198 unsigned short int mcs::Data::length() { return (unsigned short int) llength; }
1200 bool mcs::Data::isNull() { return lisnull; }
1202 void* mcs::Data::buffer() const {
1203  unsigned int pos = arrpos;
1204  return (buf + pos * (lmaxlength + (ltype == STRING ? 1 : 0)));
1205 }
1206 
1207 
1208 
1209 int mcs::Data::ival() const
1210 {
1211  char* buf = (char*) buffer();
1212  int ret;
1213 
1214  switch (ltype) {
1215  case TINY:
1216  if (lisunsigned) ret = (*((unsigned char* ) buf));
1217  else ret = (*((char* ) buf));
1218  break;
1219  case SMALL:
1220  if (lisunsigned) ret = (*((unsigned short int* ) buf));
1221  else ret = (*((short int* ) buf));
1222  break;
1223  case MEDIUM :
1224  if (lisunsigned) ret = (*((unsigned int* ) buf));
1225  else ret = (*((int* ) buf));
1226  break;
1227  case INT :
1228  if (lisunsigned) ret = (*((unsigned int* ) buf));
1229  else ret = (*((int* ) buf));
1230  break;
1231  case BIGINT:
1232  if (lisunsigned) ret = (*((unsigned long long int*) buf));
1233  else ret = (*((long long int* ) buf));
1234  break;
1235  case FLOAT:
1236  ret = (int) rintf(*((float*) buf));
1237  break;
1238  case DOUBLE:
1239  ret = (int) rint(*((double*) buf));
1240  break;
1241  case STRING:
1242  if (sscanf(buf, ifmt, &ret) != 1)
1243  throw MCS_ERROR(MSG_CONVERSION_STRING_INT);
1244  break;
1245  case TIME:
1246  return (int) tval();
1247  break;
1248  case TINY_BLOB:
1249  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1250  break;
1251  case BLOB:
1252  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1253  break;
1254  case POINTER:
1255  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1256  break;
1257  }
1258 
1259 
1260  switch (ltype) {
1261  case TINY:
1262  if (lisunsigned) ret = (*((unsigned char* ) buf));
1263  else ret = (*((char* ) buf));
1264  break;
1265  case SMALL:
1266  if (lisunsigned) ret = (*((unsigned short int* ) buf));
1267  else ret = (*((short int* ) buf));
1268  break;
1269  case MEDIUM :
1270  if (lisunsigned) ret = (*((unsigned int* ) buf));
1271  else ret = (*((int* ) buf));
1272  break;
1273  case INT :
1274  if (lisunsigned) ret = (*((unsigned int* ) buf));
1275  else ret = (*((int* ) buf));
1276  break;
1277  case BIGINT:
1278  if (lisunsigned) ret = (*((unsigned long long int*) buf));
1279  else ret = (*((long long int* ) buf));
1280  break;
1281  case FLOAT:
1282  ret = (int) rintf(*((float*) buf));
1283  break;
1284  case DOUBLE:
1285  ret = (int) rint(*((double*) buf));
1286  break;
1287  case STRING:
1288  if (sscanf(buf, ifmt, &ret) != 1)
1289  throw MCS_ERROR(MSG_CONVERSION_STRING_INT);
1290  break;
1291  case TIME:
1292  return (int) tval();
1293  break;
1294  case TINY_BLOB:
1295  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1296  break;
1297  case BLOB:
1298  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1299  break;
1300  case POINTER:
1301  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1302  break;
1303  }
1304 
1305  return ret;
1306 }
1307 
1308 
1309 unsigned int mcs::Data::uival() const
1310 {
1311  char* buf = (char*) buffer();
1312  unsigned int ret;
1313 
1314  switch (ltype) {
1315  case TINY:
1316  if (lisunsigned) ret = (*((unsigned char* ) buf));
1317  else ret = (*((char* ) buf));
1318  break;
1319  case SMALL:
1320  if (lisunsigned) ret = (*((unsigned short int* ) buf));
1321  else ret = (*((short int* ) buf));
1322  break;
1323  case MEDIUM :
1324  if (lisunsigned) ret = (*((unsigned int* ) buf));
1325  else ret = (*((int* ) buf));
1326  break;
1327  case INT :
1328  if (lisunsigned) ret = (*((unsigned int* ) buf));
1329  else ret = (*((int* ) buf));
1330  break;
1331  case BIGINT:
1332  if (lisunsigned) ret = (*((unsigned long long int*) buf));
1333  else ret = (*((long long int* ) buf));
1334  break;
1335  case FLOAT:
1336  ret = (unsigned int) rintf(*((float*) buf));
1337  break;
1338  case DOUBLE:
1339  ret = (unsigned int) rint(*((double*) buf));
1340  break;
1341  case STRING:
1342  if (sscanf(buf, ifmt, &ret) != 1)
1343  throw MCS_ERROR(MSG_CONVERSION_STRING_INT);
1344  break;
1345  case TIME:
1346  return (unsigned int) tval();
1347  case TINY_BLOB:
1348  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1349  break;
1350  case BLOB:
1351  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1352  break;
1353  case POINTER:
1354  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1355  break;
1356  }
1357 
1358  return ret;
1359 }
1360 
1361 
1362 long long int mcs::Data::lval() const
1363 {
1364  char* buf = (char*) buffer();
1365  long long int ret;
1366 
1367  switch (ltype) {
1368  case TINY :
1369  case SMALL :
1370  case MEDIUM:
1371  case INT :
1372  if (lisunsigned) ret = uival();
1373  else ret = ival();
1374  break;
1375  case BIGINT:
1376  if (lisunsigned)
1377  ret = (*((unsigned long long int*) buf));
1378  else
1379  ret = (*((long long int*) buf));
1380  break;
1381  case FLOAT : ret = (long long int) rintf(*((float*) buf)); break;
1382  case DOUBLE: ret = (long long int) rint(*((double*) buf)); break;
1383  case TIME : ret = (long long int) tval(); break;
1384  case STRING:
1385  if (sscanf(buf, lfmt, &ret) != 1)
1386  throw MCS_ERROR(MSG_CONVERSION_STRING_INT);
1387  break;
1388  case TINY_BLOB:
1389  case BLOB:
1390  case POINTER:
1391  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1392  }
1393  return ret;
1394 }
1395 
1396 
1397 unsigned long long int mcs::Data::ulval() const
1398 {
1399  char* buf = (char*) buffer();
1400  unsigned long long int ret;
1401  //Same as preceding routine
1402 
1403  switch (ltype) {
1404  case TINY :
1405  case SMALL :
1406  case MEDIUM:
1407  case INT :
1408  if (lisunsigned) ret = uival();
1409  else ret = ival();
1410  break;
1411  case BIGINT:
1412  if (lisunsigned)
1413  ret = (*((unsigned long long int*) buf));
1414  else
1415  ret = (*((long long int*) buf));
1416  break;
1417  case FLOAT : ret = (long long int) rintf(*((float*) buf)); break;
1418  case DOUBLE: ret = (long long int) rint(*((double*) buf)); break;
1419  case TIME : ret = (long long int) tval(); break;
1420  case STRING:
1421  if (sscanf(buf, lfmt, &ret) != 1)
1422  throw MCS_ERROR(MSG_CONVERSION_STRING_INT);
1423  break;
1424  case TINY_BLOB:
1425  case BLOB:
1426  case POINTER:
1427  throw MCS_ERROR(MSG_CONVERSION_BLOB_INT);
1428  }
1429 
1430  return ret;
1431 }
1432 
1433 
1434 float mcs::Data::fval() const
1435 {
1436  char* buf = (char*) buffer();
1437  float ret;
1438 
1439  switch (ltype) {
1440  case TINY :
1441  case SMALL :
1442  case MEDIUM:
1443  case INT :
1444  case BIGINT:
1445  case TIME :
1446  if (lisunsigned) ret = ulval();
1447  else ret = lval();
1448  break;
1449  case FLOAT: ret = (*((float*) buf)); break;
1450  case DOUBLE: ret = (float) (*((double*) buf)); break;
1451  case STRING:
1452  if (sscanf(buf, ffmt, &ret) != 1)
1453  throw MCS_ERROR(MSG_CONVERSION_STRING_FLOAT);
1454  break;
1455  case TINY_BLOB:
1456  case BLOB:
1457  case POINTER:
1458  throw MCS_ERROR(MSG_CONVERSION_BLOB_FLOAT);
1459  }
1460 
1461  return ret;
1462 }
1463 
1464 
1465 double mcs::Data::dval() const
1466 {
1467  char* buf = (char*) buffer();
1468  double ret;
1469 
1470  switch (ltype) {
1471  case TINY :
1472  case SMALL :
1473  case MEDIUM:
1474  case INT :
1475  case BIGINT:
1476  case TIME :
1477  if (lisunsigned) ret = ulval();
1478  else ret = lval();
1479  break;
1480  case FLOAT: ret = fval(); break;
1481  case DOUBLE: ret = (*((double*) buf)); break;
1482  case STRING:
1483  if (sscanf(buf, dfmt, &ret) != 1)
1484  throw MCS_ERROR(MSG_CONVERSION_STRING_FLOAT);
1485  break;
1486  case TINY_BLOB:
1487  case BLOB:
1488  case POINTER:
1489  throw MCS_ERROR(MSG_CONVERSION_BLOB_FLOAT);
1490  }
1491 
1492  return ret;
1493 }
1494 
1495 
1496 
1497 
1498 
1499 //void mcs::Data::MySQL_TIME_2_time_t(MYSQL_TIME* mtime, time_t* t)
1500 //{
1501 // struct tm tm;
1502 // memset(&tm, '\0', sizeof(tm));
1503 //
1504 // tm.tm_sec = mtime->second;
1505 // tm.tm_min = mtime->minute;
1506 // tm.tm_hour = mtime->hour;
1507 // tm.tm_mday = mtime->day;
1508 // tm.tm_mon = mtime->month - 1;
1509 // tm.tm_year = mtime->year - 1900;
1510 //
1511 // switch (dbtimemode) {
1512 // case GMT:
1513 // *t = timegm(&tm);
1514 // break;
1515 // case LOCAL:
1516 // *t = timelocal(&tm);
1517 // break;
1518 // }
1519 //}
1520 //
1521 //void mcs::Data::time_t_2_MySQL_TIME(time_t* t, MYSQL_TIME* mtime)
1522 //{
1523 // struct tm tm;
1524 // time_t lt = *t;
1525 // int fl = 0;
1526 //
1527 // while ( (fl == 0) ||
1528 // ((fl == 1) && (tm.tm_isdst))
1529 // ) {
1530 // switch (dbtimemode) {
1531 // case GMT:
1532 // gmtime_r(&lt, &tm);
1533 // break;
1534 // case LOCAL:
1535 // localtime_r(&lt, &tm);
1536 // break;
1537 // }
1538 // if (tm.tm_isdst) lt -= 3600;
1539 // fl++;
1540 // }
1541 //
1542 // mtime->second = tm.tm_sec ;
1543 // mtime->minute = tm.tm_min ;
1544 // mtime->hour = tm.tm_hour;
1545 // mtime->day = tm.tm_mday;
1546 // mtime->month = tm.tm_mon + 1;
1547 // mtime->year = tm.tm_year + 1900 ;
1548 //}
1549 
1550 
1551 
1552 
1553 
1554 
1555 string mcs::Data::sval(bool addWhiteSpaces) const
1556 {
1557  char* buf = (char*) buffer();
1558  char lbuf[30];
1559  long long int l;
1560  unsigned long long int ul;
1561  float f;
1562  double d;
1563  string ret;
1564 
1565  if (ltype == TINY ||
1566  ltype == SMALL ||
1567  ltype == MEDIUM ||
1568  ltype == INT
1569  ) {
1570  l = lval();
1571  sprintf(lbuf, ifmt, l);
1572  }
1573 
1574  else if (ltype == BIGINT) {
1575  if (lisunsigned) {
1576  l = lval();
1577  sprintf(lbuf, lfmt, l);
1578  }
1579  else {
1580  ul = ulval();
1581  sprintf(lbuf, lfmt, ul);
1582  }
1583  }
1584  else if (ltype == FLOAT) {
1585  f = fval();
1586  sprintf(lbuf, ffmt, f);
1587  }
1588  else if (ltype == DOUBLE) {
1589  d = dval();
1590  sprintf(lbuf, dfmt, d);
1591  }
1592  else if (ltype == TIME) {
1593  ret = (string) dt;
1594  //time_t t;
1595  //struct tm tm;
1596  //MySQL_TIME_2_time_t((MYSQL_TIME*) buf, &t);
1597  //localtime_r(&t, &tm);
1598  //strftime(lbuf, 30, "%F %T", &tm);
1599  }
1600  else if (ltype == STRING) {
1601  ret = string(buf); //, lmaxlength);
1602  if (! addWhiteSpaces)
1603  ret = trim(ret);
1604  }
1605  else if ((ltype == BLOB) || (ltype == TINY_BLOB)) {
1606  ret = hexDump(buf, llength);
1607  }
1608  if (ltype != STRING && ltype != TIME)
1609  ret = string(lbuf);
1610 
1611  ret = trim(ret);
1612  return ret;
1613 }
1614 
1615 
1616 int mcs::Data::cval(char* c, int maxlength) const
1617 {
1618  string s = sval();
1619  int l = s.length();
1620 
1621  if (l < maxlength) {
1622  memcpy(c, s.c_str(), l+1);
1623  return l;
1624  }
1625  else
1626  return 0;
1627 }
1628 
1629 
1630 
1631 void* mcs::Data::pval() const
1632 {
1633  void* p;
1634  memcpy(&p, buf, sizeof(void*));
1635  return p;
1636 }
1637 
1638 void mcs::Data::setpval(void* p)
1639 {
1640  memcpy(buf, &p, sizeof(void*));
1641 }
1642 
1643 
1644 
1645 
1646 /*
1647  Notes on TIME data type.
1648 
1649  MySQL handle 4 field type: MYSQL_TYPE_TIME, MYSQL_TYPE_DATE,
1650  MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP. In any case data is returned
1651  as a MySQL_TIME structure in local time zone. Also upon writing on DB data
1652  must be in local time zone.
1653 
1654  When converting to/from other data types we assume that:
1655  - strings express datetime in local time zone;
1656  - numbers express the number of seconds elapsed since 1970-01-01 00:00:00
1657  UTC.
1658 
1659 
1660  When a Data(TIME) object is serialized data are converted to MCS_TIME. It is
1661  convenient because it is only 64 bit long, but it has enough room to handle
1662  all dates in the year range 1900 +/- 32768, that is from 00:00:00 1 Jan
1663  30867BC to 23:59:59 31 Dec 34668AD, with microsecond resolution. Furthermore
1664  it refers to UTC, so it can be converted to local time zone when
1665  unserializing the object.
1666 */
1667 typedef int64_t MCS_TIME;
1668 
1669 #define MCS_TIME_MICROSEC 0xFFFFF // 20 bit, 0 tot, microsecond resolution, not yet used.
1670 #define MCS_TIME_SEC 0x3F // 6 bit, 20 tot
1671 #define MCS_TIME_MIN 0x3F // 6 bit, 26 tot
1672 #define MCS_TIME_HOUR 0x1F // 5 bit, 32 tot
1673 #define MCS_TIME_DAY 0x1F // 5 bit, 37 tot
1674 #define MCS_TIME_MONTH 0xF // 4 bit, 42 tot
1675 #define MCS_TIME_YEAR 0xFFFF // 16 bit, 46 tot
1676 #define MCS_TIME_FLAGS 0x3 // 2 bit, 52 tot, not yet used
1677  // 64 bit, 64 tot
1678 
1679 MCS_TIME struct_tm2MCS_TIME(struct tm* ct)
1680 {
1681  //Convert to UTC
1682  time_t t = timelocal(ct);
1683  gmtime_r(&t, ct);
1684 
1685  MCS_TIME mt =
1686  (((MCS_TIME) ct->tm_sec ) << 20) +
1687  (((MCS_TIME) ct->tm_min ) << 26) +
1688  (((MCS_TIME) ct->tm_hour) << 32) +
1689  (((MCS_TIME) ct->tm_mday) << 37) +
1690  (((MCS_TIME) ct->tm_mon ) << 42) +
1691  (((MCS_TIME) ct->tm_year) << 46) ;
1692 
1693  return mt;
1694 }
1695 
1696 
1697 int MCS_TIME2struct_tm(MCS_TIME mt, struct tm* ct)
1698 {
1699  ct->tm_sec = (int) ((mt >> 20) & MCS_TIME_SEC );
1700  ct->tm_min = (int) ((mt >> 26) & MCS_TIME_MIN );
1701  ct->tm_hour = (int) ((mt >> 32) & MCS_TIME_HOUR );
1702  ct->tm_mday = (int) ((mt >> 37) & MCS_TIME_DAY );
1703  ct->tm_mon = (int) ((mt >> 42) & MCS_TIME_MONTH);
1704  ct->tm_year = (int) ((mt >> 46) & MCS_TIME_YEAR );
1705 
1706  //Convert to local time zone
1707  time_t t = timegm(ct);
1708  localtime_r(&t, ct);
1709  return 0;
1710 }
1711 
1712 
1713 
1714 
1715 #define DATETIME_PARSE_NTEMPL 16
1716 
1717 static const char* templ[DATETIME_PARSE_NTEMPL] = {
1718  "%x%n%X",
1719  "%x%n%T",
1720  "%x%n%r",
1721 
1722  "%D%n%X",
1723  "%D%n%T",
1724  "%D%n%r",
1725 
1726  "%F%n%X",
1727  "%F%n%T",
1728  "%F%n%r",
1729 
1730  "%x", //The date using the locale's date format.
1731  "%D", //Equivalent to `%m/%d/%y'
1732  "%F", //Equivalent to `%Y-%m-%d'
1733 
1734  "%X", //The time using the locale's time format.
1735  "%T", //Equivalent to the use of `%H:%M:%S' in this place.
1736  "%r", //The complete time using the AM/PM format of the current locale.
1737 
1738  "%s", //The number of seconds since the epoch, i.e., since 1970-01-01 00:00:00 UTC.
1739 };
1740 
1741 
1742 void mcs::Data::parseTime(string s, struct tm* tm)
1743 {
1744  int i;
1745  const char* ret = NULL;
1746 
1747  memset(tm, '\0', sizeof(*tm));
1748 
1749  for (i=0; i<DATETIME_PARSE_NTEMPL; i++) {
1750  ret = strptime(s.c_str(), templ[i], tm);
1751  if (ret != NULL) break;
1752  }
1753 
1754  if (ret == NULL)
1755  throw MCS_ERROR(MSG_CONVERSION_DATETIME, s.c_str());
1756 
1757 // int ret;
1758 // bool fl_riporto = false;
1759 //
1760 // s = trim(s); // leading and trailing blanks
1761 // s = subst(s, " +", ""); // multiple blanks
1762 // s = subst(s, "[^0-9:\\- ]", ""); //non-expected chars
1763 //
1764 // const char* p = s.c_str();
1765 // float sec;
1766 //
1767 // ret = sscanf(p, dtfmt,
1768 // &(ts->tm_year), &(ts->tm_mon), &(ts->tm_mday),
1769 // &(ts->tm_hour), &(ts->tm_min), &sec);
1770 //
1771 //
1772 // if (ret == 6) { //Date and time
1773 // ts->tm_year -= 1900;
1774 // ts->tm_mon--;
1775 // }
1776 // else {
1777 // ret = sscanf(p, dafmt,
1778 // &(ts->tm_year), &(ts->tm_mon), &(ts->tm_mday));
1779 // if (ret == 3) { //Only date
1780 // ts->tm_year -= 1900;
1781 // ts->tm_mon--;
1782 // }
1783 // else {
1784 // ret = sscanf(p, tmfmt, &(ts->tm_hour),
1785 // &(ts->tm_min), &sec);
1786 // if (ret != 3)
1787 // throw MCS_ERROR(MSG_CONVERSION_DATETIME, s.c_str());
1788 // }
1789 // }
1790 //
1791 // sec = rint(sec);
1792 // if (sec == 60) {
1793 // fl_riporto = true;
1794 // sec = 59;
1795 // }
1796 // ts->tm_sec = (int) sec;
1797 //
1798 // if (
1799 // ((ts->tm_mon < 0) || (ts->tm_mon > 11)) ||
1800 // ((ts->tm_mday < 1) || (ts->tm_mday > 31)) ||
1801 // ((ts->tm_hour < 0) || (ts->tm_hour > 23)) ||
1802 // ((ts->tm_min < 0) || (ts->tm_min > 59)) ||
1803 // ((ts->tm_sec < 0) || (ts->tm_sec > 59))
1804 // )
1805 // throw MCS_ERROR(MSG_CONVERSION_DATETIME, s.c_str());
1806 //
1807 // //ts->tm_isdst = 0;
1808 // ts->tm_gmtoff = 0;
1809 // time_t t = timelocal(ts); //Normalize
1810 //
1811 // if (fl_riporto) {
1812 // t++; //Add one second
1813 // localtime_r(&t, ts);
1814 // }
1815 }
1816 
1817 
1818 void mcs::Data::tval(struct tm* ts) const
1819 {
1820  if (ltype == STRING) {
1821  parseTime(sval(), ts);
1822  }
1823  else if (ltype == TIME) {
1824  *ts = dt;
1825  //time_t t;
1826  //MySQL_TIME_2_time_t((MYSQL_TIME*) buf, &t);
1827  //localtime_r(&t, ts);
1828  }
1829  else if ((ltype == BLOB) || (ltype == TINY_BLOB))
1830  throw MCS_ERROR(MSG_CONVERSION_BLOB_DATETIME);
1831  else {
1832  time_t tt = (time_t) dval();
1833  localtime_r(&tt, ts);
1834  }
1835 }
1836 
1837 
1838 time_t mcs::Data::tval() const
1839 {
1840  struct tm ts;
1841  tval(&ts);
1842  return timelocal(&ts);
1843 }
1844 
1845 
1847 { dt.now(); }
1848 
1849 
1850 void mcs::Data::setTimeMode(enum TimeMode tm)
1851 { dt.setTimeMode(tm); }
1852 
1853 
1854 
1855 void mcs::Data::settimeval(struct tm tm)
1856 {
1857  char* buf = (char*) buffer();
1858  time_t t;
1859 
1860  lisnull = false;
1861 
1862  //switch (dbtimemode) {
1863  // case GMT:
1864  // t = timegm(&tm);
1865  // break;
1866  // case LOCAL:
1867  t = timelocal(&tm);
1868  // break;
1869  //}
1870 
1871  switch (ltype) {
1872  case TINY:
1873  case SMALL:
1874  case MEDIUM:
1875  case TINY_BLOB:
1876  case BLOB:
1877  case POINTER:
1878  throw MCS_ERROR(MSG_CONVERSION_TIME_LINT);
1879  break;
1880  case INT:
1881  case BIGINT:
1882  setival( t );
1883  break;
1884  case FLOAT:
1885  case DOUBLE:
1886  setdval( t );
1887  break;
1888  case STRING:
1889  if (lmaxlength < 30)
1890  throw MCS_ERROR(MSG_CONVERSION_STRING_TOO_LONG);
1891 
1892  strftime(buf, 30, "%F %T", &tm);
1893  break;
1894  case TIME:
1895  dt = tm;
1896  //time_t_2_MySQL_TIME(&t, (MYSQL_TIME*) buf);
1897  }
1898 }
1899 
1900 
1901 void mcs::Data::settimeval(time_t tt)
1902 {
1903  struct tm ts;
1904  localtime_r(&tt, &ts);
1905  settimeval(ts);
1906 }
1907 
1908 
1909 
1910 
1911 
1912 
1913 
1914 
1915 
1916 
1917 
1918 
1919 
1920 
1921 
1922 
1923 void mcs::Data::setNull(bool null)
1924 {
1925  lisnull = null;
1926 }
1927 
1928 
1930 {
1931  setlval(v);
1932 }
1933 
1934 void mcs::Data::setuival(unsigned int v)
1935 {
1936  setulval(v);
1937 }
1938 
1939 void mcs::Data::setlval(long long int v)
1940 {
1941  char* buf = (char*) buffer();
1942  lisnull = false;
1943  bool us = lisunsigned;
1944 
1945  switch (ltype) {
1946  case TINY:
1947  if (us) (*((unsigned char*) buf)) = (unsigned char) v;
1948  else (*((char*) buf)) = (char) v;
1949  break;
1950  case SMALL:
1951  if (us) (*((unsigned short int*) buf)) = (unsigned short int) v;
1952  else (*((short int*) buf)) = (short int) v;
1953  break;
1954  case MEDIUM :
1955  if (us) (*((unsigned int*) buf)) = (unsigned int) v;
1956  else (*((int*) buf)) = (int) v;
1957  break;
1958  case INT :
1959  if (us) (*((unsigned int*) buf)) = (unsigned int) v;
1960  else (*((int*) buf)) = (int) v;
1961  break;
1962  case BIGINT:
1963  if (us) (*((unsigned long long int*) buf)) = (unsigned long long int) v;
1964  else (*((long long int*) buf)) = (long long int) v;
1965  break;
1966  case FLOAT:
1967  (*((float*) buf)) = v; break;
1968  case DOUBLE:
1969  (*((double*) buf)) = v; break;
1970  case STRING:
1971  memset(buf, 32, lmaxlength);
1972  snprintf(buf, lmaxlength, lfmt, v);
1973  llength = strlen(buf);
1974  break;
1975  case TINY_BLOB:
1976  throw MCS_ERROR(MSG_CONVERSION_INT_BLOB); break;
1977  case BLOB:
1978  throw MCS_ERROR(MSG_CONVERSION_INT_BLOB); break;
1979  case POINTER:
1980  throw MCS_ERROR(MSG_CONVERSION_INT_BLOB); break;
1981  case TIME:
1982  time_t tt = (time_t) v;
1983  dt = tt;
1984  //time_t_2_MySQL_TIME(&tt, (MYSQL_TIME*) buf);
1985  break;
1986  }
1987 
1988  MCS_DEBUG("-> " << sval());
1989 }
1990 
1991 
1992 
1993 
1994 
1995 void mcs::Data::setulval(unsigned long long int v)
1996 {
1997  char* buf = (char*) buffer();
1998  lisnull = false;
1999  bool us = lisunsigned;
2000 
2001  switch (ltype) {
2002  case TINY:
2003  if (us) (*((unsigned char*) buf)) = (unsigned char) v;
2004  else (*((char*) buf)) = (char) v;
2005  break;
2006  case SMALL:
2007  if (us) (*((unsigned short int*) buf)) = (unsigned short int) v;
2008  else (*((short int*) buf)) = (short int) v;
2009  break;
2010  case MEDIUM :
2011  if (us) (*((unsigned int*) buf)) = (unsigned int) v;
2012  else (*((int*) buf)) = (int) v;
2013  break;
2014  case INT :
2015  if (us) (*((unsigned int*) buf)) = (unsigned int) v;
2016  else (*((int*) buf)) = (int) v;
2017  break;
2018  case BIGINT:
2019  if (us) (*((unsigned long long int*) buf)) = (unsigned long long int) v;
2020  else (*((long long int*) buf)) = (long long int) v;
2021  break;
2022  case FLOAT:
2023  (*((float*) buf)) = v; break;
2024  case DOUBLE:
2025  (*((double*) buf)) = v; break;
2026  case STRING:
2027  memset(buf, 32, lmaxlength);
2028  snprintf(buf, lmaxlength, lfmt, v);
2029  llength = strlen(buf);
2030  break;
2031  case TINY_BLOB:
2032  throw MCS_ERROR(MSG_CONVERSION_INT_BLOB); break;
2033  case BLOB:
2034  throw MCS_ERROR(MSG_CONVERSION_INT_BLOB); break;
2035  case POINTER:
2036  throw MCS_ERROR(MSG_CONVERSION_INT_BLOB); break;
2037  case TIME:
2038  time_t tt = (time_t) v;
2039  dt = tt;
2040  //time_t_2_MySQL_TIME(&tt, (MYSQL_TIME*) buf);
2041  break;
2042  }
2043 
2044  MCS_DEBUG("-> " << sval());
2045 }
2046 
2047 
2048 
2049 
2050 
2051 
2052 
2053 void mcs::Data::setdval(double v)
2054 {
2055  char* buf = (char*) buffer();
2056  lisnull = false;
2057  bool us = lisunsigned;
2058 
2059  switch (ltype) {
2060  case TINY:
2061  if (us) (*((unsigned char*) buf)) = (unsigned char) nearbyint(v);
2062  else (*((char*) buf)) = (char) nearbyint(v);
2063  break;
2064  case SMALL:
2065  if (us) (*((unsigned short int*) buf)) = (unsigned short int) nearbyint(v);
2066  else (*((short int*) buf)) = (short int) nearbyint(v);
2067  break;
2068  case MEDIUM :
2069  if (us) (*((unsigned int*) buf)) = (unsigned int) nearbyint(v);
2070  else (*((int*) buf)) = (int) nearbyint(v);
2071  break;
2072  case INT :
2073  if (us) (*((unsigned int*) buf)) = (unsigned int) nearbyint(v);
2074  else (*((int*) buf)) = (int) nearbyint(v);
2075  break;
2076  case BIGINT:
2077  if (us) (*((unsigned long long int*) buf)) = (unsigned long long int) nearbyint(v);
2078  else (*((long long int*) buf)) = (long long int) nearbyint(v);
2079  break;
2080  case FLOAT:
2081  (*((float*) buf)) = v; break;
2082  case DOUBLE:
2083  (*((double*) buf)) = v; break;
2084  case STRING:
2085  memset(buf, 32, lmaxlength);
2086  snprintf(buf, lmaxlength, dfmt, v);
2087  llength = strlen(buf);
2088  break;
2089  case TINY_BLOB:
2090  throw MCS_ERROR(MSG_CONVERSION_FLOAT_BLOB); break;
2091  case BLOB:
2092  throw MCS_ERROR(MSG_CONVERSION_FLOAT_BLOB); break;
2093  case POINTER:
2094  throw MCS_ERROR(MSG_CONVERSION_FLOAT_BLOB); break;
2095  case TIME:
2096  time_t tt = (time_t) nearbyint(v);
2097  dt = tt;
2098  //time_t_2_MySQL_TIME(&tt, (MYSQL_TIME*) buf);
2099  break;
2100  }
2101 
2102  MCS_DEBUG("-> " << sval());
2103 }
2104 
2105 
2106 void mcs::Data::setcval(const char* v)
2107 {
2108  setsval(string(v));
2109  MCS_DEBUG("-> " << sval());
2110 }
2111 
2112 
2113 void mcs::Data::setsval(string v)
2114 {
2115  char* buf = (char*) buffer();
2116  int ret=-1000;
2117  bool us = lisunsigned;
2118  lisnull = false;
2119 
2120  switch (ltype) {
2121  case TINY:
2122  if (us) ret=sscanf(v.c_str(), "%hhd", ((unsigned char*) buf));
2123  else ret=sscanf(v.c_str(), "%hhd", ((char*) buf));
2124  break;
2125  case SMALL:
2126  if (us) ret=sscanf(v.c_str(), "%hd" , ((unsigned short int*) buf));
2127  else ret=sscanf(v.c_str(), "%hd" , ((short int*) buf));
2128  break;
2129  case MEDIUM :
2130  if (us) ret=sscanf(v.c_str(), "%d" , ((unsigned int*) buf));
2131  else ret=sscanf(v.c_str(), "%d" , ((int*) buf));
2132  break;
2133  case INT :
2134  if (us) ret=sscanf(v.c_str(), "%d" , ((unsigned int*) buf));
2135  else ret=sscanf(v.c_str(), "%d" , ((int*) buf));
2136  break;
2137  case BIGINT:
2138  if (us) ret=sscanf(v.c_str(), "%lld", ((unsigned long long int*) buf));
2139  else ret=sscanf(v.c_str(), "%lld", ((long long int*) buf));
2140  break;
2141  case FLOAT:
2142  ret=sscanf(v.c_str(), "%f" , ((float*) buf)); break;
2143  case DOUBLE:
2144  ret=sscanf(v.c_str(), "%lf", ((double*) buf)); break;
2145  case TIME:
2146  dt = v;
2147  //struct tm ts;
2148  //time_t t;
2149  //parseTime(v, &ts);
2150  //
2151  //switch (dbtimemode) {
2152  // case GMT:
2153  // t = timegm(&ts);
2154  // break;
2155  // case LOCAL:
2156  // t = timelocal(&ts);
2157  // break;
2158  //}
2159  //time_t_2_MySQL_TIME(&t, (MYSQL_TIME*) buf);
2160  break;
2161  case STRING:
2162  if (v.length() > lmaxlength)
2163  throw MCS_ERROR(MSG_CONVERSION_STRING_TOO_LONG);
2164  else {
2165  memset(buf, 32, lmaxlength);
2166  llength = v.length();
2167  memcpy(buf, v.c_str(), llength);
2168  }
2169  break;
2170  case TINY_BLOB:
2171  throw MCS_ERROR(MSG_CONVERSION_STRING_BLOB); break;
2172  case BLOB:
2173  throw MCS_ERROR(MSG_CONVERSION_STRING_BLOB); break;
2174  case POINTER:
2175  throw MCS_ERROR(MSG_CONVERSION_STRING_BLOB); break;
2176  }
2177 
2178  if (ret!=-1000 && ret!=1)
2179  throw MCS_ERROR(MSG_CONVERSION_NAN);
2180 
2181  MCS_DEBUG("-> " << sval());
2182 }
2183 
2184 
2185 
2186 void mcs::Data::setblob(void* lbuf, unsigned int size)
2187 {
2188  char* buf = (char*) buffer();
2189 
2190  lisnull = false;
2191  if ((ltype != TINY_BLOB) && (ltype != BLOB))
2192  throw MCS_ERROR(MSG_NOT_A_BLOB);
2193 
2194  if (size > lmaxlength)
2195  throw MCS_ERROR(MSG_NOT_ENOUGH_SPACE, size, lmaxlength);
2196 
2197  memcpy(buf, lbuf, size);
2198 }
2199 
2200 
2201 
2202 long long int mcs::Data::MinValue(Types ltype, bool flunsigned)
2203 {
2204  int nbit;
2205  switch (ltype) {
2206  case TINY:
2207  nbit = 8; break;
2208  case SMALL:
2209  nbit = 16; break;
2210  case MEDIUM:
2211  nbit = 24; break;
2212  case INT:
2213  nbit = 32; break;
2214  case BIGINT:
2215  nbit = 64; break;
2216  default:
2217  return 0;
2218  }
2219  if (flunsigned)
2220  return 0;
2221  else
2222  return (long long int) (-1 * (pow(2.0, nbit) / 2));
2223 }
2224 
2225 
2226 long long int mcs::Data::MaxValue(Types ltype, bool flunsigned)
2227 {
2228  int nbit;
2229  switch (ltype) {
2230  case TINY:
2231  nbit = 8; break;
2232  case SMALL:
2233  nbit = 16; break;
2234  case MEDIUM:
2235  nbit = 24; break;
2236  case INT:
2237  nbit = 32; break;
2238  case BIGINT:
2239  nbit = 64; break;
2240  default:
2241  return 0;
2242  }
2243  if (flunsigned)
2244  return (long long int) (pow(2.0, nbit) - 1);
2245  else
2246  return (long long int) ((pow(2.0, nbit) / 2) - 1);
2247 }
2248 
2249 
2250 
2251 
2253 {
2254  //cout << endl << endl << "Operator assignment" << endl << endl;
2255  if (this == &d)
2256  return *this; //Self assignment
2257 
2258  if (d.isNull()) {
2259  setNull();
2260  return *this;
2261  }
2262 
2263  switch(d.type()) {
2264  case TINY:
2265  case SMALL:
2266  case MEDIUM:
2267  setival( d.ival() );
2268  break;
2269  case INT:
2270  if (d.isUnsigned())
2271  setdval( d.lval() );
2272  else
2273  setival( d.ival() );
2274  break;
2275  case BIGINT:
2276  if (d.isUnsigned())
2277  setdval( d.ulval() );
2278  else
2279  setdval( d.lval() );
2280  break;
2281  case FLOAT:
2282  case DOUBLE:
2283  setdval( d.dval() );
2284  break;
2285  case STRING:
2286  setsval( d.sval() );
2287  break;
2288  case TIME:
2289  settimeval( d.tval() );
2290  break;
2291  case TINY_BLOB:
2292  case BLOB:
2293  setblob( d.buffer(), d.length() );
2294  case POINTER:
2295  setpval(d.pval());
2296  break;
2297  }
2298 
2299  return *this;
2300 }
2301 
2302 
2303 
2304 
2305 unsigned int mcs::Data::objSize()
2306 {
2307  //For (bits): ltype (4), lisunsigned (1), lisnul (1), autoincrement(1)
2308  unsigned int size = 1;
2309 
2310  if (VarLenType(ltype)) {
2311  size += sizeof(lmaxlength);
2312  size += sizeof(unsigned short int); //llength
2313  }
2314  size += sizeof(tag);
2315  size += lname.length()+1; //NULL character
2316 
2317  //Data buffer
2318  if (ltype == TIME)
2319  size += sizeof(MCS_TIME);
2320  else
2321  size += lmaxlength;
2322 
2323  return size;
2324 }
2325 
2326 
2327 
2328 bool mcs::Data::serialize_buffer(char*& buf, unsigned int& size)
2329 {
2330  Buffer abuf(DONT_FREE); //*
2331 
2332  unsigned char tmp_mix = 0;
2333 
2334  tmp_mix += (unsigned char) ltype;
2335 
2336  if (lisunsigned)
2337  tmp_mix += 16;
2338  if (lisnull)
2339  tmp_mix += 32;
2340  if (lautoincr)
2341  tmp_mix += 64;
2342 
2343  if (ldimspec > 1) //Send also ldimspec
2344  tmp_mix += 128;
2345 
2346  abuf(sizeof(tmp_mix)) << &tmp_mix;
2347 
2348  if (ldimspec > 1) {
2349  abuf(sizeof(ldimspec)) << &ldimspec;
2350 
2351  unsigned short int dim;
2352  for (unsigned int i=0; (i<howManyDim()) || (i<varyingDim()); i++) {
2353  dim = ldim[i];
2354  abuf(sizeof(dim)) << &dim;
2355  }
2356  }
2357 
2358  if (VarLenType(ltype)) {
2359  abuf(sizeof(lmaxlength)) << &lmaxlength;
2360 
2361  unsigned short int tmp_llength = llength;
2362  abuf(sizeof(tmp_llength)) << &tmp_llength;
2363  }
2364 
2365  abuf(sizeof(tag)) << &tag;
2366  abuf(lname.length()+1) << lname.c_str();
2367 
2368  if (ltype == TIME) { /*
2369  In this case we trasform data in a MCS_TIME
2370  value, so it will be shorter. It also solve a
2371  compatibility problem between different
2372  platform when MYSQL_TIME has different size.
2373  */
2374  //struct tm ts;
2375  //char* ll = this->buf;
2376  //for (unsigned int i=0; i<arrsize; i++) {
2377  // MySQL_TIME_2_struct_tm((MYSQL_TIME*) ll, &ts);
2378  // ll += lmaxlength;
2379  //
2380  // MCS_TIME mt = struct_tm2MCS_TIME(&ts);
2381  // abuf(sizeof(MCS_TIME)) << &mt;
2382  //}
2383  time_t t;
2384  char* ll = this->buf;
2385  for (unsigned int i=0; i<arrsize; i++) {
2386  //MySQL_TIME_2_time_t((MYSQL_TIME*) ll, &t);
2387  //ll += lmaxlength;
2388 
2389  dt.setMysqlBuffer((MYSQL_TIME*) ll);
2390  t = dt;
2391  abuf(sizeof(time_t)) << &t;
2392  }
2393  }
2394  else
2395  abuf(lmaxlength * arrsize) << this->buf;
2396 
2397  size = abuf.size();
2398  buf = abuf[0];
2399  return true; //* = will be freed when not needed anymore
2400 }
2401 
2402 
2403 
2404 mcs::Data::Data(void* llbuf) : Serializable(MCS_SERIAL_BUFFER)
2405 {
2406  if (! llbuf) {
2407  init(NULL, TINY);
2408  setNull();
2409  return;
2410  }
2411  char* lbuf = (char*) llbuf;
2412 
2413  unsigned char tmp_mix;
2414  memcpy(&tmp_mix, lbuf, sizeof(tmp_mix));
2415  lbuf += sizeof(tmp_mix);
2416 
2417  ltype = (Types) (tmp_mix & 15);
2418  lisunsigned = (bool) (tmp_mix & 16);
2419  bool lisnull = (bool) (tmp_mix & 32); //This value must be set AFTER init()
2420  bool lautoincr = (bool) (tmp_mix & 64); //This value must be set AFTER init()
2421  bool hasDimSpec = ((bool) (tmp_mix & 128));
2422  string dimspec = "";
2423 
2424  if (hasDimSpec) {
2425  memcpy(&ldimspec, lbuf, sizeof(ldimspec));
2426  lbuf += sizeof(ldimspec);
2427 
2428  for (unsigned int i=0; i<MCS_DATA_NDIM; i++) {
2429  if ((i<howManyDim()) || (i<varyingDim())) {
2430  memcpy(&(ldim[i]), lbuf, sizeof(unsigned short int));
2431  lbuf += sizeof(unsigned short int);
2432  }
2433  else
2434  ldim[i] = 1;
2435  }
2436 
2437  dimspec = buildDimSpec(ldimspec, ldim);
2438  }
2439 
2440 
2441  lmaxlength = 0;
2442  unsigned short int tmp_llength = 0;
2443  if (VarLenType(ltype)) {
2444  memcpy(&lmaxlength , lbuf, sizeof(lmaxlength) );
2445  lbuf += sizeof(lmaxlength) ;
2446 
2447  memcpy(&tmp_llength, lbuf, sizeof(tmp_llength));
2448  lbuf += sizeof(tmp_llength);
2449  llength = tmp_llength;
2450  }
2451 
2452 
2453  unsigned char tmp_ltag;
2454  memcpy(&tmp_ltag , lbuf, sizeof(tag) ); lbuf += sizeof(tmp_ltag) ;
2455 
2456  string tmp_lname = string(lbuf);
2457  lbuf += tmp_lname.length()+1;
2458 
2459  init(NULL,
2460  ltype,
2461  (char*) tmp_lname.c_str(),
2462  lmaxlength,
2463  lisunsigned,
2464  0);
2465 
2466  resize(dimspec);
2467 
2468  if (ltype == TIME) { //See note in Data::serialize_buffer
2469  //MCS_TIME mt;
2470  //char* ll = this->buf;
2471  //
2472  //for (unsigned int i=0; i<arrsize; i++) {
2473  // memcpy(&mt, lbuf, sizeof(MCS_TIME));
2474  // lbuf += sizeof(MCS_TIME);
2475  //
2476  // struct tm ts;
2477  // MCS_TIME2struct_tm(mt, &ts);
2478  // Struct_tm_2_MySQL_TIME(&ts, (MYSQL_TIME*) ll);
2479  // ll += lmaxlength;
2480  //}
2481 
2482  time_t t;
2483  char* ll = this->buf;
2484 
2485  for (unsigned int i=0; i<arrsize; i++) {
2486  memcpy(&t, lbuf, sizeof(time_t));
2487  lbuf += sizeof(size_t);
2488 
2489  dt = t;
2490  //time_t_2_MySQL_TIME(&t, (MYSQL_TIME*) ll);
2491  ll += lmaxlength;
2492  }
2493  }
2494  else
2495  memcpy(buf, lbuf, lmaxlength * arrsize);
2496 
2497  if (VarLenType(ltype))
2498  llength = tmp_llength;
2499 
2500  setTag(tmp_ltag);
2501  this->lisnull = lisnull;
2502  this->lautoincr = lautoincr;
2503 }
2504 
2505 
2506 mcs::Data::Data(void* lbuf, unsigned int size, unsigned char tag)
2507  : Serializable(MCS_SERIAL_BUFFER)
2508 {
2509  if (size < 256)
2510  init(NULL, TINY_BLOB, "", size, false, 0);
2511  else if (size < 65536)
2512  init(NULL, BLOB, "", size, false, 0);
2513  else
2514  throw MCS_ERROR(MSG_BLOB_TOO_BIG, size);
2515 
2516  setblob(lbuf, size);
2517  setTag(tag);
2518 }
2519 
2521 {
2522  string s;
2523  char* p;
2524  unsigned int i;
2525 
2526  s = string( "N=") + name() +
2527  string(" T=") + Types2Str(type(), isUnsigned()) +
2528  string(" L=") + itos(maxLength()) +
2529  string(" l=") + itos(length()) +
2530  string(" n=") + itos(isNull()) +
2531  string(" D=") ;
2532 
2533  if ((type() == BLOB) || (type() == TINY_BLOB)) {
2534  p = (char*) buffer();
2535  for (i=0; i<length(); i++)
2536  s += itos(p[i]) + string(" ");
2537  }
2538  else
2539  s += sval();
2540 
2541  return s;
2542 }
2543 
2544 void mcs::Data::setTag(unsigned char ltag)
2545 {
2546  tag = ltag;
2547 }
2548 
2549 unsigned char mcs::Data::getTag()
2550 {
2551  return tag;
2552 }
2553 
2554 
2555 int mcs::Data::getSourceID()
2556 {
2557  return id_source;
2558 }
2559 
2560 void mcs::Data::setSourceID(int id)
2561 {
2562  id_source = id;
2563 }
2564 
2565 int mcs::Data::getDestID()
2566 {
2567  return id_dest;
2568 }
2569 
2570 void mcs::Data::setDestID(int id)
2571 {
2572  id_dest = id;
2573 }
Definition: mcs.hh:63
unsigned char tag
Tag for user convenience.
Definition: mcs.hh:3133
string print()
Returns a string representation of the object, for debug purpose.
Definition: Data.cc:2520
string itos(int i)
Convert an integer to a string.
Definition: Utils.cc:77
Data & operator=(const int v)
Wrapper assignment operator to setival(int).
Definition: mcs.hh:3653
void settimenow()
Convert current time value to base type and store in internal buffer.
Definition: Data.cc:1846
Types type()
Return the base type of the object.
Definition: Data.cc:1196
TimeMode
Enumerate operational mode for a DateTime object.
Definition: mcs.hh:2833
unsigned long long int ulval() const
Convert internal data to an unsigned long long integer value.
Definition: Data.cc:1397
Serialize memory buffers or files into chunks.
Definition: mcs.hh:1290
bool Types2FITS(Types dbt, bool isunsigned, int &fits)
Convert a MCS type into a FITSIO type.
Definition: Data.cc:564
bool isAutoIncrement()
Tells if the database field is an auto increment field.
Definition: Data.cc:1201
bool lautoincr
If the AUTO_INCREMENT flag is true.
Definition: mcs.hh:3130
bool IntType(Types type)
Tell if "type" is an integer type.
Definition: Data.cc:364
unsigned int size()
Return size of the buffer.
Definition: Record.cc:208
DateTime()
Constructor.
Definition: Data.cc:161
static const char * tmfmt
Format to handle time in sprintf/sscanf calls.
Definition: mcs.hh:3148
string sval(bool addWhiteSpaces=false) const
Convert internal data to a string object.
Definition: Data.cc:1555
static const char * dfmt
Format to handle double float in sprintf/sscanf calls.
Definition: mcs.hh:3160
Data()
Build Data object of base type STRING and length zero.
Definition: Data.cc:1056
unsigned short int dim(int d)
Return length of a dimension.
Definition: Data.cc:893
unsigned int arrpos
Last selected array cell.
Definition: mcs.hh:3218
void setTag(unsigned char tag)
Set a new value to internal tag.
Definition: Data.cc:2544
struct tm tmval() const
Retrieve a struct tm object.
Definition: Data.cc:266
unsigned short int ldim[15]
Size of each dimension.
Definition: mcs.hh:3209
unsigned int arrsize
Array size, i.e. how many cells are in the array.
Definition: mcs.hh:3215
char * buf
Data buffer.
Definition: mcs.hh:3136
unsigned long llength
Actual length of real data in the buffer, useful only when the base type is a variable length type...
Definition: mcs.hh:3121
Data & operator()(const int i1=0, const int i2=0, const int i3=0, const int i4=0, const int i5=0, const int i6=0, const int i7=0, const int i8=0, const int i9=0, const int i10=0, const int i11=0, const int i12=0, const int i13=0, const int i14=0, const int i15=0)
Same as array().
Definition: Data.cc:780
void setNull(bool null=true)
Set null flag. Following call to isNull() returns the value used here as parameter.
Definition: Data.cc:1923
string name()
Return the name of the object.
Definition: Data.cc:1193
void init(MYSQL_BIND *bind, Types type, const char *name="", unsigned short int maxLength=0, bool isunsigned=false, unsigned int flags=0)
Initialize internal structures.
Definition: Data.cc:956
string MYSQL2Str(enum_field_types type)
Return the name of the MySQL type given in "type".
Definition: Data.cc:393
void settmval(struct tm &ltm)
Assign a struct tm value.
Definition: Data.cc:244
static void parseTime(string s, struct tm *ts)
Fills the "struct tm*" passed as argument with the current local datetime.
Definition: Data.cc:1742
unsigned char ldimspec
Multi-dimensional array specification.
Definition: mcs.hh:3206
void setsval(string v)
Convert string value to base type and store in internal buffer.
Definition: Data.cc:2113
void settval(time_t t)
Assign a time_t value.
Definition: Data.cc:186
void setMysqlBuffer(MYSQL_TIME *mysql)
Set a pointer to a MYSQL_TIME structure.
Definition: Data.cc:168
void setsval(string s)
Parse a string to extract a datetime value.
Definition: Data.cc:229
~Data()
Destructor Frees internal buffer.
Definition: Data.cc:1174
void setulval(unsigned long long int v)
Convert unsigned long int value to base type and store in internal buffer.
Definition: Data.cc:1995
#define MCS_ERROR(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Definition: mcs.hh:964
void setcval(const char *v)
Convert string value to base type and store in internal buffer.
Definition: Data.cc:2106
char * from
Pointer to source buffer, if type = MCS_SERIAL_BUFFER.
Definition: mcs.hh:1311
int cval(char *c, int maxlength) const
Convert internal data to a NULL terminated string and store it in a buffer.
Definition: Data.cc:1616
string Types2Str(Types type, bool isunsigned)
Return the name of the type given in "type" and "isunsigned".
Definition: Data.cc:313
unsigned int varyingDim()
Return the index of the dimension that may vary.
Definition: Data.cc:661
bool isUnsigned()
Tell if the object contains unsigned integers.
Definition: Data.cc:1199
static const char * dtfmt
Format to handle datetime in sprintf/sscanf calls.
Definition: mcs.hh:3142
string Types2MYSQLStr(Types &type, bool isunsigned)
Convert a MCS type into a MySQL type.
Definition: Data.cc:509
bool isNull()
Tells if no value is stored.
Definition: Data.cc:1200
unsigned char getTag()
Retrieve the value of the tag.
Definition: Data.cc:2549
bool FloatType(Types type)
Tell if "type" is a float type.
Definition: Data.cc:379
unsigned int size()
If knowSize() is true, return the size of the entire block of data.
time_t tval() const
Retrieve a time_t value.
Definition: Data.cc:260
High level buffer.
Definition: mcs.hh:1095
bool serialize_buffer(char *&from, unsigned int &size)
Prepare a buffer with all informations contained in the object.
Definition: Data.cc:2328
int stoi(string s)
Convert a string to an integer.
Definition: Utils.cc:85
double dval() const
Convert internal data to a double (8 bytes) floating point value.
Definition: Data.cc:1465
bool Types2S_FITS(Types dbt, int len, bool isunsigned, string &fits)
Convert a MCS type into a FITSIO type code.
Definition: Data.cc:603
void setival(int v)
Convert int value to base type and store in internal buffer.
Definition: Data.cc:1929
unsigned int howManyDim()
Return how many dimensions are in the array.
Definition: Data.cc:656
static const char * parseTime(const char *s, struct tm *tm)
Parse a string to extract datetime information.
Definition: Data.cc:60
unsigned int uival() const
Convert internal data to an unsigned integer value.
Definition: Data.cc:1309
static const char * lfmt
Format to handle long integers in sprintf/sscanf calls.
Definition: mcs.hh:3154
vector< string > split(string s, string sep=" ")
Split a string into tokens.
Definition: Utils.cc:192
unsigned int arraySize()
Return size of array.
Definition: Data.cc:905
Definition: mcs.hh:55
string lname
Object name.
Definition: mcs.hh:3108
Main include file for all MCS based applications.
void emptyName()
Set the object name to an empty string.
Definition: Data.cc:1180
static const char * ifmt
Format to handle integers in sprintf/sscanf calls.
Definition: mcs.hh:3151
unsigned short int lmaxlength
Max number of bytes that can be stored in the buffer (size of the buffer).
Definition: mcs.hh:3115
void resizeVaryingDim(unsigned short int newsize)
Resize variable length dimension.
Definition: Data.cc:913
static long long int MinValue(Types ltype, bool flunsigned)
Return the minimum integer value for the base type specified.
Definition: Data.cc:2202
bool VarLenType(Types type)
Tell if "type" is a variable length type.
Definition: Data.cc:349
long long int lval() const
Convert internal data to a long long integer value.
Definition: Data.cc:1362
Definition: mcs.hh:65
void settimeval(struct tm v)
Convert "struct tm" value to base type and store in internal buffer.
void now()
Set the current datetime value.
Definition: Data.cc:179
void setlval(long long int v)
Convert long int value to base type and store in internal buffer.
Definition: Data.cc:1939
void setTimeMode(enum TimeMode tm)
Set operational time mode.
Definition: Data.cc:172
A general purpose data type.
Definition: mcs.hh:3092
time_t getTime() const
Return stored time.
Definition: Data.cc:140
float fval() const
Convert internal data to a floating point value.
Definition: Data.cc:1434
bool MYSQL2Types(enum_field_types mtype, Types &type)
Convert a MySQL type into a MCS type.
Definition: Data.cc:436
unsigned short int length()
Return the actual length of the data in the internal buffer.
Definition: Data.cc:1198
Types ltype
Object base type.
Definition: mcs.hh:3105
int id_source
The userid of the thread who send this object.
Definition: mcs.hh:3196
void setdval(double v)
Convert double value to base type and store in internal buffer.
Definition: Data.cc:2053
void setuival(unsigned int v)
Convert unsigned int value to base type and store in internal buffer.
Definition: Data.cc:1934
void to_MYSQL_TIME()
Update linked MYSQL_TIME structure (if any) with internal value.
Definition: Data.cc:124
string sval() const
Retrieve a string representation of the datetime value.
Definition: Data.cc:281
time_t tval() const
Convert internal data to a time_t value.
Definition: Data.cc:1838
string trim(string s)
Remove any leading or trailing blanks.
Definition: Utils.cc:160
bool FITS2Types(int fits, Types &dbt, bool &isunsigned)
Convert a FITSIO type into a MCS type.
Definition: Data.cc:526
string hexDump(const void *buf, unsigned int size)
Return a string with an hex dump of the buffer pointed by "buf", with a length of "size"...
Definition: Utils.cc:211
void * buffer() const
Return a pointer to the internal buffer, use this at your own risk.
Definition: Data.cc:1202
unsigned int lflags
Flags (EXPERIMENTAL).
Definition: mcs.hh:3111
int ival() const
Convert internal data to a integer value.
Definition: Data.cc:1209
unsigned int array(unsigned short int i1=0, unsigned short int i2=0, unsigned short int i3=0, unsigned short int i4=0, unsigned short int i5=0, unsigned short int i6=0, unsigned short int i7=0, unsigned short int i8=0, unsigned short int i9=0, unsigned short int i10=0, unsigned short int i11=0, unsigned short int i12=0, unsigned short int i13=0, unsigned short int i14=0, unsigned short int i15=0)
Select a cell from the array.
Definition: Data.cc:801
unsigned short int maxLength()
Return the size of the internal buffer.
Definition: Data.cc:1197
void setblob(void *lbuf, unsigned int size)
Copy "size" bytes from the address given in "lbuf" parameter.
Definition: Data.cc:2186
static const char * ffmt
Format to handle float in sprintf/sscanf calls.
Definition: mcs.hh:3157
my_bool lisnull
The object has a null value.
Definition: mcs.hh:3127
bool Types2MYSQL(Types &type, enum_field_types &mtype)
Convert a MCS type into a MySQL type.
Definition: Data.cc:477
static long long int MaxValue(Types ltype, bool flunsigned)
Return the maximum integer value for the base type specified.
Definition: Data.cc:2226
bool lisunsigned
Base type is unsigned.
Definition: mcs.hh:3124
static const char * dafmt
Format to handle date in sprintf/sscanf calls.
Definition: mcs.hh:3145
void resize(string dimSpec)
Create or resize a multi-dimensional array.
Definition: Data.cc:688
unsigned int objSize()
Return how many bytes require the object to be serialized.
Definition: Data.cc:2305
Namespace for MCS library.
Types
Enumeration of base type for Data.
Definition: mcs.hh:54
int id_dest
The userid of the thread that will receive this object.
Definition: mcs.hh:3199
Definition: mcs.hh:58

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha7
Documentation generated on Mon May 28 07:39:41 UTC 2018