(file) Return to helpers.c CVS log (file) (dir) Up to [OMI] / omi / base

   1 mike  1.1 /*
   2           **==============================================================================
   3           **
   4           ** Open Management Infrastructure (OMI)
   5           **
   6           ** Copyright (c) Microsoft Corporation
   7           ** 
   8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
   9           ** use this file except in compliance with the License. You may obtain a copy 
  10           ** of the License at 
  11           **
  12           **     http://www.apache.org/licenses/LICENSE-2.0 
  13           **
  14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
  16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
  17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
  18           **
  19           ** See the Apache 2 License for the specific language governing permissions 
  20           ** and limitations under the License.
  21           **
  22 mike  1.1 **==============================================================================
  23           */
  24           
  25           #include <ctype.h>
  26           #include "helpers.h"
  27           #include "types.h"
  28           #include "strings.h"
  29           #include "alloc.h"
  30           #include "io.h"
  31           
  32           #define T MI_T
  33           
  34           static const MI_Char* _ParseNumber(const MI_Char* p, unsigned long* n)
  35           {
  36               MI_Char* end;
  37           
  38               *n = Ztoul(p, &end, 10);
  39           
  40               if (end == p)
  41                   return NULL;
  42           
  43 mike  1.1     return end;
  44           }
  45           
  46           static const MI_Char* _ParseDecimalPart(
  47               const MI_Char* p, 
  48               unsigned long* n)
  49           {
  50               MI_Char* end;
  51               int i;
  52               MI_Char buf[7];
  53               unsigned long x;
  54           
  55               x = Ztoul(p, &end, 10);
  56           
  57               if (end == p)
  58               {
  59                   /* Zero decimal part */
  60                   *n = 0;
  61                   return p;
  62               }
  63           
  64 mike  1.1     for (i = 0; i < 6 && p != end; i++, p++)
  65                   buf[i] = *p;
  66           
  67               for (; i < 6; i++)
  68                   buf[i] = '0';
  69           
  70               buf[6] = '\0';
  71           
  72               *n = Ztoul(buf, NULL, 10);
  73           
  74               return end;
  75           }
  76           
  77           static int _ParseWSManDuration(const MI_Char* str, MI_Datetime* x)
  78           {
  79               const MI_Char* p = str;
  80               int foundT = 0;
  81               unsigned long years = 0;
  82               unsigned long months = 0;
  83               unsigned long days = 0;
  84               unsigned long hours = 0;
  85 mike  1.1     unsigned long minutes = 0;
  86               unsigned long seconds = 0;
  87               unsigned long microseconds = 0;
  88           
  89               /* xs:duration: PnYnMnDTnHnMnS */
  90               if (*p != 'P')
  91                   return -1;
  92           
  93               /* [xs:duration]
  94                *
  95                * Format: "PnYnMnDTnHnMnS", where
  96                *     P - period (required)
  97                *     nY - number of years
  98                *     nM - number of month
  99                *     nD - number of days
 100                *     T - start of time section (required for the following)
 101                *     nH - number of hours
 102                *     nM - number of minutes
 103                *     nS - number of seconds
 104                *
 105                * Examples:
 106 mike  1.1      *     -P10D (rejected)
 107                *     -P1347M (rejected)
 108                *     P5Y
 109                *     P5Y2M10D
 110                *     P5Y2M10DT15H
 111                *     PT15H
 112                *     P1347Y
 113                *     P1347M 
 114                *     P1Y2MT2H 
 115                *     P0Y1347M 
 116                *     P0Y1347M0D 
 117                *     P1Y2M3DT10H30M
 118                *
 119                * Illegal:
 120                *     P-1347M (rejected)
 121                *     P1Y2MT (tolerated)
 122                */
 123           
 124               p++;
 125           
 126               while (*p)
 127 mike  1.1     {
 128                   unsigned long n = 0;
 129           
 130                   if (*p == 'T')
 131                   {
 132                       foundT = 1;
 133                       p++;
 134                   }
 135                   else if (foundT)
 136                   {
 137                       p = _ParseNumber(p, &n);
 138           
 139                       if (!p)
 140                           break;
 141           
 142                       switch (*p)
 143                       {
 144                           case 'H':
 145                               hours = n;
 146                               break;
 147                           case 'M':
 148 mike  1.1                     minutes = n;
 149                               break;
 150                           case 'S':
 151                               seconds = n;
 152                               break;
 153                           case '.':
 154                           {
 155                               p++;
 156                               p = _ParseDecimalPart(p, &microseconds);
 157           
 158                               if (*p != 'S')
 159                                   return -1;
 160           
 161                               seconds = n;
 162                               break;
 163                           }
 164                           default:
 165                               return -1;
 166                       }
 167           
 168                       p++;
 169 mike  1.1         }
 170                   else
 171                   {
 172                       p = _ParseNumber(p, &n);
 173           
 174                       if (!p)
 175                           break;
 176           
 177                       switch (*p)
 178                       {
 179                           case 'Y':
 180                               years = n;
 181                               break;
 182                           case 'M':
 183                               months = n;
 184                               break;
 185                           case 'D':
 186                               days = n;
 187                               break;
 188                           default:
 189                               return -1;
 190 mike  1.1             }
 191           
 192                       p++;
 193                   }
 194               }
 195           
 196               /* ATTN: check for overflow */
 197           
 198               /* Normalize seconds (possibly increasing minutes) */
 199               minutes += seconds / 60;
 200               seconds = seconds % 60;
 201           
 202               /* Normalize minutes (possibly increasing hours) */
 203               hours += minutes / 60;
 204               minutes = minutes % 60;
 205           
 206               /* Normalize hours (possibly increasing days) */
 207               days += hours / 24;
 208               hours = hours % 24;
 209           
 210               /* Approximate days from years-months-days */
 211 mike  1.1     days += years * 365;
 212               days += years / 4;
 213               days += months * 30;
 214               days += months / 2;
 215           
 216               /* Set CIM datetime fields */
 217               x->isTimestamp = MI_FALSE;
 218               x->u.interval.days = (unsigned int)days;
 219               x->u.interval.hours = (unsigned int)hours;
 220               x->u.interval.minutes = (unsigned int)minutes;
 221               x->u.interval.seconds = (unsigned int)seconds;
 222               x->u.interval.microseconds = microseconds;
 223           
 224               return (p && *p == '\0') ? 0 : -1;
 225           }
 226           
 227           static const MI_Char* _ParseWSManUTC(const MI_Char* str, MI_Datetime* x)
 228           {
 229               const MI_Char* p = str;
 230               unsigned long utcHours = 0;
 231               unsigned long utcMinutes = 0;
 232 mike  1.1     long utcSign = 0; /* '1' is positive, '-1' is negative */
 233           
 234               if (*p == 'Z')
 235               {
 236                   p++;
 237                   return p;
 238               }
 239               else if (*p == '+' || *p == '-')
 240               {
 241                   /* Parse UTC "HH:SS" */
 242                   const MI_Char* end;
 243           
 244                   utcSign = (*p == '-') ? -1 : 1;
 245           
 246                   p++;
 247                   end = _ParseNumber(p, &utcHours);
 248           
 249                   if (!end || (end - p) != 2)
 250                       return NULL;
 251           
 252                   p = end;
 253 mike  1.1 
 254                   if (*p != ':')
 255                       return NULL;
 256           
 257                   p++;
 258                   end = _ParseNumber(p, &utcMinutes);
 259           
 260                   if (!end || (end - p) != 2)
 261                       return NULL;
 262           
 263                   p = end;
 264               }
 265               else
 266               {
 267                   return NULL;
 268               }
 269           
 270               /* Set CIM datetime fields */
 271               x->u.timestamp.utc = utcSign * ((utcHours * 60) + utcMinutes);
 272           
 273               return p;
 274 mike  1.1 }
 275           
 276           static const MI_Char* _ParseWSManDate(const MI_Char* str, MI_Datetime* x)
 277           {
 278               const MI_Char* p = str;
 279               unsigned long year = 0;
 280               unsigned long month = 0;
 281               unsigned long day = 0;
 282           
 283               /* Parse YYYY */
 284               {
 285                   const MI_Char* end = _ParseNumber(p, &year);
 286           
 287                   if (!end || (end - p) != 4)
 288                       return NULL;
 289           
 290                   p = end;
 291               }
 292           
 293               /* Expect '-' */
 294               if (*p++ != '-')
 295 mike  1.1         return NULL;
 296           
 297               /* Parse MM */
 298               {
 299                   const MI_Char* end = _ParseNumber(p, &month);
 300           
 301                   if (!end || (end - p) != 2)
 302                       return NULL;
 303           
 304                   p = end;
 305               }
 306           
 307               /* Expect '-' */
 308               if (*p++ != '-')
 309                   return NULL;
 310           
 311               /* Parse DD */
 312               {
 313                   const MI_Char* end = _ParseNumber(p, &day);
 314           
 315                   if (!end || (end - p) != 2)
 316 mike  1.1             return NULL;
 317           
 318                   p = end;
 319               }
 320           
 321               /* Set CIM datetime fields */
 322               memset(x, 0, sizeof(MI_Datetime));
 323               x->isTimestamp = MI_TRUE;
 324               x->u.timestamp.year = (unsigned int)year;
 325               x->u.timestamp.month = (unsigned int)month;
 326               x->u.timestamp.day = (unsigned int)day;
 327           
 328               /* Parse UTC part */
 329               if (*p == 'Z' || *p == '+' || *p == '-')
 330               {
 331                   p = _ParseWSManUTC(p, x);
 332           
 333                   if (!p)
 334                       return NULL;
 335               }
 336           
 337 mike  1.1     return p;
 338           }
 339           
 340           static const MI_Char* _ParseWSManTime(const MI_Char* str, MI_Datetime* x)
 341           {
 342               const MI_Char* p = str;
 343               unsigned long hour = 0;
 344               unsigned long minute = 0;
 345               unsigned long second = 0;
 346               unsigned long microseconds = 0;
 347           
 348               /* Parse "HH" */
 349               {
 350                   const MI_Char* end = _ParseNumber(p, &hour);
 351           
 352                   if (!end || (end - p) != 2)
 353                       return NULL;
 354           
 355                   p = end;
 356               }
 357           
 358 mike  1.1     /* Expect ':' */
 359               if (*p++ != ':')
 360                   return NULL;
 361           
 362               /* Parse "MM" */
 363               {
 364                   const MI_Char* end = _ParseNumber(p, &minute);
 365           
 366                   if (!end || (end - p) != 2)
 367                       return NULL;
 368           
 369                   p = end;
 370               }
 371           
 372               /* Expect ":" */
 373               if (*p++ != ':')
 374                   return NULL;
 375           
 376               /* Parse "SS" */
 377               {
 378                   const MI_Char* end = _ParseNumber(p, &second);
 379 mike  1.1 
 380                   if (!end || (end - p) != 2)
 381                       return NULL;
 382           
 383                   p = end;
 384               }
 385           
 386               /* Parse decimal part */
 387               if (*p == '.')
 388               {
 389                   p++;
 390                   p = _ParseDecimalPart(p, &microseconds);
 391           
 392                   if (!p)
 393                       return NULL;
 394               }
 395           
 396               /* Set CIM datetime fields */
 397               x->isTimestamp = MI_TRUE;
 398               x->u.timestamp.hour = (unsigned int)hour;
 399               x->u.timestamp.minute = (unsigned int)minute;
 400 mike  1.1     x->u.timestamp.second = (unsigned int)second;
 401               x->u.timestamp.microseconds = (unsigned int)microseconds;
 402           
 403               /* Parse UTC part */
 404               if (*p == 'Z' || *p == '+' || *p == '-')
 405               {
 406                   p = _ParseWSManUTC(p, x);
 407           
 408                   if (!p)
 409                       return NULL;
 410               }
 411           
 412               return p;
 413           }
 414           
 415           int ParseWSManDatetime(const MI_Char* str, MI_Datetime* x)
 416           {
 417               const MI_Char* p = str;
 418           
 419               /* Clear datetime */
 420               memset(x, 0, sizeof(MI_Datetime));
 421 mike  1.1 
 422               /* negative xs:duration */
 423               if (*p == '-')
 424               {
 425                   /* Negative intervals not supported by CIM */
 426                   return -1;
 427               }
 428           
 429               /* xs:duration: "PnYnMnDTnHnMnS" */
 430               if (*p == 'P')
 431               {
 432                   return _ParseWSManDuration(str, x);
 433               }
 434           
 435               /* xs:date: "YYYY-MM-DD" plus UTC */
 436               if (isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]))
 437               {
 438                   p = _ParseWSManDate(str, x);
 439           
 440                   if (!p)
 441                       return -1;
 442 mike  1.1 
 443                   if (*p == '\0')
 444                       return 0;
 445           
 446                   /* xs:time "HH:MM:SS" plus UTC */
 447                   if (*p == 'T')
 448                   {
 449                       p++;
 450                       p = _ParseWSManTime(p, x);
 451           
 452                       if (!p)
 453                           return -1;
 454           
 455                       if (*p == '\0')
 456                           return 0;
 457                   }
 458               }
 459           
 460               /* xs:time: "HH:MM:SS" plus UTC */
 461               if (isdigit(p[0]) && isdigit(p[1]) && p[2] == ':')
 462               {
 463 mike  1.1         p = _ParseWSManTime(str, x);
 464           
 465                   if (!p)
 466                       return -1;
 467           
 468                   if (*p == '\0')
 469                       return 0;
 470               }
 471           
 472               /* Failed */
 473               return -1;
 474           }
 475           
 476           void FormatWSManDatetime(const MI_Datetime* x, MI_Char buffer[64])
 477           {
 478               int n = 64;
 479           
 480               *buffer = '\0';
 481           
 482               if (x->isTimestamp)
 483               {
 484 mike  1.1         /* Example output: "2010-12-31T12:30:03.123456+06:00" */
 485                   int haveDate;
 486                   int haveTime;
 487                   MI_Char tmpbuf[64];
 488           
 489                   haveDate = x->u.timestamp.year || x->u.timestamp.month ||
 490                       x->u.timestamp.day;
 491           
 492                   haveTime = x->u.timestamp.hour || x->u.timestamp.minute ||
 493                       x->u.timestamp.second || x->u.timestamp.microseconds;
 494           
 495                   if (haveDate)
 496                   {
 497                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%04u-%02u-%02u"),
 498                           x->u.timestamp.year,
 499                           x->u.timestamp.month,
 500                           x->u.timestamp.day);
 501                       Zlcat(buffer, tmpbuf, n);
 502                   }
 503           
 504                   if (haveTime || !haveDate)
 505 mike  1.1         {
 506                       if (haveDate)
 507                           Zlcat(buffer, T("T"), n);
 508           
 509                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%02u:%02u:%02u"),
 510                           x->u.timestamp.hour,
 511                           x->u.timestamp.minute,
 512                           x->u.timestamp.second);
 513                       Zlcat(buffer, tmpbuf, n);
 514           
 515                       if (x->u.timestamp.microseconds)
 516                       {
 517                           Szprintf(tmpbuf, MI_COUNT(tmpbuf), T(".%06u"), 
 518                               x->u.timestamp.microseconds);
 519                           Zlcat(buffer, tmpbuf, n);
 520                       }
 521           
 522                   }
 523           
 524                   if (x->u.timestamp.utc > 0)
 525                   {
 526 mike  1.1             Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("+%02u:%02u"), 
 527                           x->u.timestamp.utc / 60, x->u.timestamp.utc % 60);
 528                       Zlcat(buffer, tmpbuf, n);
 529                   }
 530                   else if (x->u.timestamp.utc < 0)
 531                   {
 532                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("-%02u:%02u"), 
 533                           -x->u.timestamp.utc / 60, -x->u.timestamp.utc % 60);
 534                       Zlcat(buffer, tmpbuf, n);
 535                   }
 536               }
 537               else
 538               {
 539                   MI_Char tmpbuf[64];
 540           
 541                   /* Example: "P1Y1M22DT10H11M12S" */
 542           
 543                   Zlcat(buffer, T("P"), n);
 544           
 545                   if (x->u.interval.days)
 546                   {
 547 mike  1.1             Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uD"), x->u.interval.days);
 548                       Zlcat(buffer, tmpbuf, n);
 549                   }
 550           
 551                   if (x->u.interval.hours || x->u.interval.minutes || 
 552                       x->u.interval.seconds || x->u.interval.microseconds)
 553                   {
 554                       Zlcat(buffer, T("T"), n);
 555                   }
 556           
 557                   if (x->u.interval.hours)
 558                   {
 559                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uH"), x->u.interval.hours);
 560                       Zlcat(buffer, tmpbuf, n);
 561                   }
 562           
 563                   if (x->u.interval.minutes)
 564                   {
 565                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uM"), x->u.interval.minutes);
 566                       Zlcat(buffer, tmpbuf, n);
 567                   }
 568 mike  1.1 
 569                   if (x->u.interval.seconds && x->u.interval.microseconds)
 570                   {
 571                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%u.%06uS"),
 572                           x->u.interval.seconds, x->u.interval.microseconds);
 573                       Zlcat(buffer, tmpbuf, n);
 574                   }
 575                   else if (x->u.interval.seconds && !x->u.interval.microseconds)
 576                   {
 577                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uS"), x->u.interval.seconds);
 578                       Zlcat(buffer, tmpbuf, n);
 579                   }
 580                   else if (!x->u.interval.seconds && x->u.interval.microseconds)
 581                   {
 582                       Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("0.%06uS"),
 583                           x->u.interval.microseconds);
 584                       Zlcat(buffer, tmpbuf, n);
 585                   }
 586               }
 587           }
 588           
 589 mike  1.1 static int _StrToU32(const MI_Char* s, size_t offset, size_t size, MI_Uint32* x)
 590           {
 591               MI_Char buf[64];
 592               MI_Char* end;
 593           
 594               if (size >= MI_COUNT(buf))
 595                   return -1;
 596           
 597               memcpy(buf, &s[offset], size * sizeof(MI_Char));
 598               buf[size] = '\0';
 599           
 600               *x = (MI_Uint32)Ztoul(buf, &end, 10);
 601           
 602               if (*end != '\0')
 603                   return -1;
 604           
 605               /* Success */
 606               return 0;
 607           }
 608           
 609           int StrToChar16(const MI_Char* str, MI_Char16* x)
 610 mike  1.1 {
 611               MI_Char* end;
 612               *x = (MI_Char16)Ztoul(str, &end, 0);
 613           
 614               if (*end != '\0')
 615                   return -1;
 616           
 617               return 0;
 618           }
 619           
 620           int StrToDatetime(const MI_Char* s, MI_Datetime* x)
 621           {
 622               if (Zlen(s) != 25)
 623                   return -1;
 624           
 625               memset(x, 0, sizeof(MI_Datetime));
 626           
 627               if (s[21] == '+' || s[21] == '-')
 628               {
 629                   MI_Uint32 utc;
 630           
 631 mike  1.1         /* It must be a timestamp (YYYYMMDDHHMMSS.MMMMMMSUTC) */
 632                   if (_StrToU32(s, 0, 4, &x->u.timestamp.year) != 0 ||
 633                       _StrToU32(s, 4, 2, &x->u.timestamp.month) != 0 ||
 634                       _StrToU32(s, 6, 2, &x->u.timestamp.day) != 0 ||
 635                       _StrToU32(s, 8, 2, &x->u.timestamp.hour) != 0 ||
 636                       _StrToU32(s, 10, 2, &x->u.timestamp.minute) != 0 ||
 637                       _StrToU32(s, 12, 2, &x->u.timestamp.second) != 0 ||
 638                       s[14] != '.' ||
 639                       _StrToU32(s, 15, 6, &x->u.timestamp.microseconds) != 0 ||
 640                       _StrToU32(s, 22, 3, &utc) != 0)
 641                   {
 642                       return -1;
 643                   }
 644           
 645                   if (s[21] == '+')
 646                        x->u.timestamp.utc = (MI_Sint32)utc;
 647                   else
 648                        x->u.timestamp.utc = -(MI_Sint32)utc;
 649           
 650                   x->isTimestamp = 1;
 651               }
 652 mike  1.1     else if (s[21] == ':')
 653               {
 654                   /* It must be an interval (DDDDDDDDHHMMSS.MMMMMM:000) */
 655                   if (_StrToU32(s, 0, 8, &x->u.interval.days) != 0 ||
 656                       _StrToU32(s, 8, 2, &x->u.interval.hours) != 0 ||
 657                       _StrToU32(s, 10, 2, &x->u.interval.minutes) != 0 ||
 658                       _StrToU32(s, 12, 2, &x->u.interval.seconds) != 0 ||
 659                       s[14] != '.' ||
 660                       _StrToU32(s, 15, 6, &x->u.interval.microseconds) != 0 ||
 661                       s[22] != '0' || s[23] != '0' || s[24] != '0')
 662                   {
 663                       return -1;
 664                   }
 665           
 666                   x->isTimestamp = 0;
 667               }
 668               else
 669                   return -1;
 670           
 671               return 0;
 672           }
 673 mike  1.1 
 674           static int _ParseDatetime(const MI_Char* str, MI_Datetime* x)
 675           {
 676               if (StrToDatetime(str, x) == 0)
 677                   return 0;
 678           
 679               if (ParseWSManDatetime(str, x) == 0)
 680                   return 0;
 681           
 682               return -1;
 683           }
 684           
 685           int StrToBoolean(const MI_Char* str, MI_Boolean* x)
 686           {
 687               if (Zcasecmp(str, T("true")) == 0)
 688                   *x = MI_TRUE;
 689               else if (Zcasecmp(str, T("false")) == 0)
 690                   *x = MI_FALSE;
 691               else
 692                   return -1;
 693           
 694 mike  1.1     return 0;
 695           }
 696           
 697           int StrToUint8(const MI_Char* str, MI_Uint8* x)
 698           {
 699               MI_Char* end;
 700               *x = (MI_Uint8)Ztoul(str, &end, 0);
 701           
 702               if (*end != '\0')
 703                   return -1;
 704           
 705               return 0;
 706           }
 707           
 708           int StrToSint8(const MI_Char* str, MI_Sint8* x)
 709           {
 710               MI_Char* end;
 711               *x = (MI_Sint8)Ztol(str, &end, 0);
 712           
 713               if (*end != '\0')
 714                   return -1;
 715 mike  1.1 
 716               return 0;
 717           }
 718           
 719           int StrToUint16(const MI_Char* str, MI_Uint16* x)
 720           {
 721               MI_Char* end;
 722               *x = (MI_Uint16)Ztoul(str, &end, 0);
 723           
 724               if (*end != '\0')
 725                   return -1;
 726           
 727               return 0;
 728           }
 729           
 730           int StrToSint16(const MI_Char* str, MI_Sint16* x)
 731           {
 732               MI_Char* end;
 733               *x = (MI_Sint16)Ztol(str, &end, 0);
 734           
 735               if (*end != '\0')
 736 mike  1.1         return -1;
 737           
 738               return 0;
 739           }
 740           
 741           int StrToUint32(const MI_Char* str, MI_Uint32* x)
 742           {
 743               MI_Char* end;
 744               *x = (MI_Uint32)Ztoul(str, &end, 0);
 745           
 746               if (*end != '\0')
 747                   return -1;
 748           
 749               return 0;
 750           }
 751           
 752           int StrToSint32(const MI_Char* str, MI_Sint32* x)
 753           {
 754               MI_Char* end;
 755               *x = (MI_Sint32)Ztol(str, &end, 0);
 756           
 757 mike  1.1     if (*end != '\0')
 758                   return -1;
 759           
 760               return 0;
 761           }
 762           
 763           int StrToUint64(const MI_Char* str, MI_Uint64* x)
 764           {
 765               MI_Char* end;
 766               *x = (MI_Uint64)Ztoull(str, &end, 0);
 767           
 768               if (*end != '\0')
 769                   return -1;
 770           
 771               return 0;
 772           }
 773           
 774           int StrToSint64(const MI_Char* str, MI_Sint64* x)
 775           {
 776               MI_Char* end;
 777               *x = (MI_Sint64)Ztoll(str, &end, 0);
 778 mike  1.1 
 779               if (*end != '\0')
 780                   return -1;
 781           
 782               return 0;
 783           }
 784           
 785           int StrToReal32(const MI_Char* str, MI_Real32* x)
 786           {
 787               MI_Char* end;
 788               *x = (MI_Real32)Ztod(str, &end);
 789           
 790               if (*end != '\0')
 791                   return -1;
 792           
 793               return 0;
 794           }
 795           
 796           int StrToReal64(const MI_Char* str, MI_Real64* x)
 797           {
 798               MI_Char* end;
 799 mike  1.1     *x = (MI_Real64)Ztod(str, &end);
 800           
 801               if (*end != '\0')
 802                   return -1;
 803           
 804               return 0;
 805           }
 806           
 807           MI_Result MI_CALL Instance_SetElementFromString(
 808               MI_Instance* self, 
 809               const MI_Char* name, 
 810               const MI_Char* str)
 811           {
 812               /* ATTN: check for integer value truncation (see use of Ztol) */
 813               /* ATTN: implement array types! */
 814               /* ATTN: implement instance and reference types! */
 815               MI_Type type;
 816               MI_Value value;
 817           
 818               /* Check arguments */
 819               if (!self || !name || !str)
 820 mike  1.1         MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 821           
 822               /* Obtain type of named property */
 823               {
 824                   MI_Result r = MI_Instance_GetElement(self, name, NULL, &type, 
 825                       NULL, NULL);
 826           
 827                   if (r != MI_RESULT_OK)
 828                       return r;
 829               }
 830           
 831               /* If type is array and value is string,
 832                   try to create a single item array from this string
 833               */
 834               if (0 != (MI_ARRAY_BIT & type))
 835                   return Instance_SetElementFromStringA(
 836                       self, name, &str, 1);
 837           
 838           
 839               /* Convert string to value */
 840               switch (type)
 841 mike  1.1     {
 842                   case MI_BOOLEAN:
 843                   {
 844                       if (StrToBoolean(str, &value.boolean) != 0)
 845                           MI_RETURN(MI_RESULT_FAILED);
 846                       break;
 847                   }
 848                   case MI_UINT8:
 849                   {
 850                       if (StrToUint8(str, &value.uint8) != 0)
 851                           MI_RETURN(MI_RESULT_FAILED);
 852                       break;
 853                   }
 854                   case MI_SINT8:
 855                   {
 856                       if (StrToSint8(str, &value.sint8) != 0)
 857                           MI_RETURN(MI_RESULT_FAILED);
 858                       break;
 859                   }
 860                   case MI_UINT16:
 861                   {
 862 mike  1.1             if (StrToUint16(str, &value.uint16) != 0)
 863                           MI_RETURN(MI_RESULT_FAILED);
 864                       break;
 865                   }
 866                   case MI_SINT16:
 867                   {
 868                       if (StrToSint16(str, &value.sint16) != 0)
 869                           MI_RETURN(MI_RESULT_FAILED);
 870                       break;
 871                   }
 872                   case MI_UINT32:
 873                   {
 874                       if (StrToUint32(str, &value.uint32) != 0)
 875                           MI_RETURN(MI_RESULT_FAILED);
 876                       break;
 877                   }
 878                   case MI_SINT32:
 879                   {
 880                       if (StrToSint32(str, &value.sint32) != 0)
 881                           MI_RETURN(MI_RESULT_FAILED);
 882                       break;
 883 mike  1.1         }
 884                   case MI_UINT64:
 885                   {
 886                       if (StrToUint64(str, &value.uint64) != 0)
 887                           MI_RETURN(MI_RESULT_FAILED);
 888                       break;
 889                   }
 890                   case MI_SINT64:
 891                   {
 892                       if (StrToSint64(str, &value.sint64) != 0)
 893                           MI_RETURN(MI_RESULT_FAILED);
 894                       break;
 895                   }
 896                   case MI_REAL32:
 897                   {
 898                       if (StrToReal32(str, &value.real32) != 0)
 899                           MI_RETURN(MI_RESULT_FAILED);
 900                       break;
 901                   }
 902                   case MI_REAL64:
 903                   {
 904 mike  1.1             if (StrToReal64(str, &value.real64) != 0)
 905                           MI_RETURN(MI_RESULT_FAILED);
 906                       break;
 907                   }
 908                   case MI_CHAR16:
 909                   {
 910                       if (StrToUint16(str, &value.char16) != 0)
 911                           MI_RETURN(MI_RESULT_FAILED);
 912                       break;
 913                   }
 914                   case MI_DATETIME:
 915                   {
 916                       if (_ParseDatetime(str, &value.datetime) != 0)
 917                           MI_RETURN(MI_RESULT_FAILED);
 918                       break;
 919                   }
 920                   case MI_STRING:
 921                   {
 922                       value.string = (MI_Char*)str;
 923                       break;
 924                   }
 925 mike  1.1         default:
 926                   {
 927                       MI_RETURN(MI_RESULT_FAILED);
 928                   }
 929               }
 930           
 931               MI_RETURN(MI_Instance_SetElement(self, name, &value, type, 0));
 932           }
 933           
 934           MI_Result MI_CALL Instance_SetElementFromStringA(
 935               MI_Instance* self_, 
 936               const MI_Char* name, 
 937               const MI_Char** data,
 938               MI_Uint32 size)
 939           {
 940               Instance* self = (Instance*)self_;
 941               MI_Type type = MI_BOOLEAN;
 942               MI_Value v;
 943               MI_Uint32 i;
 944               MI_Result result = MI_RESULT_OK;
 945               MI_Uint32 flags = 0;
 946 mike  1.1 
 947               /* Clear value first */
 948               memset(&v, 0, sizeof(v));
 949           
 950               /* Check arguments */
 951               if (!self || !name || !data)
 952               {
 953                   /* return instead of goto failed: 'v' is not initialized yet */
 954                   return MI_RESULT_INVALID_PARAMETER;
 955               }
 956           
 957               /* Obtain type of named property */
 958               if (MI_Instance_GetElement(self_, name, NULL, &type, NULL, NULL))
 959               {
 960                   /* return instead of goto failed: 'v' is not initialized yet */
 961                   return MI_RESULT_FAILED;
 962               }
 963           
 964               /* Allocate array (allocate extra element for possible empty array) */
 965               if (type == MI_STRINGA)
 966               {
 967 mike  1.1         v.array.data = (MI_Char**)data;
 968                   v.array.size = size;
 969               }
 970               else
 971               {
 972                   MI_Uint32 esize = (MI_Uint32)Type_SizeOf(Type_ScalarOf(type));
 973                   v.array.data = BAlloc(self->batch, (size + 1) * esize, CALLSITE);
 974           
 975                   if (!v.array.data)
 976                   {
 977                       result = MI_RESULT_FAILED;
 978                       goto done;
 979                   }
 980           
 981                   v.array.size = size;
 982                   flags |= MI_FLAG_ADOPT;
 983               }
 984           
 985               /* Convert string to v */
 986               switch (type)
 987               {
 988 mike  1.1         case MI_BOOLEANA:
 989                   {
 990                       for (i = 0; i < size; i++)
 991                       {
 992                           if (StrToBoolean(data[i], &v.booleana.data[i]) != 0)
 993                           {
 994                               result = MI_RESULT_FAILED;
 995                               goto done;
 996                           }
 997                       }
 998                       break;
 999                   }
1000                   case MI_UINT8A:
1001                   {
1002                       for (i = 0; i < size; i++)
1003                       {
1004                           if (StrToUint8(data[i], &v.uint8a.data[i]) != 0)
1005                           {
1006                               result = MI_RESULT_FAILED;
1007                               goto done;
1008                           }
1009 mike  1.1             }
1010                       break;
1011                   }
1012                   case MI_SINT8A:
1013                   {
1014                       for (i = 0; i < size; i++)
1015                       {
1016                           if (StrToSint8(data[i], &v.sint8a.data[i]) != 0)
1017                           {
1018                               result = MI_RESULT_FAILED;
1019                               goto done;
1020                           }
1021                       }
1022                       break;
1023                   }
1024                   case MI_UINT16A:
1025                   {
1026                       for (i = 0; i < size; i++)
1027                       {
1028                           if (StrToUint16(data[i], &v.uint16a.data[i]) != 0)
1029                           {
1030 mike  1.1                     result = MI_RESULT_FAILED;
1031                               goto done;
1032                           }
1033                       }
1034                       break;
1035                   }
1036                   case MI_SINT16A:
1037                   {
1038                       for (i = 0; i < size; i++)
1039                       {
1040                           if (StrToSint16(data[i], &v.sint16a.data[i]) != 0)
1041                           {
1042                               result = MI_RESULT_FAILED;
1043                               goto done;
1044                           }
1045                       }
1046                       break;
1047                   }
1048                   case MI_UINT32A:
1049                   {
1050                       for (i = 0; i < size; i++)
1051 mike  1.1             {
1052                           if (StrToUint32(data[i], &v.uint32a.data[i]) != 0)
1053                           {
1054                               result = MI_RESULT_FAILED;
1055                               goto done;
1056                           }
1057                       }
1058                       break;
1059                   }
1060                   case MI_SINT32A:
1061                   {
1062                       for (i = 0; i < size; i++)
1063                       {
1064                           if (StrToSint32(data[i], &v.sint32a.data[i]) != 0)
1065                           {
1066                               result = MI_RESULT_FAILED;
1067                               goto done;
1068                           }
1069                       }
1070                       break;
1071                   }
1072 mike  1.1         case MI_UINT64A:
1073                   {
1074                       for (i = 0; i < size; i++)
1075                       {
1076                           if (StrToUint64(data[i], &v.uint64a.data[i]) != 0)
1077                           {
1078                               result = MI_RESULT_FAILED;
1079                               goto done;
1080                           }
1081                       }
1082                       break;
1083                   }
1084                   case MI_SINT64A:
1085                   {
1086                       for (i = 0; i < size; i++)
1087                       {
1088                           if (StrToSint64(data[i], &v.sint64a.data[i]) != 0)
1089                           {
1090                               result = MI_RESULT_FAILED;
1091                               goto done;
1092                           }
1093 mike  1.1             }
1094                       break;
1095                   }
1096                   case MI_REAL32A:
1097                   {
1098                       for (i = 0; i < size; i++)
1099                       {
1100                           if (StrToReal32(data[i], &v.real32a.data[i]) != 0)
1101                           {
1102                               result = MI_RESULT_FAILED;
1103                               goto done;
1104                           }
1105                       }
1106                       break;
1107                   }
1108                   case MI_REAL64A:
1109                   {
1110                       for (i = 0; i < size; i++)
1111                       {
1112                           if (StrToReal64(data[i], &v.real64a.data[i]) != 0)
1113                           {
1114 mike  1.1                     result = MI_RESULT_FAILED;
1115                               goto done;
1116                           }
1117                       }
1118                       break;
1119                   }
1120                   case MI_CHAR16A:
1121                   {
1122                       for (i = 0; i < size; i++)
1123                       {
1124                           if (StrToChar16(data[i], &v.char16a.data[i]) != 0)
1125                           {
1126                               result = MI_RESULT_FAILED;
1127                               goto done;
1128                           }
1129                       }
1130                       break;
1131                   }
1132                   case MI_DATETIMEA:
1133                   {
1134                       for (i = 0; i < size; i++)
1135 mike  1.1             {
1136                           if (_ParseDatetime(data[i], &v.datetimea.data[i]) != 0)
1137                           {
1138                               result = MI_RESULT_FAILED;
1139                               goto done;
1140                           }
1141                       }
1142                       break;
1143                   }
1144                   case MI_STRINGA:
1145                   {
1146                       // Handled above.
1147                       break;
1148                   }
1149                   default:
1150                   {
1151                       result = MI_RESULT_FAILED;
1152                       goto done;
1153                   }
1154               }
1155           
1156 mike  1.1     if (MI_Instance_SetElement(self_, name, &v, type, flags))
1157               {
1158                   result = MI_RESULT_FAILED;
1159                   goto done;
1160               }
1161           
1162           done:
1163           
1164               if (result && v.array.data && type != MI_STRINGA)
1165                   BFree(self->batch, v.array.data, CALLSITE);
1166           
1167               return result;
1168           }
1169           
1170           MI_Result MI_CALL Instance_GetValue(
1171               MI_Instance* self, 
1172               const MI_Char* name, 
1173               void* value,
1174               MI_Type type)
1175           {
1176               MI_Result r;
1177 mike  1.1     MI_Value v;
1178               MI_Type t;
1179               MI_Uint32 f;
1180           
1181               r = MI_Instance_GetElement(self, name, &v, &t, &f, NULL);
1182           
1183               if (r != MI_RESULT_OK)
1184                   MI_RETURN(r);
1185           
1186               if (t != type)
1187                   MI_RETURN(MI_RESULT_TYPE_MISMATCH);
1188           
1189               if (f & MI_FLAG_NULL)
1190                   MI_RETURN(MI_RESULT_NOT_FOUND);
1191           
1192               if (!value)
1193                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1194           
1195               memcpy(value, &v, Type_SizeOf(type));
1196           
1197               MI_RETURN(MI_RESULT_OK);
1198 mike  1.1 }
1199           
1200           void DatetimeToStr(const MI_Datetime* x, MI_Char buf[26])
1201           {
1202               if (x->isTimestamp)
1203               {
1204                   const MI_Char FMT[] =  MI_T("%04d%02d%02d%02d%02d%02d.%06d%c%03d");
1205                   MI_Sint32 utc = x->u.timestamp.utc;
1206                   Szprintf(buf, 26, FMT,
1207                       x->u.timestamp.year,
1208                       x->u.timestamp.month,
1209                       x->u.timestamp.day,
1210                       x->u.timestamp.hour,
1211                       x->u.timestamp.minute,
1212                       x->u.timestamp.second,
1213                       x->u.timestamp.microseconds,
1214                       utc < 0 ? '-' : '+',
1215                       utc < 0 ? -utc : utc);
1216               }
1217               else
1218               {
1219 mike  1.1         const MI_Char FMT[] = MI_T("%08u%02u%02u%02u.%06u:000");
1220                   Szprintf(buf, 26, FMT,
1221                       x->u.interval.days,
1222                       x->u.interval.hours,
1223                       x->u.interval.minutes,
1224                       x->u.interval.seconds,
1225                       x->u.interval.microseconds);
1226               }
1227           }

ViewCVS 0.9.2