genericparser2.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. // Filename:- genericparser2.cpp
  2. // leave this at the top for PCH reasons...
  3. #include "common_headers.h"
  4. #ifdef _JK2EXE
  5. #include "../qcommon/qcommon.h"
  6. #else
  7. #include "g_headers.h"
  8. #endif
  9. //#define _EXE
  10. #define MAX_TOKEN_SIZE 1024
  11. static char token[MAX_TOKEN_SIZE];
  12. static char *GetToken(char **text, bool allowLineBreaks, bool readUntilEOL = false)
  13. {
  14. char *pointer = *text;
  15. int length = 0;
  16. int c = 0;
  17. bool foundLineBreak;
  18. token[0] = 0;
  19. if (!pointer)
  20. {
  21. return token;
  22. }
  23. while(1)
  24. {
  25. foundLineBreak = false;
  26. while(1)
  27. {
  28. c = *pointer;
  29. if (c > ' ')
  30. {
  31. break;
  32. }
  33. if (!c)
  34. {
  35. *text = 0;
  36. return token;
  37. }
  38. if (c == '\n')
  39. {
  40. foundLineBreak = true;
  41. }
  42. pointer++;
  43. }
  44. if (foundLineBreak && !allowLineBreaks)
  45. {
  46. *text = pointer;
  47. return token;
  48. }
  49. c = *pointer;
  50. // skip single line comment
  51. if (c == '/' && pointer[1] == '/')
  52. {
  53. pointer += 2;
  54. while (*pointer && *pointer != '\n')
  55. {
  56. pointer++;
  57. }
  58. }
  59. // skip multi line comments
  60. else if (c == '/' && pointer[1] == '*')
  61. {
  62. pointer += 2;
  63. while (*pointer && (*pointer != '*' || pointer[1] != '/'))
  64. {
  65. pointer++;
  66. }
  67. if (*pointer)
  68. {
  69. pointer += 2;
  70. }
  71. }
  72. else
  73. { // found the start of a token
  74. break;
  75. }
  76. }
  77. if (c == '\"')
  78. { // handle a string
  79. pointer++;
  80. while (1)
  81. {
  82. c = *pointer++;
  83. if (c == '\"')
  84. {
  85. // token[length++] = c;
  86. break;
  87. }
  88. else if (!c)
  89. {
  90. break;
  91. }
  92. else if (length < MAX_TOKEN_SIZE)
  93. {
  94. token[length++] = c;
  95. }
  96. }
  97. }
  98. else if (readUntilEOL)
  99. {
  100. // absorb all characters until EOL
  101. while(c != '\n' && c != '\r')
  102. {
  103. if (c == '/' && ((*(pointer+1)) == '/' || (*(pointer+1)) == '*'))
  104. {
  105. break;
  106. }
  107. if (length < MAX_TOKEN_SIZE)
  108. {
  109. token[length++] = c;
  110. }
  111. pointer++;
  112. c = *pointer;
  113. }
  114. // remove trailing white space
  115. while(length && token[length-1] < ' ')
  116. {
  117. length--;
  118. }
  119. }
  120. else
  121. {
  122. while(c > ' ')
  123. {
  124. if (length < MAX_TOKEN_SIZE)
  125. {
  126. token[length++] = c;
  127. }
  128. pointer++;
  129. c = *pointer;
  130. }
  131. }
  132. if (token[0] == '\"')
  133. { // remove start quote
  134. length--;
  135. memmove(token, token+1, length);
  136. if (length && token[length-1] == '\"')
  137. { // remove end quote
  138. length--;
  139. }
  140. }
  141. if (length >= MAX_TOKEN_SIZE)
  142. {
  143. length = 0;
  144. }
  145. token[length] = 0;
  146. *text = (char *)pointer;
  147. return token;
  148. }
  149. CTextPool::CTextPool(int initSize) :
  150. mNext(0),
  151. mSize(initSize),
  152. mUsed(0)
  153. {
  154. #ifdef _EXE
  155. // mPool = (char *)Z_Malloc(mSize, TAG_GP2);
  156. mPool = (char *)Z_Malloc(mSize, TAG_TEXTPOOL, qtrue);
  157. #else
  158. mPool = (char *)trap_Z_Malloc(mSize, TAG_GP2);
  159. #endif
  160. }
  161. CTextPool::~CTextPool(void)
  162. {
  163. #ifdef _EXE
  164. Z_Free(mPool);
  165. #else
  166. trap_Z_Free(mPool);
  167. #endif
  168. }
  169. char *CTextPool::AllocText(char *text, bool addNULL, CTextPool **poolPtr)
  170. {
  171. int length = strlen(text) + (addNULL ? 1 : 0);
  172. if (mUsed + length + 1> mSize)
  173. { // extra 1 to put a null on the end
  174. if (poolPtr)
  175. {
  176. (*poolPtr)->SetNext(new CTextPool(mSize));
  177. *poolPtr = (*poolPtr)->GetNext();
  178. return (*poolPtr)->AllocText(text, addNULL);
  179. }
  180. return 0;
  181. }
  182. strcpy(mPool + mUsed, text);
  183. mUsed += length;
  184. mPool[mUsed] = 0;
  185. return mPool + mUsed - length;
  186. }
  187. void CleanTextPool(CTextPool *pool)
  188. {
  189. CTextPool *next;
  190. while(pool)
  191. {
  192. next = pool->GetNext();
  193. delete pool;
  194. pool = next;
  195. }
  196. }
  197. CGPObject::CGPObject(const char *initName) :
  198. mName(initName),
  199. mNext(0),
  200. mInOrderNext(0),
  201. mInOrderPrevious(0)
  202. {
  203. }
  204. bool CGPObject::WriteText(CTextPool **textPool, const char *text)
  205. {
  206. if (strchr(text, ' ') || !text[0])
  207. {
  208. (*textPool)->AllocText("\"", false, textPool);
  209. (*textPool)->AllocText((char *)text, false, textPool);
  210. (*textPool)->AllocText("\"", false, textPool);
  211. }
  212. else
  213. {
  214. (*textPool)->AllocText((char *)text, false, textPool);
  215. }
  216. return true;
  217. }
  218. CGPValue::CGPValue(const char *initName, const char *initValue) :
  219. CGPObject(initName),
  220. mList(0)
  221. {
  222. if (initValue)
  223. {
  224. AddValue(initValue);
  225. }
  226. }
  227. CGPValue::~CGPValue(void)
  228. {
  229. CGPObject *next;
  230. while(mList)
  231. {
  232. next = mList->GetNext();
  233. delete mList;
  234. mList = next;
  235. }
  236. }
  237. CGPValue *CGPValue::Duplicate(CTextPool **textPool)
  238. {
  239. CGPValue *newValue;
  240. CGPObject *iterator;
  241. char *name;
  242. if (textPool)
  243. {
  244. name = (*textPool)->AllocText((char *)mName, true, textPool);
  245. }
  246. else
  247. {
  248. name = (char *)mName;
  249. }
  250. newValue = new CGPValue(name);
  251. iterator = mList;
  252. while(iterator)
  253. {
  254. if (textPool)
  255. {
  256. name = (*textPool)->AllocText((char *)iterator->GetName(), true, textPool);
  257. }
  258. else
  259. {
  260. name = (char *)iterator->GetName();
  261. }
  262. newValue->AddValue(name);
  263. iterator = iterator->GetNext();
  264. }
  265. return newValue;
  266. }
  267. bool CGPValue::IsList(void)
  268. {
  269. if (!mList || !mList->GetNext())
  270. {
  271. return false;
  272. }
  273. return true;
  274. }
  275. const char *CGPValue::GetTopValue(void)
  276. {
  277. if (mList)
  278. {
  279. return mList->GetName();
  280. }
  281. return 0;
  282. }
  283. void CGPValue::AddValue(const char *newValue, CTextPool **textPool)
  284. {
  285. if (textPool)
  286. {
  287. newValue = (*textPool)->AllocText((char *)newValue, true, textPool);
  288. }
  289. if (mList == 0)
  290. {
  291. mList = new CGPObject(newValue);
  292. mList->SetInOrderNext(mList);
  293. }
  294. else
  295. {
  296. mList->GetInOrderNext()->SetNext(new CGPObject(newValue));
  297. mList->SetInOrderNext(mList->GetInOrderNext()->GetNext());
  298. }
  299. }
  300. bool CGPValue::Parse(char **dataPtr, CTextPool **textPool)
  301. {
  302. char *token;
  303. char *value;
  304. while(1)
  305. {
  306. token = GetToken(dataPtr, true, true);
  307. if (!token[0])
  308. { // end of data - error!
  309. return false;
  310. }
  311. else if (strcmpi(token, "]") == 0)
  312. { // ending brace for this list
  313. break;
  314. }
  315. value = (*textPool)->AllocText(token, true, textPool);
  316. AddValue(value);
  317. }
  318. return true;
  319. }
  320. bool CGPValue::Write(CTextPool **textPool, int depth)
  321. {
  322. int i;
  323. CGPObject *next;
  324. if (!mList)
  325. {
  326. return true;
  327. }
  328. for(i=0;i<depth;i++)
  329. {
  330. (*textPool)->AllocText("\t", false, textPool);
  331. }
  332. WriteText(textPool, mName);
  333. if (!mList->GetNext())
  334. {
  335. (*textPool)->AllocText("\t\t", false, textPool);
  336. mList->WriteText(textPool, mList->GetName());
  337. (*textPool)->AllocText("\r\n", false, textPool);
  338. }
  339. else
  340. {
  341. (*textPool)->AllocText("\r\n", false, textPool);
  342. for(i=0;i<depth;i++)
  343. {
  344. (*textPool)->AllocText("\t", false, textPool);
  345. }
  346. (*textPool)->AllocText("[\r\n", false, textPool);
  347. next = mList;
  348. while(next)
  349. {
  350. for(i=0;i<depth+1;i++)
  351. {
  352. (*textPool)->AllocText("\t", false, textPool);
  353. }
  354. mList->WriteText(textPool, next->GetName());
  355. (*textPool)->AllocText("\r\n", false, textPool);
  356. next = next->GetNext();
  357. }
  358. for(i=0;i<depth;i++)
  359. {
  360. (*textPool)->AllocText("\t", false, textPool);
  361. }
  362. (*textPool)->AllocText("]\r\n", false, textPool);
  363. }
  364. return true;
  365. }
  366. CGPGroup::CGPGroup(const char *initName, CGPGroup *initParent) :
  367. CGPObject(initName),
  368. mPairs(0),
  369. mInOrderPairs(0),
  370. mCurrentPair(0),
  371. mSubGroups(0),
  372. mInOrderSubGroups(0),
  373. mCurrentSubGroup(0),
  374. mParent(initParent),
  375. mWriteable(false)
  376. {
  377. }
  378. CGPGroup::~CGPGroup(void)
  379. {
  380. Clean();
  381. }
  382. int CGPGroup::GetNumSubGroups(void)
  383. {
  384. int count;
  385. CGPGroup *group;
  386. count = 0;
  387. group = mSubGroups;
  388. while(group)
  389. {
  390. count++;
  391. group = (CGPGroup *)group->GetNext();
  392. }
  393. return(count);
  394. }
  395. int CGPGroup::GetNumPairs(void)
  396. {
  397. int count;
  398. CGPValue *pair;
  399. count = 0;
  400. pair = mPairs;
  401. while(pair)
  402. {
  403. count++;
  404. pair = (CGPValue *)pair->GetNext();
  405. }
  406. return(count);
  407. }
  408. void CGPGroup::Clean(void)
  409. {
  410. while(mPairs)
  411. {
  412. mCurrentPair = (CGPValue *)mPairs->GetNext();
  413. delete mPairs;
  414. mPairs = mCurrentPair;
  415. }
  416. while(mSubGroups)
  417. {
  418. mCurrentSubGroup = (CGPGroup *)mSubGroups->GetNext();
  419. delete mSubGroups;
  420. mSubGroups = mCurrentSubGroup;
  421. }
  422. mPairs = mInOrderPairs = mCurrentPair = 0;
  423. mSubGroups = mInOrderSubGroups = mCurrentSubGroup = 0;
  424. mParent = 0;
  425. mWriteable = false;
  426. }
  427. CGPGroup *CGPGroup::Duplicate(CTextPool **textPool, CGPGroup *initParent)
  428. {
  429. CGPGroup *newGroup, *subSub, *newSub;
  430. CGPValue *newPair, *subPair;
  431. char *name;
  432. if (textPool)
  433. {
  434. name = (*textPool)->AllocText((char *)mName, true, textPool);
  435. }
  436. else
  437. {
  438. name = (char *)mName;
  439. }
  440. newGroup = new CGPGroup(name);
  441. subSub = mSubGroups;
  442. while(subSub)
  443. {
  444. newSub = subSub->Duplicate(textPool, newGroup);
  445. newGroup->AddGroup(newSub);
  446. subSub = (CGPGroup *)subSub->GetNext();
  447. }
  448. subPair = mPairs;
  449. while(subPair)
  450. {
  451. newPair = subPair->Duplicate(textPool);
  452. newGroup->AddPair(newPair);
  453. subPair = (CGPValue *)subPair->GetNext();
  454. }
  455. return newGroup;
  456. }
  457. void CGPGroup::SortObject(CGPObject *object, CGPObject **unsortedList, CGPObject **sortedList,
  458. CGPObject **lastObject)
  459. {
  460. CGPObject *test, *last;
  461. if (!*unsortedList)
  462. {
  463. *unsortedList = *sortedList = object;
  464. }
  465. else
  466. {
  467. (*lastObject)->SetNext(object);
  468. test = *sortedList;
  469. last = 0;
  470. while(test)
  471. {
  472. if (strcmpi(object->GetName(), test->GetName()) < 0)
  473. {
  474. break;
  475. }
  476. last = test;
  477. test = test->GetInOrderNext();
  478. }
  479. if (test)
  480. {
  481. test->SetInOrderPrevious(object);
  482. object->SetInOrderNext(test);
  483. }
  484. if (last)
  485. {
  486. last->SetInOrderNext(object);
  487. object->SetInOrderPrevious(last);
  488. }
  489. else
  490. {
  491. *sortedList = object;
  492. }
  493. }
  494. *lastObject = object;
  495. }
  496. CGPValue *CGPGroup::AddPair(const char *name, const char *value, CTextPool **textPool)
  497. {
  498. CGPValue *newPair;
  499. if (textPool)
  500. {
  501. name = (*textPool)->AllocText((char *)name, true, textPool);
  502. if (value)
  503. {
  504. value = (*textPool)->AllocText((char *)value, true, textPool);
  505. }
  506. }
  507. newPair = new CGPValue(name, value);
  508. AddPair(newPair);
  509. return newPair;
  510. }
  511. void CGPGroup::AddPair(CGPValue *NewPair)
  512. {
  513. SortObject(NewPair, (CGPObject **)&mPairs, (CGPObject **)&mInOrderPairs,
  514. (CGPObject **)&mCurrentPair);
  515. }
  516. CGPGroup *CGPGroup::AddGroup(const char *name, CTextPool **textPool)
  517. {
  518. CGPGroup *newGroup;
  519. if (textPool)
  520. {
  521. name = (*textPool)->AllocText((char *)name, true, textPool);
  522. }
  523. newGroup = new CGPGroup(name);
  524. AddGroup(newGroup);
  525. return newGroup;
  526. }
  527. void CGPGroup::AddGroup(CGPGroup *NewGroup)
  528. {
  529. SortObject(NewGroup, (CGPObject **)&mSubGroups, (CGPObject **)&mInOrderSubGroups,
  530. (CGPObject **)&mCurrentSubGroup);
  531. }
  532. CGPGroup *CGPGroup::FindSubGroup(const char *name)
  533. {
  534. CGPGroup *group;
  535. group = mSubGroups;
  536. while(group)
  537. {
  538. if(!stricmp(name, group->GetName()))
  539. {
  540. return(group);
  541. }
  542. group = (CGPGroup *)group->GetNext();
  543. }
  544. return(NULL);
  545. }
  546. bool CGPGroup::Parse(char **dataPtr, CTextPool **textPool)
  547. {
  548. char *token;
  549. char lastToken[MAX_TOKEN_SIZE];
  550. CGPGroup *newSubGroup;
  551. CGPValue *newPair;
  552. while(1)
  553. {
  554. token = GetToken(dataPtr, true);
  555. if (!token[0])
  556. { // end of data - error!
  557. if (mParent)
  558. {
  559. return false;
  560. }
  561. else
  562. {
  563. break;
  564. }
  565. }
  566. else if (strcmpi(token, "}") == 0)
  567. { // ending brace for this group
  568. break;
  569. }
  570. strcpy(lastToken, token);
  571. // read ahead to see what we are doing
  572. token = GetToken(dataPtr, true, true);
  573. if (strcmpi(token, "{") == 0)
  574. { // new sub group
  575. newSubGroup = AddGroup(lastToken, textPool);
  576. newSubGroup->SetWriteable(mWriteable);
  577. if (!newSubGroup->Parse(dataPtr, textPool))
  578. {
  579. return false;
  580. }
  581. }
  582. else if (strcmpi(token, "[") == 0)
  583. { // new pair list
  584. newPair = AddPair(lastToken, 0, textPool);
  585. if (!newPair->Parse(dataPtr, textPool))
  586. {
  587. return false;
  588. }
  589. }
  590. else
  591. { // new pair
  592. AddPair(lastToken, token, textPool);
  593. }
  594. }
  595. return true;
  596. }
  597. bool CGPGroup::Write(CTextPool **textPool, int depth)
  598. {
  599. int i;
  600. CGPValue *mPair = mPairs;
  601. CGPGroup *mSubGroup = mSubGroups;
  602. if (depth >= 0)
  603. {
  604. for(i=0;i<depth;i++)
  605. {
  606. (*textPool)->AllocText("\t", false, textPool);
  607. }
  608. WriteText(textPool, mName);
  609. (*textPool)->AllocText("\r\n", false, textPool);
  610. for(i=0;i<depth;i++)
  611. {
  612. (*textPool)->AllocText("\t", false, textPool);
  613. }
  614. (*textPool)->AllocText("{\r\n", false, textPool);
  615. }
  616. while(mPair)
  617. {
  618. mPair->Write(textPool, depth+1);
  619. mPair = (CGPValue *)mPair->GetNext();
  620. }
  621. while(mSubGroup)
  622. {
  623. mSubGroup->Write(textPool, depth+1);
  624. mSubGroup = (CGPGroup *)mSubGroup->GetNext();
  625. }
  626. if (depth >= 0)
  627. {
  628. for(i=0;i<depth;i++)
  629. {
  630. (*textPool)->AllocText("\t", false, textPool);
  631. }
  632. (*textPool)->AllocText("}\r\n", false, textPool);
  633. }
  634. return true;
  635. }
  636. CGPValue *CGPGroup::FindPair(const char *key)
  637. {
  638. CGPValue *pair = mPairs;
  639. while(pair)
  640. {
  641. if (strcmpi(pair->GetName(), key) == 0)
  642. {
  643. return pair;
  644. }
  645. pair = pair->GetNext();
  646. }
  647. return 0;
  648. }
  649. const char *CGPGroup::FindPairValue(const char *key, const char *defaultVal)
  650. {
  651. CGPValue *pair = FindPair(key);
  652. if (pair)
  653. {
  654. return pair->GetTopValue();
  655. }
  656. return defaultVal;
  657. }
  658. CGenericParser2::CGenericParser2(void) :
  659. mTextPool(0),
  660. mWriteable(false)
  661. {
  662. }
  663. CGenericParser2::~CGenericParser2(void)
  664. {
  665. Clean();
  666. }
  667. bool CGenericParser2::Parse(char **dataPtr, bool cleanFirst, bool writeable)
  668. {
  669. CTextPool *topPool;
  670. #ifdef _XBOX
  671. // Parsers are temporary structures. They exist mainly at load time.
  672. extern void Z_SetNewDeleteTemporary(bool bTemp);
  673. Z_SetNewDeleteTemporary(true);
  674. #endif
  675. if (cleanFirst)
  676. {
  677. Clean();
  678. }
  679. if (!mTextPool)
  680. {
  681. mTextPool = new CTextPool;
  682. }
  683. SetWriteable(writeable);
  684. mTopLevel.SetWriteable(writeable);
  685. topPool = mTextPool;
  686. bool ret = mTopLevel.Parse(dataPtr, &topPool);
  687. #ifdef _XBOX
  688. Z_SetNewDeleteTemporary(false);
  689. #endif
  690. return ret;
  691. }
  692. void CGenericParser2::Clean(void)
  693. {
  694. mTopLevel.Clean();
  695. CleanTextPool(mTextPool);
  696. mTextPool = 0;
  697. }
  698. bool CGenericParser2::Write(CTextPool *textPool)
  699. {
  700. return mTopLevel.Write(&textPool, -1);
  701. }
  702. // The following groups of routines are used for a C interface into GP2.
  703. // C++ users should just use the objects as normally and not call these routines below
  704. //
  705. // CGenericParser2 (void *) routines
  706. TGenericParser2 GP_Parse(char **dataPtr, bool cleanFirst, bool writeable)
  707. {
  708. CGenericParser2 *parse;
  709. parse = new CGenericParser2;
  710. if (parse->Parse(dataPtr, cleanFirst, writeable))
  711. {
  712. return parse;
  713. }
  714. delete parse;
  715. return 0;
  716. }
  717. void GP_Clean(TGenericParser2 GP2)
  718. {
  719. if (!GP2)
  720. {
  721. return;
  722. }
  723. ((CGenericParser2 *)GP2)->Clean();
  724. }
  725. void GP_Delete(TGenericParser2 *GP2)
  726. {
  727. if (!GP2 || !(*GP2))
  728. {
  729. return;
  730. }
  731. delete ((CGenericParser2 *)(*GP2));
  732. (*GP2) = 0;
  733. }
  734. TGPGroup GP_GetBaseParseGroup(TGenericParser2 GP2)
  735. {
  736. if (!GP2)
  737. {
  738. return 0;
  739. }
  740. return ((CGenericParser2 *)GP2)->GetBaseParseGroup();
  741. }
  742. // CGPGroup (void *) routines
  743. const char *GPG_GetName(TGPGroup GPG)
  744. {
  745. if (!GPG)
  746. {
  747. return "";
  748. }
  749. return ((CGPGroup *)GPG)->GetName();
  750. }
  751. TGPGroup GPG_GetNext(TGPGroup GPG)
  752. {
  753. if (!GPG)
  754. {
  755. return 0;
  756. }
  757. return ((CGPGroup *)GPG)->GetNext();
  758. }
  759. TGPGroup GPG_GetInOrderNext(TGPGroup GPG)
  760. {
  761. if (!GPG)
  762. {
  763. return 0;
  764. }
  765. return ((CGPGroup *)GPG)->GetInOrderNext();
  766. }
  767. TGPGroup GPG_GetInOrderPrevious(TGPGroup GPG)
  768. {
  769. if (!GPG)
  770. {
  771. return 0;
  772. }
  773. return ((CGPGroup *)GPG)->GetInOrderPrevious();
  774. }
  775. TGPGroup GPG_GetPairs(TGPGroup GPG)
  776. {
  777. if (!GPG)
  778. {
  779. return 0;
  780. }
  781. return ((CGPGroup *)GPG)->GetPairs();
  782. }
  783. TGPGroup GPG_GetInOrderPairs(TGPGroup GPG)
  784. {
  785. if (!GPG)
  786. {
  787. return 0;
  788. }
  789. return ((CGPGroup *)GPG)->GetInOrderPairs();
  790. }
  791. TGPGroup GPG_GetSubGroups(TGPGroup GPG)
  792. {
  793. if (!GPG)
  794. {
  795. return 0;
  796. }
  797. return ((CGPGroup *)GPG)->GetSubGroups();
  798. }
  799. TGPGroup GPG_GetInOrderSubGroups(TGPGroup GPG)
  800. {
  801. if (!GPG)
  802. {
  803. return 0;
  804. }
  805. return ((CGPGroup *)GPG)->GetInOrderSubGroups();
  806. }
  807. TGPGroup GPG_FindSubGroup(TGPGroup GPG, const char *name)
  808. {
  809. if (!GPG)
  810. {
  811. return 0;
  812. }
  813. return ((CGPGroup *)GPG)->FindSubGroup(name);
  814. }
  815. TGPValue GPG_FindPair(TGPGroup GPG, const char *key)
  816. {
  817. if (!GPG)
  818. {
  819. return 0;
  820. }
  821. return ((CGPGroup *)GPG)->FindPair(key);
  822. }
  823. const char *GPG_FindPairValue(TGPGroup GPG, const char *key, const char *defaultVal)
  824. {
  825. if (!GPG)
  826. {
  827. return defaultVal;
  828. }
  829. return ((CGPGroup *)GPG)->FindPairValue(key, defaultVal);
  830. }
  831. // CGPValue (void *) routines
  832. const char *GPV_GetName(TGPValue GPV)
  833. {
  834. if (!GPV)
  835. {
  836. return "";
  837. }
  838. return ((CGPValue *)GPV)->GetName();
  839. }
  840. TGPValue GPV_GetNext(TGPValue GPV)
  841. {
  842. if (!GPV)
  843. {
  844. return 0;
  845. }
  846. return ((CGPValue *)GPV)->GetNext();
  847. }
  848. TGPValue GPV_GetInOrderNext(TGPValue GPV)
  849. {
  850. if (!GPV)
  851. {
  852. return 0;
  853. }
  854. return ((CGPValue *)GPV)->GetInOrderNext();
  855. }
  856. TGPValue GPV_GetInOrderPrevious(TGPValue GPV)
  857. {
  858. if (!GPV)
  859. {
  860. return 0;
  861. }
  862. return ((CGPValue *)GPV)->GetInOrderPrevious();
  863. }
  864. bool GPV_IsList(TGPValue GPV)
  865. {
  866. if (!GPV)
  867. {
  868. return 0;
  869. }
  870. return ((CGPValue *)GPV)->IsList();
  871. }
  872. const char *GPV_GetTopValue(TGPValue GPV)
  873. {
  874. if (!GPV)
  875. {
  876. return "";
  877. }
  878. return ((CGPValue *)GPV)->GetTopValue();
  879. }
  880. TGPValue GPV_GetList(TGPValue GPV)
  881. {
  882. if (!GPV)
  883. {
  884. return 0;
  885. }
  886. return ((CGPValue *)GPV)->GetList();
  887. }
  888. //////////////////// eof /////////////////////