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