|
@@ -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,
|