ソースを参照

cmData.h/c : Completed initial implementation of cmDataParser.

master
kevin 10年前
コミット
1a70a5afa0
2個のファイルの変更516行の追加77行の削除
  1. 505
    71
      cmData.c
  2. 11
    6
      cmData.h

+ 505
- 71
cmData.c ファイルの表示

@@ -4,8 +4,10 @@
4 4
 #include "cmCtx.h"
5 5
 #include "cmMem.h"
6 6
 #include "cmMallocDebug.h"
7
+#include "cmLinkedHeap.h"
7 8
 #include "cmData.h"
8 9
 #include "cmLex.h"
10
+#include "cmText.h"
9 11
 #include "cmStack.h"
10 12
 
11 13
 cmDtRC_t _cmDataErrNo = kOkDtRC;
@@ -668,20 +670,26 @@ cmData_t* cmDataSetDoublePtr( cmData_t* p, double* vp,         unsigned cnt )
668 670
 
669 671
 // Set the value of an existing array based data object. 
670 672
 // Allocate the internal array and copy the array into it.
671
-cmData_t* cmDataSetStrAlloc( cmData_t* p, const cmChar_t* s )
673
+cmData_t* cmDataSetStrAllocN( cmData_t* p, const cmChar_t* s, unsigned charCnt )
672 674
 {
673 675
   if( cmIsFlag(p->flags,kDynPtrDtFl) )
674
-    cmMemResizeStr(p->u.z,s);
676
+    cmMemResizeStrN(p->u.z,s,charCnt);
675 677
   else
676 678
   {
677 679
     _cmDataFreeArray(p);
678
-    p->u.z = cmMemAllocStr(s);
680
+    p->u.z = cmMemAllocStrN(s,charCnt);
679 681
   }
680 682
   p->tid    = kStrDtId;
681 683
   p->flags  = cmSetFlag(p->flags,kDynPtrDtFl);
682 684
   return p;
683 685
 }
684 686
 
687
+cmData_t* cmDataSetStrAlloc( cmData_t* p, const cmChar_t* s )
688
+{ return cmDataSetStrAllocN(p,s,strlen(s)); }
689
+
690
+cmData_t* cmDataSetConstStrAllocN(  cmData_t* p, const cmChar_t* s, unsigned charCnt )
691
+{ return cmDataSetStrAllocN(p,s,charCnt); }
692
+
685 693
 cmData_t* cmDataSetConstStrAlloc(  cmData_t* p, const cmChar_t* s )
686 694
 { return cmDataSetStrAlloc(p,s); }
687 695
 
@@ -697,6 +705,7 @@ cmData_t* cmDataSetCharAllocPtr(  cmData_t* p, const char* vp,  unsigned cnt )
697 705
     _cmDataFreeArray(p);
698 706
     p->u.cp = cmMemAlloc(char, cnt );
699 707
   }
708
+
700 709
   memcpy(p->u.cp,vp,sizeof(char)*cnt);
701 710
   p->tid   = kCharPtrDtId;
702 711
   p->flags = cmSetFlag(p->flags,kDynPtrDtFl);
@@ -1034,6 +1043,14 @@ cmData_t* cmDataStrAlloc( cmData_t* parent, cmChar_t* str )
1034 1043
   return p;
1035 1044
 }
1036 1045
 
1046
+cmData_t* cmDataConstStrAllocN( cmData_t* parent, const cmChar_t* str, unsigned charCnt )
1047
+{
1048
+  cmData_t* p = _cmDataAllocNode(parent,kConstStrDtId);
1049
+  cmDataSetConstStrAllocN(p,str,charCnt);
1050
+  return p;
1051
+}
1052
+
1053
+
1037 1054
 cmData_t* cmDataConstStrAlloc( cmData_t* parent, const cmChar_t* str )
1038 1055
 {
1039 1056
   cmData_t* p = _cmDataAllocNode(parent,kConstStrDtId);
@@ -1460,6 +1477,15 @@ cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t *label, cmData_
1460 1477
   cmDataAppendChild(p,value);
1461 1478
   return p;
1462 1479
 }
1480
+
1481
+cmData_t* cmDataAllocPairLabelN(cmData_t* parent, const cmChar_t* label, unsigned charCnt, cmData_t* value)
1482
+{
1483
+  cmData_t* p  = _cmDataAllocNode(parent,kPairDtId);
1484
+  cmDataConstStrAllocN(p,label,charCnt);
1485
+  cmDataAppendChild(p,value);
1486
+  return p;
1487
+}
1488
+
1463 1489
   
1464 1490
 //----------------------------------------------------------------------------
1465 1491
 
@@ -1759,7 +1785,7 @@ const cmChar_t* cmDataRecdKeyLabel( cmData_t* p, unsigned index )
1759 1785
   return label;
1760 1786
 }
1761 1787
   
1762
-cmData_t*       cmRecdMake( cmData_t* parent, cmData_t* p )
1788
+cmData_t*       cmDataRecdMake( cmData_t* parent, cmData_t* p )
1763 1789
 {
1764 1790
   _cmDataFree(p);
1765 1791
   p->parent  = parent;
@@ -1769,10 +1795,10 @@ cmData_t*       cmRecdMake( cmData_t* parent, cmData_t* p )
1769 1795
   return p;
1770 1796
 }
1771 1797
 
1772
-cmData_t*       cmRecdAlloc(cmData_t* parent)
1798
+cmData_t*       cmDataRecdAlloc(cmData_t* parent)
1773 1799
 { return _cmDataAllocNode(parent,kRecordDtId); }
1774 1800
 
1775
-cmData_t* cmRecdAppendPair( cmData_t* p, cmData_t* pair )
1801
+cmData_t* cmDataRecdAppendPair( cmData_t* p, cmData_t* pair )
1776 1802
 {
1777 1803
   assert( p!=NULL && p->tid==kRecordDtId);
1778 1804
   cmDataAppendChild(p,pair);
@@ -1822,7 +1848,7 @@ cmDtRC_t  _cmDataRecdParseInputV(cmData_t* parent, unsigned idFl, va_list vl )
1822 1848
 
1823 1849
 cmData_t*       cmDataRecdAllocLabelV( cmData_t* parent, va_list vl )
1824 1850
 {
1825
-  cmData_t* p = cmRecdAlloc(parent);
1851
+  cmData_t* p = cmDataRecdAlloc(parent);
1826 1852
   cmDtRC_t rc = _cmDataRecdParseInputV(p, false, vl );
1827 1853
   if( rc != kOkDtRC )
1828 1854
   {
@@ -1843,7 +1869,7 @@ cmData_t*       cmDataRecdAllocLabelA( cmData_t* parent, ... )
1843 1869
 
1844 1870
 cmData_t*       cmDataRecdAllocIdV( cmData_t* parent, va_list vl )
1845 1871
 {
1846
-  cmData_t* p = cmRecdAlloc(parent);
1872
+  cmData_t* p = cmDataRecdAlloc(parent);
1847 1873
   cmDtRC_t rc = _cmDataRecdParseInputV(p, true, vl );
1848 1874
   if( rc != kOkDtRC )
1849 1875
   {
@@ -2181,7 +2207,6 @@ cmDtRC_t cmDataDeserialize( const void* buf, unsigned bufByteCnt, cmData_t** pp
2181 2207
 //============================================================================
2182 2208
 //============================================================================
2183 2209
 //============================================================================
2184
-#ifdef NOT_DEF
2185 2210
 enum
2186 2211
 {
2187 2212
   kLCurlyLexTId = kUserLexTId + 1,
@@ -2196,7 +2221,7 @@ enum
2196 2221
 
2197 2222
 typedef struct
2198 2223
 {
2199
-  unsigned id;
2224
+  unsigned        id;
2200 2225
   const cmChar_t* label;
2201 2226
 } cmDtToken_t;
2202 2227
 
@@ -2222,10 +2247,6 @@ typedef struct
2222 2247
 
2223 2248
 } cmDataParser_t;
2224 2249
 
2225
-typedef struct
2226
-{
2227
-  unsigned tokId;
2228
-} cmDataStEle_t;
2229 2250
 
2230 2251
 cmDataParserH_t cmDataParserNullHandle = cmSTATIC_NULL_HANDLE;
2231 2252
 
@@ -2239,10 +2260,10 @@ cmDataParser_t* _cmDataParserHandleToPtr( cmDataParserH_t h )
2239 2260
 cmDtRC_t _cmDataParserDestroy( cmDataParser_t* p )
2240 2261
 {
2241 2262
   if( cmLexFinal(&p->lexH) != kOkLexRC )
2242
-    cmErrMsg(&p->err,kLexFailedDtRC,"Lexer release failed.");
2263
+    cmErrMsg(&p->err,kLexFailDtRC,"Lexer release failed.");
2243 2264
 
2244 2265
   if( cmStackFree(&p->stH) != kOkStRC )
2245
-    cmErrMsg(&p->err,kParserStackFailDtRC,"The data object parser stack release failed.");
2266
+    cmErrMsg(&p->err,kParseStackFailDtRC,"The data object parser stack release failed.");
2246 2267
 
2247 2268
   return kOkDtRC;
2248 2269
 }
@@ -2257,22 +2278,22 @@ cmDtRC_t cmDataParserCreate( cmCtx_t* ctx, cmDataParserH_t* hp )
2257 2278
 
2258 2279
   cmDataParser_t* p = cmMemAllocZ(cmDataParser_t,1);
2259 2280
 
2260
-  cmErrSetup(&p->err,&ctx->err,"Data Parser");
2281
+  cmErrSetup(&p->err,&ctx->rpt,"Data Parser");
2261 2282
 
2262
-  if(cmLexIsValid(p->lexH = cmLexInit(NULL,0,0,err->rpt))==false)
2283
+  if(cmLexIsValid(p->lexH = cmLexInit(NULL,0,0,&ctx->rpt))==false)
2263 2284
   {
2264
-    rc = cmErrMsg(err, kLexFailDtRC, "The data object parser lexer create failed.");
2285
+    rc = cmErrMsg(&p->err, kLexFailDtRC, "The data object parser lexer create failed.");
2265 2286
     goto errLabel;
2266 2287
   }
2267 2288
 
2268
-  for(i=0; cmDtTokeyArray[i].id!=kErrorLexTId; ++i)
2269
-    if( cmLexRegisterToken(p->lexH, cmDtTokenArray[i].id, cmDtTokenArray[i].label) != kOkLexRC )
2289
+  for(i=0; _cmDtTokenArray[i].id != kErrorLexTId; ++i)
2290
+    if( cmLexRegisterToken(p->lexH, _cmDtTokenArray[i].id, _cmDtTokenArray[i].label) != kOkLexRC )
2270 2291
     {
2271
-      rc = cmErrMsg(&p->err,kLexFailDtRC,"The data object parser lexer could not register the '%s' token.",cmDtTokenArray[i].label);
2292
+      rc = cmErrMsg(&p->err,kLexFailDtRC,"The data object parser lexer could not register the '%s' token.",_cmDtTokenArray[i].label);
2272 2293
       goto errLabel;
2273 2294
     }
2274 2295
 
2275
-  if( cmStackAlloc(ctx, &p->stH, 1024, 1024, sizeof(cmDataStEle_t)) != kOkStRC )
2296
+  if( cmStackAlloc(ctx, &p->stH, 1024, 1024, sizeof(cmData_t*)) != kOkStRC )
2276 2297
   {
2277 2298
     rc = cmErrMsg(&p->err,kParseStackFailDtRC,"The data object parser stack create failed.");
2278 2299
     goto errLabel;
@@ -2287,7 +2308,7 @@ cmDtRC_t cmDataParserCreate( cmCtx_t* ctx, cmDataParserH_t* hp )
2287 2308
   return kOkDtRC;
2288 2309
 }
2289 2310
 
2290
-cmDtRC_t cmDataParserDestroy( cmErr_t* err, cmDataParserH_t* hp )
2311
+cmDtRC_t cmDataParserDestroy( cmDataParserH_t* hp )
2291 2312
 {
2292 2313
   cmDtRC_t rc=kOkDtRC;
2293 2314
 
@@ -2309,91 +2330,460 @@ bool     cmDataParserIsValid( cmDataParserH_t h )
2309 2330
 { return h.h != NULL; }
2310 2331
 
2311 2332
 
2312
-cmDtRC_t _cmDataLexErrorV( cmErr_t* err, cmLexH_t lexH, const cmChar_t* fmt, va_list vl )
2333
+
2334
+// {
2335
+//  id0 : scalar_value
2336
+//  id1 : ( heterogenous, array, value )
2337
+//  id2 : [ homogeneous array values ]
2338
+//  id3 : 
2339
+// }
2340
+
2341
+
2342
+// flags describing the expected next token
2343
+enum
2344
+{
2345
+  kValueExpFl = 0x01,
2346
+  kIdExpFl    = 0x02,
2347
+  kColonExpFl = 0x04,
2348
+  kCommaExpFl = 0x08
2349
+};
2350
+
2351
+typedef struct
2352
+{
2353
+  cmData_t* dp;
2354
+} cmDataStEle_t;
2355
+
2356
+typedef struct
2313 2357
 {
2358
+  cmDataParser_t*  p;
2359
+  cmData_t*        cnp;
2360
+  unsigned         flags;
2361
+  cmChar_t*        tmpStr;
2362
+
2363
+  unsigned         arrayCnt;
2364
+  void*            arrayMem;
2314 2365
   
2366
+} cmDataParserCtx_t;
2367
+
2368
+cmDtRC_t _cmDpSyntaxErrV( cmDataParserCtx_t* c, const cmChar_t* fmt, va_list vl )
2369
+{
2370
+  cmChar_t* s0 = NULL;
2371
+  s0 = cmTsVPrintfP(s0,fmt,vl);
2372
+  cmDtRC_t rc = cmErrMsg(&c->p->err,kSyntaxErrDtRC,"Syntax error on line %i. %s",cmLexCurrentLineNumber(c->p->lexH),cmStringNullGuard(s0));
2373
+  cmMemFree(s0);
2374
+  return rc;
2315 2375
 }
2316 2376
 
2317
-cmDtRC_t _cmDataLexError( cmErr_t* err, cmLexH_t lexH, const cmChar_t* fmt, ... )
2377
+cmDtRC_t _cmDpSyntaxErr( cmDataParserCtx_t* c, const cmChar_t* fmt, ... )
2318 2378
 {
2319 2379
   va_list vl;
2320 2380
   va_start(vl,fmt);
2321
-  cmDtRC_t rc, _cmDataLexErrorV(err,lexH,fmt,vl);
2381
+  cmDtRC_t rc = _cmDpSyntaxErrV(c,fmt,vl);
2322 2382
   va_end(vl);
2323 2383
   return rc;
2324 2384
 }
2325 2385
 
2326
-// {
2327
-//  id0 : scalar_value
2328
-//  id1 : ( heterogenous, array, value )
2329
-//  id2 : [ homogeneous array values ]
2330
-//  id3 : 
2331
-// }
2386
+cmDtRC_t _cmDpPopStack(  cmDataParserCtx_t* c, cmData_t** pp )
2387
+{
2388
+  const void* vp;
2389
+  if((vp = cmStackTop(c->p->stH)) == NULL )
2390
+    return _cmDpSyntaxErr(c,"Stack underflow.");
2391
+  
2392
+  *pp = *(cmData_t**)vp;
2332 2393
 
2333
-enum
2394
+  return kOkDtRC;
2395
+}
2396
+
2397
+cmDtRC_t _cmDpStoreArrayEle( cmDataParserCtx_t* c, void* dp, unsigned byteCnt )
2334 2398
 {
2335
-  kRecdStateId,
2336
-  kFieldValueStateId,
2337
-  kArrayValueStateId
2338
-};
2399
+  char* vp = cmMemResize(char, c->cnp->u.vp, c->cnp->cnt+byteCnt);
2400
+  
2401
+  memcpy(vp + c->cnp->cnt,dp,byteCnt);
2402
+  c->cnp->u.vp = vp;
2403
+  c->cnp->cnt += byteCnt;
2404
+  
2405
+  c->flags = kValueExpFl | kCommaExpFl;
2406
+
2407
+  return kOkDtRC;
2408
+}
2409
+
2410
+cmDtRC_t _cmDataParserOpenPair( cmDataParserCtx_t* c )
2411
+{
2412
+  assert( c->cnp->tid == kRecordDtId );
2413
+
2414
+  cmData_t* nnp = cmDataAllocNull(NULL);
2415
+  cmData_t* pnp = cmDataAllocPairLabelN( c->cnp, cmLexTokenText(c->p->lexH), cmLexTokenCharCount(c->p->lexH), nnp );
2416
+
2417
+  // store the current node
2418
+  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2419
+    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2420
+
2421
+  // make the new pair the current node
2422
+  c->cnp = pnp;
2423
+
2424
+  // pair openings must be followed by a colon.
2425
+  c->flags  = kColonExpFl;
2426
+ 
2427
+  return kOkDtRC;
2428
+}
2429
+
2430
+cmDtRC_t _cmDataParserClosePair( cmDataParserCtx_t* c )
2431
+{
2432
+  cmDtRC_t rc;
2433
+
2434
+  // make the pair's parent record the current node
2435
+  if((rc = _cmDpPopStack(c, &c->cnp )) != kOkDtRC )
2436
+    return rc;
2437
+
2438
+  // pairs only occur in records
2439
+  if( c->cnp->tid != kRecordDtId )
2440
+    return _cmDpSyntaxErr(c,"A 'pair' end was found outside of a 'record'.");
2441
+
2442
+  // pairs must be followed by id's or comma's
2443
+  c->flags = kIdExpFl | kCommaExpFl; 
2444
+
2445
+  return rc;
2446
+}
2447
+
2448
+cmDtRC_t _cmDpStoreValue( cmDataParserCtx_t* c, cmData_t* np, const cmChar_t* typeLabel )
2449
+{
2450
+  assert( np != NULL );
2451
+
2452
+  cmDtRC_t rc = kOkDtRC;
2453
+
2454
+  switch( c->cnp->tid )
2455
+  {
2456
+    case kPairDtId:
2457
+
2458
+      // assign the new node as the value of the pair
2459
+      cmDataPairSetValue(c->cnp,np);
2460
+
2461
+      // close the values parent pair
2462
+      rc = _cmDataParserClosePair(c);
2463
+      break;
2464
+
2465
+    case kListDtId:      
2466
+      cmDataAppendChild(c->cnp,np);
2467
+      c->flags = kValueExpFl;
2468
+      break;
2469
+
2470
+    default:
2471
+      rc = _cmDpSyntaxErr(c,"A '%s' value was found outside of a valid container.",typeLabel);
2472
+  }
2473
+
2474
+  c->flags |= kCommaExpFl;
2475
+
2476
+  return rc;
2477
+}
2478
+
2479
+cmDtRC_t _cmDataParserReal( cmDataParserCtx_t* c )
2480
+{
2481
+  cmDtRC_t rc  = kOkDtRC;
2482
+  double   val = cmLexTokenDouble(c->p->lexH);
2483
+
2484
+  if( c->cnp->tid == kVoidPtrDtId )
2485
+    rc = _cmDpStoreArrayEle(c,&val,sizeof(val));
2486
+  else
2487
+    rc = _cmDpStoreValue(c,cmDataAllocDouble(NULL,val),"real");
2488
+
2489
+  return rc;
2490
+}
2491
+
2492
+cmDtRC_t _cmDataParserInt( cmDataParserCtx_t* c )
2493
+{
2494
+  cmDtRC_t rc  = kOkDtRC;
2495
+  int      val = cmLexTokenInt(c->p->lexH);
2496
+
2497
+  if( c->cnp->tid == kVoidPtrDtId )
2498
+    rc = _cmDpStoreArrayEle(c,&val,sizeof(val));
2499
+  else
2500
+    rc = _cmDpStoreValue(c,cmDataAllocInt(NULL,val),"int");
2501
+
2502
+  return rc;
2503
+}
2504
+
2505
+cmDtRC_t _cmDataParserString( cmDataParserCtx_t* c )
2506
+{
2507
+  // if we are expecting a pair label
2508
+  if( cmIsFlag(c->flags,kIdExpFl) )
2509
+    return _cmDataParserOpenPair(c);
2510
+    
2511
+  // otherwise a 'value' must be expected
2512
+  if( cmIsNotFlag(c->flags,kValueExpFl) )
2513
+    return _cmDpSyntaxErr(c,"Unexpected string.");
2514
+
2515
+  cmData_t* np = cmDataConstStrAllocN(NULL,cmLexTokenText(c->p->lexH), cmLexTokenCharCount(c->p->lexH));
2516
+
2517
+  return _cmDpStoreValue(c,np,"string");
2518
+}
2519
+
2520
+cmDtRC_t _cmDataParserOpenRecd( cmDataParserCtx_t* c )
2521
+{
2522
+  // records are values - so we must be expecting a value
2523
+  if( cmIsFlag(c->flags,kValueExpFl) == false )
2524
+    return _cmDpSyntaxErr(c,"Unexpected '{'.");
2525
+
2526
+  // store the current node
2527
+  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2528
+    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2529
+
2530
+  // alloc a new record and make it the current node
2531
+  if( (c->cnp = cmDataRecdAlloc(c->cnp)) == NULL )
2532
+    return _cmDpSyntaxErr(c,"'recd' allocate failed.");
2533
+
2534
+  // new records must be followed by an id token.
2535
+  c->flags = kIdExpFl;
2536
+
2537
+  return kOkDtRC;
2538
+}
2539
+
2540
+cmDtRC_t _cmDataParserCloseRecd( cmDataParserCtx_t* c )
2541
+{
2542
+  cmDtRC_t rc;
2543
+
2544
+  // make the parent node the new curren node
2545
+  if((rc = _cmDpPopStack(c,&c->cnp)) != kOkDtRC )
2546
+    return rc;
2547
+
2548
+  switch( c->cnp->tid )
2549
+  {
2550
+    case kPairDtId:
2551
+      // if the parent node is a pair then close it
2552
+      rc = _cmDataParserClosePair(c);
2553
+      break;
2554
+
2555
+    case kListDtId:
2556
+      // parent node is a list - so expect another value
2557
+      c->flags = kValueExpFl;
2558
+      break;
2559
+
2560
+    default:
2561
+      return _cmDpSyntaxErr(c,"'records' may only be contained in other records or heterogenous arrays.");
2562
+      
2563
+  }
2564
+
2565
+  c->flags |= kCommaExpFl;
2566
+    
2567
+  return rc;
2568
+}
2569
+
2570
+cmDtRC_t _cmDataParserOpenList( cmDataParserCtx_t* c )
2571
+{
2572
+  // lists are values - so we must be expecting a value
2573
+  if( cmIsFlag(c->flags,kValueExpFl) == false )
2574
+    return _cmDpSyntaxErr(c,"Unexpected '('.");
2575
+
2576
+  // store the current node
2577
+  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2578
+    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2579
+
2580
+  // create a new list
2581
+  if( (c->cnp = cmDataListAlloc(c->cnp)) == NULL )
2582
+    return _cmDpSyntaxErr(c,"'list' allocate failed.");
2583
+
2584
+  // new lists must be followed by a value
2585
+  c->flags = kValueExpFl;
2586
+
2587
+  return kOkDtRC;
2588
+}
2589
+
2590
+cmDtRC_t _cmDataParserCloseList( cmDataParserCtx_t* c )
2591
+{
2592
+  cmDtRC_t rc;
2593
+
2594
+  // make the list's parent the current node
2595
+  if((rc = _cmDpPopStack(c,&c->cnp)) != kOkDtRC )
2596
+    return rc;
2597
+
2598
+  switch( c->cnp->tid )
2599
+  {
2600
+    case kPairDtId:
2601
+      // if the list's parent is a pair then close it
2602
+      rc = _cmDataParserClosePair(c);
2603
+      break;
2604
+
2605
+    case kListDtId:
2606
+      // the list's parent is another list so expect a value
2607
+      c->flags = kValueExpFl;
2608
+      break;
2609
+
2610
+    default:
2611
+      return _cmDpSyntaxErr(c,"'lists' may only be contained in other records or lists.");
2612
+      
2613
+  }
2614
+
2615
+  c->flags |= kCommaExpFl;
2616
+    
2617
+  return rc;
2618
+}
2619
+
2620
+cmDtRC_t _cmDataParserOpenArray( cmDataParserCtx_t* c )
2621
+{
2622
+
2623
+  // arrays are values - so we must be expecting a value
2624
+  if( cmIsFlag(c->flags,kValueExpFl) == false )
2625
+    return _cmDpSyntaxErr(c,"Unexpected '('.");
2626
+
2627
+  // store the current node
2628
+  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2629
+    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2630
+
2631
+  // create a new array
2632
+  if( (c->cnp = cmDataSetVoidAllocPtr(c->cnp, NULL, 0 )) == NULL )
2633
+    return _cmDpSyntaxErr(c,"'array' allocate failed.");
2634
+
2635
+  // new arrays must be followed by a value
2636
+  c->flags = kValueExpFl;
2637
+
2638
+  return kOkDtRC;
2639
+
2640
+}
2641
+
2642
+cmDtRC_t _cmDataParserCloseArray( cmDataParserCtx_t* c )
2643
+{
2644
+  cmDtRC_t rc;
2645
+  
2646
+  // make the arrays parent the current node
2647
+  if((rc = _cmDpPopStack(c,&c->cnp)) != kOkDtRC )
2648
+    return rc;
2649
+
2650
+  switch( c->cnp->tid )
2651
+  {
2652
+    
2653
+    case kPairDtId:
2654
+      // the arrays parent is a pair - so close it
2655
+      rc = _cmDataParserClosePair(c);
2656
+      break;
2657
+      
2658
+    case kListDtId:
2659
+      // the arrays parent is a list - so expect a value
2660
+      c->flags = kValueExpFl;
2661
+      break;
2662
+
2663
+    default:
2664
+      return _cmDpSyntaxErr(c,"'arrays' may only be contained in other records or lists.");
2665
+      
2666
+  }
2667
+
2668
+  c->flags |= kCommaExpFl;
2669
+    
2670
+  return rc;
2671
+}
2672
+
2673
+cmDtRC_t _cmDataParserOnColon( cmDataParserCtx_t* c )
2674
+{
2675
+  // colons only follow field identifiers and are always followed by values.
2676
+  if( cmIsFlag(c->flags,kColonExpFl) == false )
2677
+    return _cmDpSyntaxErr(c,"Unexpected colon.");
2678
+
2679
+  c->flags = kValueExpFl;
2680
+
2681
+  return kOkDtRC;
2682
+}
2683
+
2684
+cmDtRC_t _cmDataParserOnComma( cmDataParserCtx_t* c )
2685
+{
2686
+  // comma's may be found in three places:
2687
+  // 1) following field values
2688
+  // 2) between list values
2689
+  // 3) between  array values
2690
+  // comma's are always followed by values
2691
+  if( cmIsFlag(c->flags,kCommaExpFl) == false )
2692
+    return  _cmDpSyntaxErr(c, "Unexpected comma.");
2693
+
2694
+  c->flags = kValueExpFl;
2695
+
2696
+  return kOkDtRC;      
2697
+}
2698
+
2339 2699
 
2340 2700
 cmDtRC_t cmDataParserExec( cmDataParserH_t h, const cmChar_t* text, cmData_t** pp )
2341 2701
 {
2342 2702
   cmDtRC_t rc = kOkDtRC;
2343 2703
   unsigned tokenId;
2344 2704
 
2345
-  cmDataParser_t* p = _cmDataParserHandleToPtr(h);
2346
-  cmData_t*       d = cmRecdAlloc(NULL);
2347
-  
2705
+  cmDataParserCtx_t ctx;
2706
+  cmDataParser_t* p   = _cmDataParserHandleToPtr(h);
2707
+
2708
+  ctx.cnp   = NULL;  // current node ptr
2709
+  ctx.p     = p;
2710
+  ctx.flags = kValueExpFl;
2348 2711
 
2349 2712
   if( cmLexSetTextBuffer(p->lexH,text,strlen(text)) != kOkLexRC )
2350 2713
     return cmErrMsg(&p->err,kLexFailDtRC,"The data object lexer failed during reset.");
2351 2714
 
2715
+  cmStackClear(p->stH,false);
2716
+
2352 2717
   while((tokenId = cmLexGetNextToken(p->lexH)) != kEofLexTId )
2353 2718
   {
2354
-    case kRealLexTId:     // real number (contains a decimal point or is in scientific notation) 
2355
-      break;
2719
+    switch(tokenId)
2720
+    {
2721
+      case kRealLexTId:     // real number (contains a decimal point or is in scientific notation) 
2722
+        rc = _cmDataParserReal(&ctx);
2723
+        break;
2356 2724
 
2357
-    case kIntLexTId:      // decimal integer
2358
-      break;
2725
+      case kIntLexTId:      // decimal integer
2726
+        rc = _cmDataParserInt(&ctx);
2727
+        break;
2359 2728
 
2360
-    case kHexLexTId:      // hexidecimal integer
2361
-      break;
2729
+      case kHexLexTId:      // hexidecimal integer
2730
+        rc = _cmDataParserInt(&ctx);
2731
+        break;
2362 2732
 
2363
-    case kIdentLexTId:    // identifier
2364
-      break;
2733
+      case kIdentLexTId:    // identifiers are treated as strings
2734
+      case kQStrLexTId:     // quoted string
2735
+        rc = _cmDataParserString(&ctx);
2736
+        break;
2365 2737
 
2366
-    case kQStrLexTId:     // quoted string
2738
+      case kLCurlyLexTId:    // a new record is starting
2739
+        rc = _cmDataParserOpenRecd(&ctx);
2367 2740
       break;
2368 2741
 
2369
-    case kLCurlyLexTId
2370
-    case kRCurlyLexTId:
2371
-    case kLParenLexTId:
2372
-    case kRParenLexTId:
2373
-    case kLBrackLexTId:
2374
-    case kRBrackLexTId:
2375
-    case kColonLexTId:
2376
-    case kCommaLexTId:
2377
-
2378
-
2379
-    case kBlockCmtLexTId: // block comment
2380
-    case kLineCmtLexTId:  // line comment
2381
-    case kErrorLexTId:    // the lexer was unable to identify the current token
2382
-    case kUnknownLexTId:  // the token is of an unknown type (only used when kReturnUnknownLexFl is set)
2383
-    case kEofLexTId:      // the lexer reached the end of input
2384
-    case kSpaceLexTId:    // white space
2385
-      {
2386
-        rc = cmErrMsg(err,kLexFailDtRC,"The data object lexer failed with an unexpected token '%s' on line '%i'.",cmLexIdToLabel(lexH,tokenId),cmLexCurrentLineNumber(lexH));
2387
-        goto errLabel;
2388
-      }
2742
+      case kRCurlyLexTId:   // the current record is finished
2743
+        rc = _cmDataParserCloseRecd(&ctx);
2744
+        break;
2745
+
2746
+      case kLParenLexTId:   // a list is starting
2747
+        rc = _cmDataParserOpenList(&ctx);
2748
+        break;
2749
+
2750
+      case kRParenLexTId:   // a list is finished
2751
+        rc = _cmDataParserCloseList(&ctx);
2752
+        break;
2389 2753
 
2754
+      case kLBrackLexTId:   // an  array is starting
2755
+        rc = _cmDataParserOpenArray(&ctx);
2756
+        break;
2757
+
2758
+      case kRBrackLexTId:   // an array is ending
2759
+        rc = _cmDataParserCloseArray(&ctx);
2760
+        break;
2761
+
2762
+      case kColonLexTId:    // the previous id was a field id 
2763
+        rc = _cmDataParserOnColon(&ctx);
2764
+        break;
2765
+
2766
+      case kCommaLexTId:    // comma sep. for array or fields
2767
+        rc = _cmDataParserOnComma(&ctx);
2768
+        break;
2769
+
2770
+      case kBlockCmtLexTId: // block comment
2771
+      case kLineCmtLexTId:  // line comment
2772
+      case kErrorLexTId:    // the lexer was unable to identify the current token
2773
+      case kUnknownLexTId:  // the token is of an unknown type (only used when kReturnUnknownLexFl is set)
2774
+      case kEofLexTId:      // the lexer reached the end of input
2775
+      case kSpaceLexTId:    // white space
2776
+        {
2777
+          rc = cmErrMsg(&p->err,kLexFailDtRC,"The data object lexer failed with an unexpected token '%s' on line '%i'.",cmLexIdToLabel(p->lexH,tokenId),cmLexCurrentLineNumber(p->lexH));
2778
+          goto errLabel;
2779
+        }
2780
+    }
2390 2781
   }
2391 2782
 
2392 2783
  errLabel:
2393 2784
   return rc;
2394 2785
 }
2395 2786
 
2396
-#endif
2397 2787
 //============================================================================
2398 2788
 //============================================================================
2399 2789
 //============================================================================
@@ -2487,10 +2877,54 @@ void     _cmDataPrint( const cmData_t* p, cmRpt_t* rpt, unsigned indent )
2487 2877
 void cmDataPrint( const cmData_t* p, cmRpt_t* rpt )
2488 2878
 { _cmDataPrint(p,rpt,0); }
2489 2879
 
2880
+
2881
+cmDtRC_t cmDataParserTest( cmCtx_t* ctx )
2882
+{
2883
+  cmDtRC_t        rc = kOkDtRC;
2884
+  cmDataParserH_t h  = cmDataParserNullHandle;
2885
+  cmErr_t         err;
2886
+  cmData_t*       dp = NULL;
2887
+
2888
+  const cmChar_t text[] =
2889
+  {
2890
+    "{ f0:1.23 f1:\"hey\" "
2891
+  };
2892
+
2893
+  cmErrSetup(&err,&ctx->rpt,"Data Parser Tester");
2894
+
2895
+  if((rc = cmDataParserCreate(ctx, &h )) != kOkDtRC )
2896
+  {
2897
+    rc = cmErrMsg(&err,rc,"Data parser create failed.");
2898
+    goto errLabel;
2899
+  }
2900
+
2901
+  if( cmDataParserExec(h,text,&dp) != kOkDtRC )
2902
+    rc = cmErrMsg(&err,rc,"Data parser exec failed.");
2903
+  else
2904
+  {
2905
+    cmDataPrint(dp,&ctx->rpt);
2906
+  }
2907
+
2908
+ errLabel:
2909
+  if( cmDataParserDestroy( &h ) != kOkDtRC )
2910
+  {
2911
+    rc = cmErrMsg(&err,rc,"Data parser destroy failed.");
2912
+    goto errLabel;
2913
+  }
2914
+
2915
+  cmDataFree(dp);
2916
+
2917
+  return rc;
2918
+}
2919
+
2920
+
2490 2921
 void     cmDataTest( cmCtx_t* ctx )
2491 2922
 {
2492 2923
   float farr[] = { 1.23, 45.6, 7.89 };
2493 2924
 
2925
+  cmDataParserTest(ctx);
2926
+  return;
2927
+
2494 2928
   cmData_t* d0 = cmDataRecdAllocLabelA(NULL,
2495 2929
     "name",kConstStrDtId,"This is a string.",
2496 2930
     "id",  kUIntDtId,    21,

+ 11
- 6
cmData.h ファイルの表示

@@ -13,6 +13,7 @@ extern "C" {
13 13
     kMissingFieldDtRC,
14 14
     kLexFailDtRC,
15 15
     kParseStackFailDtRC,
16
+    kSyntaxErrDtRC,
16 17
     kEolDtRC
17 18
   };
18 19
 
@@ -66,8 +67,8 @@ extern "C" {
66 67
 
67 68
     kMinStructDtId,
68 69
     kListDtId = kMinStructDtId, // children nodes are array elements, cnt=child count
69
-    kPairDtId,                  // key/value pairs, cnt=2, first child is key, second is value
70
-    kRecordDtId,                // children nodes are pairs, cnt=pair count
70
+    kPairDtId,                   // key/value pairs, cnt=2, first child is key, second is value
71
+    kRecordDtId,                 // children nodes are pairs, cnt=pair count
71 72
     kMaxStructDtId,
72 73
 
73 74
     kOptArgDtFl = 0x80000000
@@ -273,7 +274,9 @@ extern "C" {
273 274
   // These functions begin by releasing any resources help by *p
274 275
   // and then dynamically allocate the internal array and copy 
275 276
   // the array data into it.
277
+  cmData_t* cmDataSetStrAllocN(      cmData_t* p, const cmChar_t* s, unsigned charCnt );
276 278
   cmData_t* cmDataSetStrAlloc(       cmData_t* p, const cmChar_t* s );
279
+  cmData_t* cmDataSetConstStrAllocN( cmData_t* p, const cmChar_t* s, unsigned charCnt );
277 280
   cmData_t* cmDataSetConstStrAlloc(  cmData_t* p, const cmChar_t* s );
278 281
   cmData_t* cmDataSetVoidAllocPtr(   cmData_t* p, const void* vp,           unsigned cnt );
279 282
   cmData_t* cmDataSetCharAllocPtr(   cmData_t* p, const char* vp,           unsigned cnt );
@@ -326,6 +329,7 @@ extern "C" {
326 329
   // and copy v[cnt] into it.
327 330
   cmData_t* cmDataStrAlloc(       cmData_t* parent, cmChar_t* str );
328 331
   cmData_t* cmDataConstStrAlloc(  cmData_t* parent, const cmChar_t* str );
332
+  cmData_t* cmDataConstStrAllocN( cmData_t* parent, const cmChar_t* str, unsigned charCnt );
329 333
   cmData_t* cmDataCharAllocPtr(   cmData_t* parent, const char* v,           unsigned cnt );
330 334
   cmData_t* cmDataUCharAllocPtr(  cmData_t* parent, const unsigned char* v,  unsigned cnt );
331 335
   cmData_t* cmDataShortAllocPtr(  cmData_t* parent, const short* v,          unsigned cnt );
@@ -430,6 +434,7 @@ extern "C" {
430 434
   cmData_t* cmDataAllocPairId(    cmData_t* parent, unsigned  keyId,       cmData_t* value );
431 435
 
432 436
   // Dynamically allocate the label but link (w/o realloc) the value.
437
+  cmData_t* cmDataAllocPairLabelN(cmData_t* parent, const cmChar_t* label, unsigned charCnt, cmData_t* value);
433 438
   cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t* label, cmData_t* value );
434 439
 
435 440
   //----------------------------------------------------------------------------
@@ -489,13 +494,13 @@ extern "C" {
489 494
   unsigned        cmDataRecdKeyId(    cmData_t* p, unsigned index );
490 495
   const cmChar_t* cmDataRecdKeyLabel( cmData_t* p, unsigned index );
491 496
   
492
-  cmData_t*       cmRecdMake( cmData_t* parent, cmData_t* p );
493
-  cmData_t*       cmRecdAlloc( cmData_t* parent );
497
+  cmData_t*       cmDataRecdMake( cmData_t* parent, cmData_t* p );
498
+  cmData_t*       cmDataRecdAlloc( cmData_t* parent );
494 499
   
495 500
   // Append a pair node by linking the pair node 'pair' to the record node 'p'.
496 501
   // 'pair' is simply linked to 'p' via cmDataAppendChild() no 
497 502
   // reallocation or duplicattion takes place.
498
-  cmData_t*       cmRecdAppendPair( cmData_t* p, cmData_t* pair );
503
+  cmData_t*       cmDataRecdAppendPair( cmData_t* p, cmData_t* pair );
499 504
 
500 505
 
501 506
   // Var-args format:
@@ -539,7 +544,7 @@ extern "C" {
539 544
   cmDtRC_t cmDataParserCreate( cmCtx_t* ctx, cmDataParserH_t* hp );
540 545
   cmDtRC_t cmDataParserDestroy( cmDataParserH_t* hp );
541 546
   bool     cmDataParserIsValid( cmDataParserH_t h );
542
-  cmDtRC_t cmDataParserExec(   cmDataParserH_t  h, cmChar_t* text, cmData_t** pp );
547
+  cmDtRC_t cmDataParserExec(   cmDataParserH_t  h, const cmChar_t* text, cmData_t** pp );
543 548
   //-----------------------------------------------------------------------------
544 549
   
545 550
   void     cmDataPrint( const cmData_t* p, cmRpt_t* rpt );

読み込み中…
キャンセル
保存