PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/EMBOSS-6.4.0/ajax/core/ajquery.c

#
C | 2861 lines | 1527 code | 678 blank | 656 comment | 204 complexity | e7dae42574d9828e35220b8f8d28432b MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, LGPL-2.0, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. ** This is free software; you can redistribute it and/or
  3. ** modify it under the terms of the GNU Library General Public License
  4. ** as published by the Free Software Foundation; either version 2
  5. ** of the License, or (at your option) any later version.
  6. **
  7. ** This program is distributed in the hope that it will be useful,
  8. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ** GNU General Public License for more details.
  11. **
  12. ** You should have received a copy of the GNU Library General Public License
  13. ** along with this program; if not, write to the Free Software
  14. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. ******************************************************************************/
  16. #include "ajax.h"
  17. static AjBool queryRegInitDone = AJFALSE;
  18. static AjPStr queryFormat = NULL;
  19. static AjPStr queryList = NULL;
  20. static AjPStr querySvr = NULL;
  21. static AjPStr queryDb = NULL;
  22. static AjPStr queryChr = NULL;
  23. static AjPStr queryTest = NULL;
  24. static AjPRegexp queryRegAsis = NULL;
  25. static AjPRegexp queryRegSvr = NULL;
  26. static AjPRegexp queryRegDbId = NULL;
  27. static AjPRegexp queryRegDbField = NULL;
  28. static AjPRegexp queryRegFmt = NULL;
  29. static AjPRegexp queryRegFieldId = NULL;
  30. static AjPRegexp queryRegId = NULL;
  31. static AjPRegexp queryRegList = NULL;
  32. static AjPRegexp queryRegRange = NULL;
  33. static AjPRegexp queryRegWild = NULL;
  34. static void queryWildComp(void);
  35. static void queryRegInit(void);
  36. static const AjPStr queryGetFieldC(const AjPQuery query,
  37. const char* txt);
  38. static const char* queryDatatypeName[] =
  39. {
  40. "unknown", "sequence", "features", "assembly",
  41. "obo", "resource", "taxon",
  42. "text", NULL
  43. };
  44. /* @filesection ajquery *******************************************************
  45. **
  46. ** @nam1rule aj Function belongs to the AJAX library.
  47. **
  48. ******************************************************************************/
  49. /* @datasection [AjPQuery] Query object ***************************************
  50. **
  51. ** Function is for manipulating query objects
  52. **
  53. ** @nam2rule Query
  54. **
  55. ******************************************************************************/
  56. /* @section Query Constructors ************************************************
  57. **
  58. ** All constructors return a new query object by pointer. It
  59. ** is the responsibility of the user to first destroy any previous
  60. ** query object. The target pointer does not need to be
  61. ** initialised to NULL, but it is good programming practice to do so
  62. ** anyway.
  63. **
  64. ** @fdata [AjPQuery]
  65. **
  66. ** @nam3rule New Constructor
  67. ** @argrule New datatype [const AjEDataType] Enumerated datatype
  68. **
  69. ** @valrule * [AjPQuery]
  70. **
  71. ** @fcategory new
  72. **
  73. ******************************************************************************/
  74. /* @func ajQueryNew ********************************************************
  75. **
  76. ** Creates a new query object for a specific datatype from the
  77. ** AJDATATYPE enumerated types
  78. **
  79. ** @param [r] datatype [const AjEDataType] Enumerated datatype
  80. ** @return [AjPQuery] New query object.
  81. ** @@
  82. ******************************************************************************/
  83. AjPQuery ajQueryNew(const AjEDataType datatype)
  84. {
  85. AjPQuery pthis;
  86. AJNEW0(pthis);
  87. pthis->SvrName = ajStrNew();
  88. pthis->DbName = ajStrNew();
  89. pthis->DbAlias= ajStrNew();
  90. pthis->QueryFields = ajListNew();
  91. pthis->ResultsList = ajListNew();
  92. pthis->ResultsTable = ajTablestrNewConst(100);
  93. pthis->DbIdentifier = ajStrNew();
  94. pthis->DbAccession = ajStrNew();
  95. pthis->Wild = ajFalse;
  96. pthis->Method = ajStrNew();
  97. pthis->Formatstr = ajStrNew();
  98. pthis->IndexDir = ajStrNew();
  99. pthis->Directory = ajStrNew();
  100. pthis->Filename = ajStrNew();
  101. pthis->Application = ajStrNew();
  102. pthis->Field = ajStrNew();
  103. pthis->DbFilter = ajStrNew();
  104. pthis->DbReturn = ajStrNew();
  105. pthis->QueryType = AJQUERY_UNKNOWN;
  106. pthis->Access = NULL;
  107. pthis->DataType = datatype;
  108. pthis->QryData = NULL;
  109. pthis->Fpos = NULLFPOS;
  110. pthis->QryDone = ajFalse;
  111. pthis->HasAcc = ajTrue;
  112. return pthis;
  113. }
  114. /* @section Query Destructors *************************************************
  115. **
  116. ** Destruction destroys all internal data structures and frees the
  117. ** memory allocated for the query object.
  118. **
  119. ** @fdata [AjPQuery]
  120. **
  121. ** @nam3rule Del destructor
  122. **
  123. ** @argrule Del pthis [AjPQuery*] Query
  124. **
  125. ** @valrule * [void]
  126. **
  127. ** @fcategory delete
  128. **
  129. ******************************************************************************/
  130. /* @func ajQueryDel ***********************************************************
  131. **
  132. ** Deletes a query object
  133. **
  134. ** @param [d] pthis [AjPQuery*] Address of query object
  135. ** @return [void]
  136. ** @@
  137. ******************************************************************************/
  138. void ajQueryDel(AjPQuery* pthis)
  139. {
  140. AjPQuery thys;
  141. AjPQueryField field = NULL;
  142. AjPTextAccess textaccess;
  143. if(!pthis)
  144. return;
  145. if(!*pthis)
  146. return;
  147. ajDebug("ajQueryDel db:'%S' svr: '%S' fields:%u\n",
  148. (*pthis)->DbName, (*pthis)->SvrName,
  149. ajListGetLength((*pthis)->QueryFields));
  150. thys = *pthis;
  151. ajStrDel(&thys->SvrName);
  152. ajStrDel(&thys->DbName);
  153. ajStrDel(&thys->DbAlias);
  154. ajStrDel(&thys->DbType);
  155. ajStrDel(&thys->DbIdentifier);
  156. ajStrDel(&thys->DbAccession);
  157. ajStrDel(&thys->DbFilter);
  158. ajStrDel(&thys->DbReturn);
  159. while(ajListPop(thys->QueryFields, (void **) &field))
  160. ajQueryfieldDel(&field);
  161. ajListFree(&thys->QueryFields);
  162. ajListFreeData(&thys->ResultsList);
  163. ajTableFree(&thys->ResultsTable);
  164. ajStrDel(&thys->Method);
  165. ajStrDel(&thys->Qlinks);
  166. ajStrDel(&thys->Formatstr);
  167. ajStrDel(&thys->IndexDir);
  168. ajStrDel(&thys->Directory);
  169. ajStrDel(&thys->Filename);
  170. ajStrDel(&thys->Exclude);
  171. ajStrDel(&thys->DbFields);
  172. ajStrDel(&thys->DbUrl);
  173. ajStrDel(&thys->DbProxy);
  174. ajStrDel(&thys->DbHttpVer);
  175. ajStrDel(&thys->ServerVer);
  176. ajStrDel(&thys->Field);
  177. ajStrDel(&thys->QryString);
  178. ajStrDel(&thys->Application);
  179. if(thys->QryData)
  180. {
  181. textaccess = thys->TextAccess;
  182. if(textaccess)
  183. {
  184. if(textaccess->AccessFree)
  185. textaccess->AccessFree(thys);
  186. }
  187. AJFREE(thys->QryData);
  188. }
  189. AJFREE(*pthis);
  190. return;
  191. }
  192. /* @section Query Casts ***************************************************
  193. **
  194. ** These functions examine the contents of a query object
  195. ** and return some derived information. Some of them provide access to
  196. ** the internal components of a query object. They are
  197. ** provided for programming convenience but should be used with
  198. ** caution.
  199. **
  200. ** @fdata [AjPQuery]
  201. **
  202. ** @nam3rule Get Return a value
  203. ** @nam4rule Datatype Return name of datatype
  204. ** @nam4rule Id Return id query term
  205. ** @nam4rule Format Return format name
  206. ** @nam4rule Query Return a report of the query string
  207. ** @nam3rule Getall Return all values
  208. ** @nam4rule Fields Return a set of standard query fields
  209. **
  210. ** @argrule * query [const AjPQuery] Query object
  211. ** @argrule GetQuery Pdest [AjPStr*] Returned query string
  212. **
  213. **
  214. ** @valrule * [AjBool] True on success
  215. ** @valrule *Fields [const AjPList] List of field objects found
  216. ** @valrule *Format [const AjPStr] Format name
  217. ** @valrule *Id [const AjPStr] Wildcard ID
  218. ** @valrule *Datatype [const char*] Datatype standard name
  219. **
  220. ** @fcategory cast
  221. **
  222. ******************************************************************************/
  223. /* @func ajQueryGetDatatype ***************************************************
  224. **
  225. ** Returns the query datatype from a query
  226. **
  227. ** @param [r] query [const AjPQuery] Query
  228. ** @return [const char*] Standard name for query datatype
  229. ******************************************************************************/
  230. const char* ajQueryGetDatatype(const AjPQuery query)
  231. {
  232. if(query->DataType > AJDATATYPE_MAX)
  233. return "invalid";
  234. return queryDatatypeName[query->DataType];
  235. }
  236. /* @func ajQueryGetFormat *****************************************************
  237. **
  238. ** Returns the format name from a query
  239. **
  240. ** @param [r] query [const AjPQuery] Query
  241. ** @return [const AjPStr] Format name
  242. ******************************************************************************/
  243. const AjPStr ajQueryGetFormat(const AjPQuery query)
  244. {
  245. return query->Formatstr;
  246. }
  247. /* @func ajQueryGetId *********************************************************
  248. **
  249. ** Returns the ID query string from a query
  250. **
  251. ** @param [r] query [const AjPQuery] Query
  252. ** @return [const AjPStr] Wildcard ID query string
  253. ******************************************************************************/
  254. const AjPStr ajQueryGetId(const AjPQuery query)
  255. {
  256. return queryGetFieldC(query, "id");
  257. }
  258. /* @func ajQueryGetQuery *******************************************************
  259. **
  260. ** Returns a report of the query string from a query
  261. **
  262. ** @param [r] query [const AjPQuery] Query
  263. ** @param [w] Pdest [AjPStr*] Query string
  264. ** @return [AjBool] True on success
  265. ******************************************************************************/
  266. AjBool ajQueryGetQuery(const AjPQuery query, AjPStr *Pdest)
  267. {
  268. AjIList iter = NULL;
  269. AjPQueryField field = NULL;
  270. const char* queryLinkNames[] = {"", "OR", "AND", "EOR", "NOT", "ELSE"};
  271. if(!Pdest)
  272. return ajFalse;
  273. ajStrAssignClear(Pdest);
  274. iter = ajListIterNewread(query->QueryFields);
  275. while(!ajListIterDone(iter))
  276. {
  277. field = ajListIterGet(iter);
  278. if(field->Link != AJQLINK_INIT)
  279. ajFmtPrintAppS(Pdest, " %s ", queryLinkNames[field->Link]);
  280. ajFmtPrintAppS(Pdest, "%S:%S", field->Field, field->Wildquery);
  281. }
  282. ajListIterDel(&iter);
  283. return ajTrue;
  284. }
  285. /* @func ajQueryGetallFields **************************************************
  286. **
  287. ** Returns the standard sequence query string from a query
  288. **
  289. ** @param [r] query [const AjPQuery] Query
  290. ** @return [const AjPList] List of field objects
  291. ******************************************************************************/
  292. const AjPList ajQueryGetallFields(const AjPQuery query)
  293. {
  294. return query->QueryFields;
  295. }
  296. /* @funcstatic queryGetFieldC *************************************************
  297. **
  298. ** Returns the query string from a query for a named field
  299. **
  300. ** @param [r] query [const AjPQuery] Query
  301. ** @param [r] txt [const char*] Field name
  302. ** @return [const AjPStr] Wildcard ID query string
  303. ******************************************************************************/
  304. static const AjPStr queryGetFieldC(const AjPQuery query,
  305. const char* txt)
  306. {
  307. AjPStr ret = NULL;
  308. AjIList iter = NULL;
  309. AjPQueryField field = NULL;
  310. iter = ajListIterNewread(query->QueryFields);
  311. while(!ajListIterDone(iter))
  312. {
  313. field = ajListIterGet(iter);
  314. if(ajStrMatchC(field->Field, txt))
  315. {
  316. ret = field->Wildquery;
  317. break;
  318. }
  319. }
  320. ajListIterDel(&iter);
  321. return ret;
  322. }
  323. /* @section Query Casts *******************************************************
  324. **
  325. ** These functions use the contents of a query object but do
  326. ** not make any changes.
  327. **
  328. ** @fdata [AjPQuery]
  329. **
  330. ** @nam3rule Is Test for a property
  331. ** @nam3rule Known Test a property matches known options
  332. ** @nam4rule Set Query has some query field(s) defined
  333. ** @nam4rule KnownField Test field name is defined for the data source
  334. ** @suffix C Character string input
  335. ** @suffix S String input
  336. **
  337. ** @argrule * thys [const AjPQuery] query
  338. ** @argrule C fieldtxt [const char*] Field name
  339. ** @argrule S field [const AjPStr] Field name
  340. **
  341. ** @valrule * [AjBool] True if property exists
  342. **
  343. ** @fcategory cast
  344. **
  345. ******************************************************************************/
  346. /* @func ajQueryIsSet *********************************************************
  347. **
  348. ** Tests whether any element of a query has been set.
  349. **
  350. ** @param [r] thys [const AjPQuery] Query object.
  351. ** @return [AjBool] ajTrue if query should be made. ajFalse if the query
  352. ** includes all entries.
  353. ** @@
  354. ******************************************************************************/
  355. AjBool ajQueryIsSet(const AjPQuery thys)
  356. {
  357. ajDebug("ajQueryIsSet list:%u\n", ajListGetLength(thys->QueryFields));
  358. if(ajListGetLength(thys->QueryFields))
  359. return ajTrue;
  360. return ajFalse;
  361. }
  362. /* @func ajQueryKnownFieldC ***************************************************
  363. **
  364. ** Checks whether a query field is defined for a database as a "fields:"
  365. ** string in the database definition.
  366. **
  367. ** @param [r] thys [const AjPQuery] Query object
  368. ** @param [r] fieldtxt [const char*] field name
  369. ** @return [AjBool] ajTrue if the field is defined
  370. ******************************************************************************/
  371. AjBool ajQueryKnownFieldC(const AjPQuery thys, const char* fieldtxt)
  372. {
  373. AjPStrTok handle = NULL;
  374. AjPStr token = NULL;
  375. ajDebug("ajQueryKnownFieldC qry '%s' fields '%S'\n",
  376. fieldtxt, thys->DbFields);
  377. ajStrTokenAssignC(&handle, thys->DbFields, "\t ,;\n\r");
  378. while(ajStrTokenNextParse(&handle, &token))
  379. {
  380. if(ajStrMatchCaseC(token, fieldtxt))
  381. {
  382. ajDebug("ajQueryKnownFieldC match '%S'\n", token);
  383. ajStrTokenDel(&handle);
  384. ajStrDel(&token);
  385. return ajTrue;
  386. }
  387. }
  388. ajStrTokenDel(&handle);
  389. ajStrDel(&token);
  390. if(ajCharMatchCaseC(fieldtxt, "id"))
  391. return ajTrue;
  392. if(thys->HasAcc && ajCharMatchCaseC(fieldtxt, "acc"))
  393. return ajTrue;
  394. return ajFalse;
  395. }
  396. /* @func ajQueryKnownFieldS ***************************************************
  397. **
  398. ** Checks whether a query field is defined for a database as a "fields:"
  399. ** string in the database definition.
  400. **
  401. ** @param [r] thys [const AjPQuery] Query object
  402. ** @param [r] field [const AjPStr] field name
  403. ** @return [AjBool] ajTrue if the field is defined
  404. ******************************************************************************/
  405. AjBool ajQueryKnownFieldS(const AjPQuery thys, const AjPStr field)
  406. {
  407. return ajQueryKnownFieldC(thys, ajStrGetPtr(field));
  408. }
  409. /* @section Modifiers *********************************************************
  410. **
  411. ** Modify values in a query object
  412. **
  413. ** @fdata [AjPQuery]
  414. **
  415. ** @nam3rule Add Add content
  416. ** @nam4rule AddField Add a query field
  417. ** @nam5rule And Add an AND query field
  418. ** @nam5rule Else Add an ELSE query field
  419. ** @nam5rule Eor Add an EOR query field
  420. ** @nam5rule Not Add a NOT query field
  421. ** @nam5rule Or Add an OR query field
  422. ** @nam3rule Set Set internals
  423. ** @nam4rule Wild Set wildcard property
  424. ** @nam3rule Clear Reset for reuse
  425. ** @nam3rule Starclear Reset all fields that are just '*' for 'match all'
  426. ** @suffix C Character string data
  427. ** @suffix S String data
  428. **
  429. ** @argrule * thys [AjPQuery] Query object
  430. ** @argrule C fieldtxt [const char*] Field name
  431. ** @argrule C wildquerytxt [const char*] Query string
  432. ** @argrule S field [const AjPStr] Field name
  433. ** @argrule S wildquery [const AjPStr] Query string
  434. **
  435. ** @valrule * [void]
  436. ** @valrule *AddField [AjBool] True on success
  437. ** @valrule *Wild [AjBool] True if query had wildcard(s)
  438. **
  439. ** @fcategory modify
  440. **
  441. ******************************************************************************/
  442. /* @func ajQueryAddFieldAndC **************************************************
  443. **
  444. ** Adds a query with an 'AND' operator
  445. **
  446. ** @param [u] thys [AjPQuery] Query object
  447. ** @param [r] fieldtxt [const char*] field name
  448. ** @param [r] wildquerytxt [const char*] wildcard query string
  449. ** @return [AjBool] ajTrue on success
  450. ******************************************************************************/
  451. AjBool ajQueryAddFieldAndC(AjPQuery thys, const char* fieldtxt,
  452. const char* wildquerytxt)
  453. {
  454. AjPQueryField qryfield;
  455. qryfield = ajQueryfieldNewC(fieldtxt, wildquerytxt, AJQLINK_AND);
  456. if(!thys->QueryFields)
  457. thys->QueryFields = ajListNew();
  458. ajListPushAppend(thys->QueryFields, qryfield);
  459. qryfield = NULL;
  460. return ajTrue;
  461. }
  462. /* @func ajQueryAddFieldAndS **************************************************
  463. **
  464. ** Adds a query with an 'AND' operator
  465. **
  466. ** @param [u] thys [AjPQuery] Query object
  467. ** @param [r] field [const AjPStr] field name
  468. ** @param [r] wildquery [const AjPStr] wildcard query string
  469. ** @return [AjBool] ajTrue on success
  470. ******************************************************************************/
  471. AjBool ajQueryAddFieldAndS(AjPQuery thys, const AjPStr field,
  472. const AjPStr wildquery)
  473. {
  474. AjPQueryField qryfield;
  475. qryfield = ajQueryfieldNewS(field, wildquery, AJQLINK_AND);
  476. if(!thys->QueryFields)
  477. thys->QueryFields = ajListNew();
  478. ajListPushAppend(thys->QueryFields, qryfield);
  479. qryfield = NULL;
  480. return ajTrue;
  481. }
  482. /* @func ajQueryAddFieldElseC *************************************************
  483. **
  484. ** Adds a query with an 'ELSE' operator
  485. **
  486. ** @param [u] thys [AjPQuery] Query object
  487. ** @param [r] fieldtxt [const char*] field name
  488. ** @param [r] wildquerytxt [const char*] wildcard query string
  489. ** @return [AjBool] ajTrue on success
  490. ******************************************************************************/
  491. AjBool ajQueryAddFieldElseC(AjPQuery thys, const char* fieldtxt,
  492. const char* wildquerytxt)
  493. {
  494. AjPQueryField qryfield;
  495. qryfield = ajQueryfieldNewC(fieldtxt, wildquerytxt, AJQLINK_ELSE);
  496. if(!thys->QueryFields)
  497. thys->QueryFields = ajListNew();
  498. ajListPushAppend(thys->QueryFields, qryfield);
  499. qryfield = NULL;
  500. return ajTrue;
  501. }
  502. /* @func ajQueryAddFieldElseS *************************************************
  503. **
  504. ** Adds a query with an 'ELSE' operator
  505. **
  506. ** @param [u] thys [AjPQuery] Query object
  507. ** @param [r] field [const AjPStr] field name
  508. ** @param [r] wildquery [const AjPStr] wildcard query string
  509. ** @return [AjBool] ajTrue on success
  510. ******************************************************************************/
  511. AjBool ajQueryAddFieldElseS(AjPQuery thys, const AjPStr field,
  512. const AjPStr wildquery)
  513. {
  514. AjPQueryField qryfield;
  515. qryfield = ajQueryfieldNewS(field, wildquery, AJQLINK_ELSE);
  516. if(!thys->QueryFields)
  517. thys->QueryFields = ajListNew();
  518. ajListPushAppend(thys->QueryFields, qryfield);
  519. qryfield = NULL;
  520. return ajTrue;
  521. }
  522. /* @func ajQueryAddFieldEorC **************************************************
  523. **
  524. ** Adds a query with an 'EOR' operator
  525. **
  526. ** @param [u] thys [AjPQuery] Query object
  527. ** @param [r] fieldtxt [const char*] field name
  528. ** @param [r] wildquerytxt [const char*] wildcard query string
  529. ** @return [AjBool] ajTrue on success
  530. ******************************************************************************/
  531. AjBool ajQueryAddFieldEorC(AjPQuery thys, const char* fieldtxt,
  532. const char* wildquerytxt)
  533. {
  534. AjPQueryField qryfield;
  535. qryfield = ajQueryfieldNewC(fieldtxt, wildquerytxt, AJQLINK_EOR);
  536. if(!thys->QueryFields)
  537. thys->QueryFields = ajListNew();
  538. ajListPushAppend(thys->QueryFields, qryfield);
  539. qryfield = NULL;
  540. return ajTrue;
  541. }
  542. /* @func ajQueryAddFieldEorS **************************************************
  543. **
  544. ** Adds a query with an 'EOR' operator
  545. **
  546. ** @param [u] thys [AjPQuery] Query object
  547. ** @param [r] field [const AjPStr] field name
  548. ** @param [r] wildquery [const AjPStr] wildcard query string
  549. ** @return [AjBool] ajTrue on success
  550. ******************************************************************************/
  551. AjBool ajQueryAddFieldEorS(AjPQuery thys, const AjPStr field,
  552. const AjPStr wildquery)
  553. {
  554. AjPQueryField qryfield;
  555. qryfield = ajQueryfieldNewS(field, wildquery, AJQLINK_EOR);
  556. if(!thys->QueryFields)
  557. thys->QueryFields = ajListNew();
  558. ajListPushAppend(thys->QueryFields, qryfield);
  559. qryfield = NULL;
  560. return ajTrue;
  561. }
  562. /* @func ajQueryAddFieldNotC **************************************************
  563. **
  564. ** Adds a query with a 'NOT' operator
  565. **
  566. ** @param [u] thys [AjPQuery] Query object
  567. ** @param [r] fieldtxt [const char*] field name
  568. ** @param [r] wildquerytxt [const char*] wildcard query string
  569. ** @return [AjBool] ajTrue on success
  570. ******************************************************************************/
  571. AjBool ajQueryAddFieldNotC(AjPQuery thys, const char* fieldtxt,
  572. const char* wildquerytxt)
  573. {
  574. AjPQueryField qryfield;
  575. qryfield = ajQueryfieldNewC(fieldtxt, wildquerytxt, AJQLINK_NOT);
  576. if(!thys->QueryFields)
  577. thys->QueryFields = ajListNew();
  578. ajListPushAppend(thys->QueryFields, qryfield);
  579. qryfield = NULL;
  580. return ajTrue;
  581. }
  582. /* @func ajQueryAddFieldNotS **************************************************
  583. **
  584. ** Adds a query with a 'NOT' operator
  585. **
  586. ** @param [u] thys [AjPQuery] Query object
  587. ** @param [r] field [const AjPStr] field name
  588. ** @param [r] wildquery [const AjPStr] wildcard query string
  589. ** @return [AjBool] ajTrue on success
  590. ******************************************************************************/
  591. AjBool ajQueryAddFieldNotS(AjPQuery thys, const AjPStr field,
  592. const AjPStr wildquery)
  593. {
  594. AjPQueryField qryfield;
  595. qryfield = ajQueryfieldNewS(field, wildquery, AJQLINK_NOT);
  596. if(!thys->QueryFields)
  597. thys->QueryFields = ajListNew();
  598. ajListPushAppend(thys->QueryFields, qryfield);
  599. qryfield = NULL;
  600. return ajTrue;
  601. }
  602. /* @func ajQueryAddFieldOrC ***************************************************
  603. **
  604. ** Adds a query with an 'OR' operator
  605. **
  606. ** @param [u] thys [AjPQuery] Query object
  607. ** @param [r] fieldtxt [const char*] field name
  608. ** @param [r] wildquerytxt [const char*] wildcard query string
  609. ** @return [AjBool] ajTrue on success
  610. ******************************************************************************/
  611. AjBool ajQueryAddFieldOrC(AjPQuery thys, const char* fieldtxt,
  612. const char* wildquerytxt)
  613. {
  614. AjPQueryField qryfield;
  615. if(!thys->QueryFields)
  616. thys->QueryFields = ajListNew();
  617. if(!ajListGetLength(thys->QueryFields))
  618. qryfield = ajQueryfieldNewC(fieldtxt, wildquerytxt, AJQLINK_INIT);
  619. else
  620. qryfield = ajQueryfieldNewC(fieldtxt, wildquerytxt, AJQLINK_OR);
  621. ajListPushAppend(thys->QueryFields, qryfield);
  622. qryfield = NULL;
  623. return ajTrue;
  624. }
  625. /* @func ajQueryAddFieldOrS ***************************************************
  626. **
  627. ** Adds a query with an 'OR' operator
  628. **
  629. ** @param [u] thys [AjPQuery] Query object
  630. ** @param [r] field [const AjPStr] field name
  631. ** @param [r] wildquery [const AjPStr] wildcard query string
  632. ** @return [AjBool] ajTrue on success
  633. ******************************************************************************/
  634. AjBool ajQueryAddFieldOrS(AjPQuery thys, const AjPStr field,
  635. const AjPStr wildquery)
  636. {
  637. AjPQueryField qryfield;
  638. if(!thys->QueryFields)
  639. thys->QueryFields = ajListNew();
  640. if(!ajListGetLength(thys->QueryFields))
  641. qryfield = ajQueryfieldNewS(field, wildquery, AJQLINK_INIT);
  642. else
  643. qryfield = ajQueryfieldNewS(field, wildquery, AJQLINK_OR);
  644. ajListPushAppend(thys->QueryFields, qryfield);
  645. qryfield = NULL;
  646. return ajTrue;
  647. }
  648. /* @func ajQueryClear *********************************************************
  649. **
  650. ** Resets a query object to a clean state for reuse.
  651. ** Keep the begin, end and reverse values.
  652. **
  653. ** @param [u] thys [AjPQuery] query object
  654. ** @return [void]
  655. ** @@
  656. ******************************************************************************/
  657. void ajQueryClear(AjPQuery thys)
  658. {
  659. AjPQueryField field = NULL;
  660. void *result;
  661. ajStrSetClear(&thys->SvrName);
  662. ajStrSetClear(&thys->DbName);
  663. ajStrSetClear(&thys->DbAlias);
  664. ajStrSetClear(&thys->DbType);
  665. while(ajListPop(thys->QueryFields, (void **) &field))
  666. ajQueryfieldDel(&field);
  667. while(ajListPop(thys->ResultsList, (void **) &result))
  668. continue;
  669. ajTableClear(thys->ResultsTable);
  670. ajStrSetClear(&thys->Method);
  671. ajStrSetClear(&thys->Qlinks);
  672. ajStrSetClear(&thys->Formatstr);
  673. ajStrSetClear(&thys->IndexDir);
  674. ajStrSetClear(&thys->Directory);
  675. ajStrSetClear(&thys->Filename);
  676. ajStrSetClear(&thys->Exclude);
  677. ajStrSetClear(&thys->DbFields);
  678. ajStrSetClear(&thys->DbUrl);
  679. ajStrSetClear(&thys->DbProxy);
  680. ajStrSetClear(&thys->DbHttpVer);
  681. ajStrSetClear(&thys->ServerVer);
  682. ajStrSetClear(&thys->Field);
  683. ajStrSetClear(&thys->QryString);
  684. ajStrSetClear(&thys->Application);
  685. ajStrSetClear(&thys->DbIdentifier);
  686. ajStrSetClear(&thys->DbAccession);
  687. ajStrSetClear(&thys->DbFilter);
  688. ajStrSetClear(&thys->DbReturn);
  689. thys->Fpos = 0L;
  690. thys->TextAccess = NULL;
  691. thys->Access = NULL;
  692. if(thys->QryData)
  693. AJFREE(thys->QryData);
  694. thys->QueryType = AJQUERY_UNKNOWN;
  695. /*thys->DataType = AJDATATYPE_UNKNOWN;*/
  696. thys->QryDone = ajFalse;
  697. thys->SetServer = ajFalse;
  698. thys->SetDatabase = ajFalse;
  699. thys->SetQuery = ajFalse;
  700. thys->Wild = ajFalse;
  701. thys->CaseId = ajFalse;
  702. thys->HasAcc = ajTrue; /* default true in ajQueryNew */
  703. return;
  704. }
  705. /* @func ajQuerySetWild ******************************************************
  706. **
  707. ** Tests whether a query includes wild cards in any element,
  708. ** or can return more than one entry (keyword and some other search terms
  709. ** will find multiple entries)
  710. **
  711. ** @param [u] thys [AjPQuery] Query object.
  712. ** @return [AjBool] ajTrue if query had wild cards.
  713. ** @@
  714. ******************************************************************************/
  715. AjBool ajQuerySetWild(AjPQuery thys)
  716. {
  717. AjIList iter = NULL;
  718. AjPQueryField field = NULL;
  719. AjBool ret = ajFalse;
  720. ajuint ifield = 0;
  721. if(!queryRegWild)
  722. queryWildComp();
  723. ajDebug("ajQuerySetWild fields: %u\n",
  724. ajListGetLength(thys->QueryFields));
  725. /* first test for ID query */
  726. iter = ajListIterNewread(thys->QueryFields);
  727. while(!ajListIterDone(iter))
  728. {
  729. field = ajListIterGet(iter);
  730. ajDebug("test1 query %S '%S' %u\n",
  731. field->Field, field->Wildquery, field->Link);
  732. if(ajStrMatchC(field->Field, "id"))
  733. {
  734. if(ajRegExec(queryRegWild, field->Wildquery))
  735. {
  736. thys->Wild = ajTrue;
  737. ajDebug("wild id query %S '%S'\n",
  738. field->Field, field->Wildquery);
  739. ajListIterDel(&iter);
  740. return ajTrue;
  741. }
  742. break;
  743. }
  744. }
  745. ajListIterRewind(iter);
  746. /* now test the other fields */
  747. while(!ajListIterDone(iter))
  748. {
  749. field = ajListIterGet(iter);
  750. ajDebug("test2 query %S '%S'\n",
  751. field->Field, field->Wildquery);
  752. if(ifield++ && field->Link != AJQLINK_ELSE) /* field [|&!^] field */
  753. {
  754. ajListIterDel(&iter);
  755. return ajTrue;
  756. }
  757. if(ajStrMatchC(field->Field, "id"))
  758. continue;
  759. if(ajRegExec(queryRegWild, field->Wildquery))
  760. {
  761. thys->Wild = ajTrue;
  762. ajDebug("wild query %S '%S'\n",
  763. field->Field, field->Wildquery);
  764. ajListIterDel(&iter);
  765. return ajTrue;
  766. }
  767. if(!ajStrMatchC(field->Field, "acc"))
  768. ret = ajTrue;
  769. }
  770. ajListIterDel(&iter);
  771. ajDebug("wildcard in stored query: %B\n", ret);
  772. return ret;
  773. }
  774. /* @func ajQueryStarclear *****************************************************
  775. **
  776. ** Clears elements of a query object if they are simply "*" because this
  777. ** is equivalent to a null string.
  778. **
  779. ** @param [u] thys [AjPQuery] Query object.
  780. ** @return [void]
  781. ** @@
  782. ******************************************************************************/
  783. void ajQueryStarclear(AjPQuery thys)
  784. {
  785. AjIList iter = NULL;
  786. AjPQueryField field = NULL;
  787. iter = ajListIterNew(thys->QueryFields);
  788. while(!ajListIterDone(iter))
  789. {
  790. field = ajListIterGet(iter);
  791. if(ajStrMatchC(field->Wildquery, "*"))
  792. {
  793. ajDebug("ajQueryStarclear keep field %S '%S'\n",
  794. field->Field, field->Wildquery);
  795. /*
  796. ajQueryfieldDel(&field);
  797. ajListIterRemove(iter);
  798. */
  799. }
  800. }
  801. ajListIterDel(&iter);
  802. return;
  803. }
  804. /* @section Debug *************************************************************
  805. **
  806. ** Reports sequence contents for debugging purposes
  807. **
  808. ** @fdata [AjPQuery]
  809. ** @fcategory misc
  810. **
  811. ** @nam3rule Trace Print report to debug file (if any)
  812. ** @nam4rule TraceTitle Print report to debug file (if any) with title
  813. **
  814. ** @argrule * thys [const AjPQuery] query object.
  815. **
  816. ** @valrule * [void]
  817. **
  818. ******************************************************************************/
  819. /* @func ajQueryTrace *********************************************************
  820. **
  821. ** Debug calls to trace the data in a query object.
  822. **
  823. ** @param [r] thys [const AjPQuery] query object.
  824. ** @return [void]
  825. ** @@
  826. ******************************************************************************/
  827. void ajQueryTrace(const AjPQuery thys)
  828. {
  829. AjIList iter = NULL;
  830. AjPQueryField field = NULL;
  831. const char* operators[] =
  832. {
  833. "init",
  834. "OR", "AND", "EOR", "NOT",
  835. "ELSE"
  836. };
  837. ajDebug( " Query Trace\n");
  838. if(ajStrGetLen(thys->SvrName))
  839. ajDebug( " SvrName: '%S'\n", thys->SvrName);
  840. if(ajStrGetLen(thys->DbName))
  841. ajDebug( " DbName: '%S'\n", thys->DbName);
  842. if(ajStrGetLen(thys->DbAlias))
  843. ajDebug( " DbAlias: '%S'\n", thys->DbAlias);
  844. if(ajStrGetLen(thys->DbType))
  845. ajDebug( " DbType: '%S' (%d)\n", thys->DbType, thys->QueryType);
  846. iter = ajListIterNewread(thys->QueryFields);
  847. while(!ajListIterDone(iter))
  848. {
  849. field = ajListIterGet(iter);
  850. if(field->Link < AJQLINK_MAX)
  851. ajDebug( " %S: '%S' %d (%s)\n",
  852. field->Field, field->Wildquery,
  853. field->Link, operators[field->Link]);
  854. else
  855. ajDebug( " %S: '%S' %d\n",
  856. field->Field, field->Wildquery,
  857. field->Link);
  858. }
  859. ajListIterDel(&iter);
  860. ajDebug( " Case-sensitive Id: '%B'\n", thys->CaseId);
  861. ajDebug( " Has accession: %B\n", thys->HasAcc);
  862. if(ajStrGetLen(thys->Method))
  863. ajDebug( " Method: '%S'\n", thys->Method);
  864. if(ajStrGetLen(thys->Formatstr))
  865. ajDebug( " Formatstr: '%S'\n", thys->Formatstr);
  866. if(ajStrGetLen(thys->IndexDir))
  867. ajDebug( " IndexDir: '%S'\n", thys->IndexDir);
  868. if(ajStrGetLen(thys->Directory))
  869. ajDebug( " Directory: '%S'\n", thys->Directory);
  870. if(ajStrGetLen(thys->Filename))
  871. ajDebug( " Filename: '%S'\n", thys->Filename);
  872. if(ajStrGetLen(thys->Exclude))
  873. ajDebug( " Exclude: '%S'\n", thys->Exclude);
  874. if(ajStrGetLen(thys->DbFields))
  875. ajDebug( " DbFields: '%S'\n", thys->DbFields);
  876. if(ajStrGetLen(thys->DbIdentifier))
  877. ajDebug( " DbIdentifier: '%S'\n", thys->DbIdentifier);
  878. if(ajStrGetLen(thys->DbAccession))
  879. ajDebug( " DbAccession: '%S'\n", thys->DbAccession);
  880. if(ajStrGetLen(thys->DbFilter))
  881. ajDebug( " DbFilter: '%S'\n", thys->DbFilter);
  882. if(ajStrGetLen(thys->DbReturn))
  883. ajDebug( " DbReturn: '%S'\n", thys->DbReturn);
  884. if(ajStrGetLen(thys->DbUrl))
  885. ajDebug( " DbUrl: '%S'\n", thys->DbUrl);
  886. if(ajStrGetLen(thys->DbProxy))
  887. ajDebug( " DbProxy: '%S'\n", thys->DbProxy);
  888. if(ajStrGetLen(thys->DbHttpVer))
  889. ajDebug( " DbHttpVer: '%S'\n", thys->DbHttpVer);
  890. if(ajStrGetLen(thys->Field))
  891. ajDebug( " Field: '%S'\n", thys->Field);
  892. if(ajStrGetLen(thys->QryString))
  893. ajDebug( " QryString: '%S'\n", thys->QryString);
  894. if(ajStrGetLen(thys->Application))
  895. ajDebug( " Application: '%S'\n", thys->Application);
  896. ajDebug( " Fpos: %ld\n", thys->Fpos);
  897. ajDebug( " QryDone: %B\n", thys->QryDone);
  898. ajDebug( " Wildcard in query: %B\n", thys->Wild);
  899. if(thys->Access)
  900. ajDebug( " Access: exists\n");
  901. if(thys->QryData)
  902. ajDebug( " QryData: exists\n");
  903. return;
  904. }
  905. /* @section exit **************************************************************
  906. **
  907. ** Functions called on exit from the program by ajExit to do
  908. ** any necessary cleanup and to report internal statistics to the debug file
  909. **
  910. ** @fdata [AjPQuery]
  911. ** @fnote general exit functions, no arguments
  912. **
  913. ** @nam3rule Exit Cleanup and report on exit
  914. **
  915. ** @valrule * [void]
  916. **
  917. ** @fcategory misc
  918. ******************************************************************************/
  919. /* @func ajQueryExit **********************************************************
  920. **
  921. ** Cleans up query processing internal memory
  922. **
  923. ** @return [void]
  924. ** @@
  925. ******************************************************************************/
  926. void ajQueryExit(void)
  927. {
  928. ajStrDel(&queryFormat);
  929. ajStrDel(&queryList);
  930. ajStrDel(&querySvr);
  931. ajStrDel(&queryDb);
  932. ajStrDel(&queryChr);
  933. ajStrDel(&queryTest);
  934. ajRegFree(&queryRegAsis);
  935. ajRegFree(&queryRegSvr);
  936. ajRegFree(&queryRegDbId);
  937. ajRegFree(&queryRegDbField);
  938. ajRegFree(&queryRegFmt);
  939. ajRegFree(&queryRegFieldId);
  940. ajRegFree(&queryRegId);
  941. ajRegFree(&queryRegList);
  942. ajRegFree(&queryRegRange);
  943. ajRegFree(&queryRegWild);
  944. return;
  945. }
  946. /* @datasection [AjPQueryField] Query fields **********************************
  947. **
  948. ** Query field processing
  949. **
  950. ** @nam2rule Queryfield
  951. **
  952. ******************************************************************************/
  953. /* @section constructors ******************************************************
  954. **
  955. ** Constructors
  956. **
  957. ** @fdata [AjPQueryField]
  958. **
  959. ** @nam3rule New Constructor
  960. ** @suffix C Character string data
  961. ** @suffix S String data
  962. **
  963. ** @argrule C fieldtxt [const char*] Field name
  964. ** @argrule C wildtxt [const char*] Wildcard query string
  965. ** @argrule S field [const AjPStr] Field name
  966. ** @argrule S wild [const AjPStr] Wildcard query string
  967. ** @argrule New oper [AjEQryLink] Operator
  968. **
  969. ** @valrule * [AjPQueryField] Query field object
  970. **
  971. ** @fcategory new
  972. **
  973. ******************************************************************************/
  974. /* @func ajQueryfieldNewC *****************************************************
  975. **
  976. ** Constructor for a query field
  977. **
  978. ** @param [r] fieldtxt [const char*] Field name
  979. ** @param [r] wildtxt [const char*] Wildcard query string
  980. ** @param [r] oper [AjEQryLink] Operator
  981. **
  982. ** @return [AjPQueryField] Query field
  983. ******************************************************************************/
  984. AjPQueryField ajQueryfieldNewC(const char* fieldtxt,
  985. const char* wildtxt,
  986. AjEQryLink oper)
  987. {
  988. AjPQueryField ret;
  989. AJNEW0(ret);
  990. ajDebug("ajQueryfieldNewC '%s' '%s'\n", fieldtxt, wildtxt);
  991. ret->Field = ajStrNewC(fieldtxt);
  992. ret->Wildquery = ajStrNewC(wildtxt);
  993. ret->Link = oper;
  994. ajStrFmtLower(&ret->Field);
  995. return ret;
  996. }
  997. /* @func ajQueryfieldNewS *****************************************************
  998. **
  999. ** Constructor for a query field
  1000. **
  1001. ** @param [r] field [const AjPStr] Field name
  1002. ** @param [r] wild [const AjPStr] Wildcard query string
  1003. ** @param [r] oper [AjEQryLink] Operator
  1004. **
  1005. ** @return [AjPQueryField] Query field
  1006. ******************************************************************************/
  1007. AjPQueryField ajQueryfieldNewS(const AjPStr field,
  1008. const AjPStr wild,
  1009. AjEQryLink oper)
  1010. {
  1011. AjPQueryField ret;
  1012. AJNEW0(ret);
  1013. ajDebug("ajQueryfieldNewS '%S' '%S'\n", field, wild);
  1014. ret->Field = ajStrNewS(field);
  1015. ret->Wildquery = ajStrNewS(wild);
  1016. ret->Link = oper;
  1017. ajStrFmtLower(&ret->Field);
  1018. return ret;
  1019. }
  1020. /* @section Query Field Destructors *******************************************
  1021. **
  1022. ** Destruction destroys all internal data structures and frees the
  1023. ** memory allocated for the query field object.
  1024. **
  1025. ** @fdata [AjPQueryField]
  1026. **
  1027. ** @nam3rule Del destructor
  1028. **
  1029. ** @argrule Del Pthis [AjPQueryField*] Query field
  1030. **
  1031. ** @valrule * [void]
  1032. **
  1033. ** @fcategory delete
  1034. **
  1035. ******************************************************************************/
  1036. /* @func ajQueryfieldDel ******************************************************
  1037. **
  1038. ** Destructor for a query field
  1039. **
  1040. ** @param [d] Pthis [AjPQueryField*] Query field object to be deleted
  1041. **
  1042. ** @return [void]
  1043. ******************************************************************************/
  1044. void ajQueryfieldDel(AjPQueryField *Pthis)
  1045. {
  1046. AjPQueryField thys;
  1047. if(!Pthis) return;
  1048. if(!*Pthis) return;
  1049. thys = *Pthis;
  1050. ajStrDel(&thys->Field);
  1051. ajStrDel(&thys->Wildquery);
  1052. AJFREE(*Pthis);
  1053. return;
  1054. }
  1055. /* @datasection [AjPList] Query field list ************************************
  1056. **
  1057. ** Query fields lists are handled internally. Only static functions
  1058. ** should appear here
  1059. **
  1060. ** @nam2rule Querylist Query list processing
  1061. **
  1062. ******************************************************************************/
  1063. /* @section Debug *************************************************************
  1064. **
  1065. ** Reports sequence contents for debugging purposes
  1066. **
  1067. ** @fdata [AjPList]
  1068. ** @fcategory misc
  1069. **
  1070. ** @nam3rule Trace Print report to debug file (if any)
  1071. ** @nam4rule TraceTitle Print report to debug file (if any) with title
  1072. **
  1073. ** @argrule * list [const AjPList] query list
  1074. **
  1075. ** @valrule * [void]
  1076. **
  1077. ******************************************************************************/
  1078. /* @func ajQuerylistTrace *****************************************************
  1079. **
  1080. ** Traces the nodes in a query list
  1081. **
  1082. ** @param [r] list [const AjPList] The query list
  1083. ** @return [void]
  1084. ******************************************************************************/
  1085. void ajQuerylistTrace(const AjPList list)
  1086. {
  1087. AjIList iter;
  1088. AjPQueryList node;
  1089. ajuint i = 0;
  1090. iter = ajListIterNewread(list);
  1091. ajDebug("ajQuerylistTrace %d nodes\n", ajListGetLength(list));
  1092. while(!ajListIterDone(iter))
  1093. {
  1094. node = (AjPQueryList) ajListIterGet(iter);
  1095. ajDebug("%3d: '%S' '%S' %d\n",
  1096. ++i, node->Qry,
  1097. node->Formatstr, node->Format);
  1098. }
  1099. ajListIterDel(&iter);
  1100. ajDebug("...Done...\n");
  1101. return;
  1102. }
  1103. /* @funcstatic queryWildComp **************************************************
  1104. **
  1105. ** Compiles the regular expressions for testing wild cards in queries.
  1106. ** These are held in static storage and built once only if needed.
  1107. **
  1108. ** @return [void]
  1109. ** @@
  1110. ******************************************************************************/
  1111. static void queryWildComp(void)
  1112. {
  1113. if(!queryRegWild)
  1114. queryRegWild = ajRegCompC("[*?]");
  1115. return;
  1116. }
  1117. /* @datasection [AjPStr] Query string *****************************************
  1118. **
  1119. ** Function is for manipulating query strings
  1120. **
  1121. ** @nam2rule Querystr
  1122. **
  1123. ******************************************************************************/
  1124. /* @section Query string parsing **********************************************
  1125. **
  1126. ** Parses a query string and removes the processed string trokens
  1127. **
  1128. ** @fdata [AjPStr]
  1129. ** @fcategory modify
  1130. **
  1131. ** @nam3rule Parse Parse the string
  1132. ** @nam4rule ParseFormat Parse the format prefix
  1133. ** @nam4rule ParseListfile Parse the listfile prefix
  1134. ** @nam4rule ParseRange Parse the range suffix
  1135. ** @nam4rule ParseRead Parse a text query and read data
  1136. **
  1137. ** @argrule Parse Pqry [AjPStr*] Query string
  1138. ** @argrule Format textin [AjPTextin] Text input object
  1139. ** @argrule Format findformat [AjBool function] Function to validate
  1140. ** format name
  1141. ** @argrule Range Pbegin [ajint*] Begin position
  1142. ** @argrule Range Pend [ajint*] End position
  1143. ** @argrule Range Prev [AjBool*] Reverse orientation
  1144. ** @argrule Read textin [AjPTextin] Text input object
  1145. ** @argrule Read findformat [AjBool function] Function to validate format name
  1146. ** @argrule Read Pnontext [AjBool*] True if access is a non-text method
  1147. ** to be processed by the caller
  1148. **
  1149. ** @valrule * [AjBool] True if found
  1150. ** @valrule *Format [const AjPStr] Format name if found
  1151. **
  1152. ******************************************************************************/
  1153. /* @func ajQuerystrParseFormat ************************************************
  1154. **
  1155. ** Parses a query (USA, UFO or general query).
  1156. **
  1157. ** Then tests for "format::" and returns this if it is found,
  1158. ** removing the format part of the original query.
  1159. **
  1160. ** @param [u] Pqry [AjPStr*] Query string
  1161. ** @param [u] textin [AjPTextin] Text input object
  1162. ** @param [f] findformat [AjBool function] Function to validate format name
  1163. ** @return [const AjPStr] Format name if found
  1164. ** @@
  1165. ******************************************************************************/
  1166. const AjPStr ajQuerystrParseFormat(AjPStr *Pqry, AjPTextin textin,
  1167. AjBool findformat(const AjPStr format,
  1168. ajint *iformat))
  1169. {
  1170. AjBool fmtstat = ajFalse; /* status returns from regex tests */
  1171. AjBool asisstat = ajFalse;
  1172. AjBool liststat = ajFalse;
  1173. AjPQuery qry = textin->Query;
  1174. ajDebug("++ajQuerystrParseFormat '%S'\n", *Pqry);
  1175. if(!queryRegInitDone)
  1176. queryRegInit();
  1177. /* Strip any leading spaces */
  1178. ajStrTrimC(Pqry," \t\n");
  1179. asisstat = ajRegExec(queryRegAsis, *Pqry);
  1180. liststat = ajRegExec(queryRegList, *Pqry);
  1181. if(liststat || asisstat)
  1182. return NULL;
  1183. fmtstat = ajRegExec(queryRegFmt, *Pqry);
  1184. if(!fmtstat)
  1185. {
  1186. if(ajStrGetLen(textin->Formatstr))
  1187. {
  1188. if(findformat(textin->Formatstr, &textin->Format))
  1189. ajStrAssignS(&qry->Formatstr, textin->Formatstr);
  1190. }
  1191. return NULL;
  1192. }
  1193. ajRegSubI(queryRegFmt, 1, &queryFormat);
  1194. ajRegSubI(queryRegFmt, 2, Pqry);
  1195. ajDebug("found format %S rest '%S'\n", queryFormat, *Pqry);
  1196. ajStrAssignEmptyC(&queryFormat, "unknown");
  1197. if(findformat(queryFormat, &textin->Format))
  1198. {
  1199. ajStrAssignS(&qry->Formatstr, queryFormat);
  1200. ajStrAssignS(&textin->Formatstr, queryFormat);
  1201. }
  1202. else
  1203. ajErr("Unknown input format '%S'\n", queryFormat);
  1204. return queryFormat;
  1205. }
  1206. /* @func ajQuerystrParseListfile **********************************************
  1207. **
  1208. ** Parses a query (USA, UFO or general query).
  1209. **
  1210. ** Then tests for "list::" or "@" and returns true if found,
  1211. ** removing the filename only in the origiunal query.
  1212. **
  1213. ** @param [u] Pqry [AjPStr*] Query string
  1214. ** @return [AjBool] True if found
  1215. ** @@
  1216. ******************************************************************************/
  1217. AjBool ajQuerystrParseListfile(AjPStr *Pqry)
  1218. {
  1219. AjBool liststat = ajFalse; /* status returns from regex tests */
  1220. ajDebug("++ajQuerystrParseListfile '%S'\n", *Pqry);
  1221. if(!queryRegInitDone)
  1222. queryRegInit();
  1223. /* Strip any leading spaces */
  1224. ajStrTrimC(Pqry," \t\n");
  1225. ajStrAssignS(&queryTest, *Pqry);
  1226. liststat = ajRegExec(queryRegList, queryTest);
  1227. if(liststat)
  1228. {
  1229. ajRegSubI(queryRegList, 2, Pqry);
  1230. ajDebug("list found @%S\n", *Pqry);
  1231. }
  1232. return liststat;
  1233. }
  1234. /* @func ajQuerystrParseRange *************************************************
  1235. **
  1236. ** Parses a query (USA, UFO or general query).
  1237. **
  1238. ** Tests for "[n:n:r]" range and sets this if it is found,
  1239. ** removing the range part of the original query.
  1240. **
  1241. ** @param [u] Pqry [AjPStr*] Query string
  1242. ** @param [u] Pbegin [ajint*] Begin position
  1243. ** @param [u] Pend [ajint*] End position
  1244. ** @param [u] Prev [AjBool*] Reverse orientation
  1245. ** @return [AjBool] True if range was found.
  1246. ** @@
  1247. ******************************************************************************/
  1248. AjBool ajQuerystrParseRange(AjPStr *Pqry, ajint *Pbegin, ajint *Pend,
  1249. AjBool *Prev)
  1250. {
  1251. AjPStr tmpstr = NULL;
  1252. AjBool rangestat = ajFalse;
  1253. if(!queryRegInitDone)
  1254. queryRegInit();
  1255. ajDebug("ajQuerystrParseRange: '%S'\n", *Pqry);
  1256. rangestat = ajRegExec(queryRegRange, *Pqry);
  1257. if(rangestat)
  1258. {
  1259. ajRegSubI(queryRegRange, 2, &tmpstr);
  1260. if(ajStrGetLen(tmpstr))
  1261. ajStrToInt(tmpstr, Pbegin);
  1262. ajRegSubI(queryRegRange, 3, &tmpstr);
  1263. if(ajStrGetLen(tmpstr))
  1264. ajStrToInt(tmpstr, Pend);
  1265. ajRegSubI(queryRegRange, 5, &tmpstr);
  1266. if(ajStrGetLen(tmpstr))
  1267. *Prev = ajTrue;
  1268. ajStrDel(&tmpstr);
  1269. ajRegSubI(queryRegRange, 1, Pqry);
  1270. ajDebug("range found [%d:%d:%b]\n",
  1271. *Pbegin, *Pend, *Prev);
  1272. }
  1273. return rangestat;
  1274. }
  1275. /* @func ajQuerystrParseRead **************************************************
  1276. **
  1277. ** Parses a query (USA, UFO or general query).
  1278. **
  1279. ** First tests for "asis" input and sets the rest of the query as input data.
  1280. **
  1281. ** Then tests for server:dbname:query or dbname:query
  1282. ** and tests whether the access method is a text method.
  1283. **
  1284. ** For text access, calls the access method to opens the file
  1285. ** (and set the file position).
  1286. **
  1287. ** If there is no database, looks for file:query and opens the file.
  1288. ** If an offset is provided as %offset sets the file position
  1289. **
  1290. ** If the file does now exist, tests again for a database of that name
  1291. ** from any known server.
  1292. **
  1293. ** If no text data was found, returns the filled in datatype-specific details
  1294. **
  1295. ** @param [u] Pqry [AjPStr*] Query string
  1296. ** @param [u] textin [AjPTextin] Text input structure.
  1297. ** @param [f] findformat [AjBool function] Function to validate format name
  1298. ** @param [w] Pnontext [AjBool*] True if access is a non-text method
  1299. ** @return [AjBool] ajTrue on success.
  1300. ** @@
  1301. ******************************************************************************/
  1302. AjBool ajQuerystrParseRead(AjPStr *Pqry, AjPTextin textin,
  1303. AjBool findformat(const AjPStr format,
  1304. ajint *iformat),
  1305. AjBool *Pnontext)
  1306. {
  1307. AjPQuery qry;
  1308. AjBool svrstat = ajFalse;
  1309. AjBool regstat = ajFalse;
  1310. AjBool dbstat = ajFalse;
  1311. AjBool accstat = ajFalse; /* return status from reading something */
  1312. AjBool asisstat = ajFalse;
  1313. AjBool drcatstat = ajFalse;
  1314. AjBool inbraces = ajFalse;
  1315. AjPStr braceopen = NULL;
  1316. AjPStr braceclose = NULL;
  1317. AjPStr idstr = NULL;
  1318. AjPStr lastoper= NULL;
  1319. AjPStr operstr = NULL;
  1320. AjPStr allfields = NULL;
  1321. AjPStr qrystring = NULL;
  1322. AjPStr qrystr = NULL;
  1323. ajlong i;
  1324. AjPStrTok handle = NULL;
  1325. AjPResource drcat = NULL;
  1326. AjPTextAccess textaccess = NULL;
  1327. ajint iformat = 0;
  1328. #ifdef __CYGWIN__
  1329. char cygd;
  1330. #endif
  1331. *Pnontext = ajFalse;
  1332. qry = textin->Query;
  1333. if(qry->QryDone)
  1334. return ajFalse;
  1335. ajStrAssignS(&qry->QryString, *Pqry);
  1336. ajStrDel(&qry->Field); /* clear it. we test this for regstat */
  1337. if(!queryRegInitDone)
  1338. queryRegInit();
  1339. ajDebug("++ajQrystrParseRead '%S' '%S' %d\n",
  1340. *Pqry,
  1341. textin->Formatstr, textin->Format);
  1342. /* Strip any leading spaces */
  1343. ajStrTrimC(Pqry," \t\n");
  1344. asisstat = ajRegExec(queryRegAsis, *Pqry);
  1345. if(asisstat)
  1346. {
  1347. ajStrAssignC(&queryFormat, "asis");
  1348. if(!findformat(queryFormat, &textin->Format))
  1349. {
  1350. ajErr("asis:: not supported by datatype for '%S'",
  1351. *Pqry);
  1352. return ajFalse;
  1353. }
  1354. ajStrAssignS(&qry->Formatstr, queryFormat);
  1355. ajStrAssignS(&textin->Formatstr, queryFormat);
  1356. ajRegSubI(queryRegAsis, 1, &qry->Filename);
  1357. ajDebug("asis sequence '%S'\n", qry->Filename);
  1358. return ajTextinAccessAsis(textin);
  1359. }
  1360. #ifdef __CYGWIN__
  1361. if(ajStrGetCharPos(*Pqry,1) == ':')
  1362. {
  1363. cygd = ajStrGetCharFirst(*Pqry);
  1364. if(isupper((int) cygd))
  1365. ajStrPasteCountK(Pqry, 0, (char) tolower((int)cygd), 1);
  1366. ajStrPasteCountK(Pqry, 1, '/', 1);
  1367. ajStrInsertC(Pqry, 0, "/cygdrive/");
  1368. }
  1369. #endif
  1370. ajDebug("query to test: '%S'\n\n", *Pqry);
  1371. svrstat = ajRegExec(queryRegSvr, *Pqry);
  1372. ajDebug("server dbexp: %B '%S'\n", svrstat, *Pqry);
  1373. if(svrstat)
  1374. {
  1375. ajRegSubI(queryRegSvr, 1, &querySvr);
  1376. /* clear it if this was really a file */
  1377. if(ajNamServer(querySvr))
  1378. {
  1379. ajRegPost(queryRegSvr, Pqry);
  1380. ajDebug("found server %S, rest '%S'\n",
  1381. querySvr, *Pqry);
  1382. }
  1383. else
  1384. {
  1385. ajDebug("unknown server %S, try dbname\n", querySvr);
  1386. ajStrDel(&querySvr);
  1387. svrstat = ajFalse;
  1388. }
  1389. }
  1390. regstat = ajFalse;
  1391. if(ajRegExec(queryRegDbField, *Pqry))
  1392. {
  1393. regstat = ajTrue;
  1394. ajDebug("dbname queryRegDbField: %B '%S'\n", regstat, *Pqry);
  1395. /* test dbname-field: or dbname: */
  1396. ajRegSubI(queryRegDbField, 1, &queryDb);
  1397. ajRegSubI(queryRegDbField, 4, &allfields);
  1398. ajRegSubI(queryRegDbField, 5, &braceclose);
  1399. ajStrTrimWhite(&allfields);
  1400. if(!ajStrMatchC(braceclose, "}"))
  1401. ajErr("Bad query syntax: unclosed braces '%S'", *Pqry);
  1402. inbraces = ajTrue; /* braces in the regex */
  1403. qry->QueryType = AJQUERY_QUERY;
  1404. ajDebug("Query db: '%S' allfields: '%S'\n", queryDb, allfields);
  1405. /* clear it if this was really a file */
  1406. if(ajStrGetLen(querySvr))
  1407. {
  1408. if(!ajNamAliasServer(&queryDb, querySvr))
  1409. {
  1410. ajDebug("unknown dbname %S for server %S\n",
  1411. queryDb, querySvr);
  1412. ajStrDel(&queryDb);
  1413. ajStrDel(&qry->Field);
  1414. regstat = ajFalse;
  1415. }
  1416. }
  1417. else if(!ajNamAliasDatabase(&queryDb))
  1418. {
  1419. drcat = ajResourceNewDrcat(queryDb);
  1420. if(drcat)
  1421. {
  1422. ajDebug("d…

Large files files are truncated, but you can click here to view the full file