PageRenderTime 121ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/locationPathExpr.cpp

https://bitbucket.org/aonyung/vtd-xml-c-64
C++ | 2314 lines | 2059 code | 146 blank | 109 comment | 536 complexity | 40f07237d0779123f6a08f3abc598f02 MD5 | raw file
  1. /*
  2. * Copyright (C) 2002-2011 XimpleWare, info@ximpleware.com
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "locationPathExpr.h"
  19. #include "autoPilot.h"
  20. #include "textIter.h"
  21. using namespace com_ximpleware;
  22. LocationPathExpr::LocationPathExpr() try :
  23. pathType(RELATIVE_PATH),
  24. s(NULL),
  25. currentStep(NULL),
  26. state(XPATH_EVAL_START),
  27. ih(new IntHash())
  28. {
  29. }
  30. catch (std::bad_alloc&){
  31. throw OutOfMemException("Allocation failed for LocationPathExpr");
  32. }
  33. LocationPathExpr::~LocationPathExpr(){
  34. Step *tmp, *tmp2;
  35. if (s != NULL){
  36. tmp = s;
  37. tmp2 = tmp->nextS;
  38. while(tmp2!=NULL){
  39. delete(tmp);
  40. tmp= tmp2;
  41. tmp2 = tmp2->nextS;
  42. }
  43. delete(tmp);
  44. }
  45. delete(ih);
  46. }
  47. bool LocationPathExpr::evalBoolean(VTDNav *vn){
  48. bool a = false;
  49. int size;
  50. vn->push2();
  51. // record stack size
  52. size = vn->contextBuf2->size;
  53. try{
  54. a = (evalNodeSet(vn) != -1);
  55. }catch (...){
  56. }
  57. //rewind stack
  58. vn->contextBuf2->size = size;
  59. reset(vn);
  60. vn->pop2();
  61. return a;
  62. }
  63. double LocationPathExpr::evalNumber(VTDNav *vn){
  64. double d = 0.0;
  65. int a = getStringIndex(vn);
  66. try{
  67. if (a!=-1) return vn->parseDouble(a);
  68. }catch (...){
  69. }
  70. return 0/d;
  71. }
  72. int LocationPathExpr::evalNodeSet(VTDNav *vn){
  73. int result;
  74. if (currentStep == NULL) {
  75. if ( pathType == ABSOLUTE_PATH){
  76. vn->toElement(ROOT);
  77. vn->toElement(PARENT);
  78. }
  79. currentStep = s;
  80. if (currentStep == NULL){
  81. if (state == XPATH_EVAL_START){
  82. state = XPATH_EVAL_END;
  83. return 0;
  84. }
  85. else{
  86. return -1;
  87. }
  88. }
  89. }
  90. while (true) {
  91. switch (currentStep->axis_type) {
  92. case AXIS_CHILD:
  93. if ( (result = process_child(vn))!=-2)
  94. return result;
  95. break;
  96. case AXIS_DESCENDANT_OR_SELF:
  97. case AXIS_DESCENDANT:
  98. case AXIS_PRECEDING:
  99. case AXIS_FOLLOWING:
  100. if ((result = process_DDFP(vn))!= -2)
  101. return result;
  102. break;
  103. case AXIS_PARENT:
  104. if ((result = process_parent(vn))!= -2)
  105. return result;
  106. break;
  107. case AXIS_ANCESTOR:
  108. if ((result = process_ancestor(vn))!= -2)
  109. return result;
  110. break;
  111. case AXIS_ANCESTOR_OR_SELF:
  112. if ((result = process_ancestor_or_self(vn))!= -2)
  113. return result;
  114. break;
  115. case AXIS_SELF:
  116. if ((result = process_self(vn))!= -2)
  117. return result;
  118. break;
  119. case AXIS_FOLLOWING_SIBLING:
  120. if ((result = process_following_sibling(vn))!= -2)
  121. return result;
  122. break;
  123. case AXIS_PRECEDING_SIBLING:
  124. if ((result = process_preceding_sibling(vn))!= -2)
  125. return result;
  126. break;
  127. case AXIS_ATTRIBUTE:
  128. if ((result = process_attribute(vn))!= -2)
  129. return result;
  130. break;
  131. case AXIS_NAMESPACE:
  132. if ((result = process_namespace(vn))!= -2)
  133. return result;
  134. break;
  135. default:
  136. throw XPathEvalException("axis not supported");
  137. }
  138. }
  139. }
  140. UCSChar* LocationPathExpr::evalString(VTDNav *vn){
  141. int a = getStringIndex(vn);
  142. try {
  143. if (a != -1)
  144. return vn->toString(a);
  145. } catch (std::bad_alloc&) {
  146. throw;
  147. }
  148. return createEmptyString();
  149. }
  150. void LocationPathExpr::reset(VTDNav *vn){
  151. Step *temp = s;
  152. state = XPATH_EVAL_START;
  153. ih->reset();
  154. currentStep = NULL;
  155. while(temp!=NULL){
  156. temp->reset_s(vn);
  157. temp = temp->nextS;
  158. }
  159. }
  160. void LocationPathExpr::toString(UCSChar *string){
  161. Step *ts = s;
  162. if (pathType == ABSOLUTE_PATH){
  163. wprintf(L"/");
  164. }
  165. if (ts == NULL)
  166. return;
  167. else
  168. ts->toString_s(string);
  169. }
  170. bool LocationPathExpr::isNumerical(){return false;}
  171. bool LocationPathExpr::isNodeSet(){return true;}
  172. bool LocationPathExpr::isString(){return false;}
  173. bool LocationPathExpr::isBoolean(){return false;}
  174. bool LocationPathExpr::requireContextSize(){return false;}
  175. void LocationPathExpr::setContextSize(int size){}
  176. void LocationPathExpr::setPosition(int pos){}
  177. int LocationPathExpr::adjust(int n){
  178. int i;
  179. if (pathType == RELATIVE_PATH){
  180. i= min(6,IntHash::determineHashWidth(n));//hashwidth 64
  181. } else {
  182. i=IntHash::determineHashWidth(n);
  183. }
  184. if (ih!=NULL && i<=ih->e)
  185. {}else {
  186. delete (ih);
  187. ih = new IntHash(i);
  188. }
  189. Step *temp = s;
  190. while(temp!=NULL){
  191. temp->adjust(n);
  192. temp = temp->nextS;
  193. }
  194. return i;
  195. }
  196. int LocationPathExpr::computeContextSize(Predicate *p, VTDNav *vn){
  197. bool b = false;
  198. //Predicate *tp = NULL;
  199. int i = 0;
  200. AutoPilot *ap = (AutoPilot *)currentStep->o;
  201. UCSChar *helper = NULL;
  202. switch(currentStep->axis_type){
  203. case AXIS_CHILD:
  204. if (currentStep->nt->testType < NT_TEXT){
  205. b = vn->toElement(FIRST_CHILD);
  206. if (b) {
  207. do {
  208. if (currentStep->eval_s2(vn, p)) {
  209. i++;
  210. }
  211. } while (vn->toElement(NEXT_SIBLING));
  212. vn->toElement(PARENT);
  213. currentStep->resetP2_s(vn,p);
  214. return i;
  215. } else
  216. return 0;
  217. }else {
  218. int result;
  219. TextIter* ti = new TextIter();
  220. ti->touch(vn);
  221. selectNodeType(ti);
  222. while((result=ti->getNext())!=-1){
  223. vn->LN = result;
  224. vn->atTerminal = true;
  225. if (currentStep->evalPredicates2(vn,p)){
  226. i++;
  227. }
  228. }
  229. vn->atTerminal = false;
  230. currentStep->resetP2_s(vn,p);
  231. return i;
  232. }
  233. case AXIS_DESCENDANT_OR_SELF:
  234. case AXIS_DESCENDANT:
  235. case AXIS_PRECEDING:
  236. case AXIS_FOLLOWING:
  237. if (currentStep->nt->testType == NT_NODE){
  238. helper = (UCSChar *)L"*";
  239. }else if (currentStep->nt->testType == NT_NAMETEST){
  240. helper = currentStep->nt->nodeName;
  241. }else
  242. throw XPathEvalException(
  243. "can't run descendant following, or following-sibling axis over comment(), pi(), and text()");
  244. if (ap==NULL)
  245. ap = new AutoPilot(vn);
  246. else
  247. ap->bind(vn);
  248. if (currentStep->axis_type == AXIS_DESCENDANT_OR_SELF ){
  249. if (currentStep->nt->testType == NT_NODE)
  250. ap->setSpecial(true);
  251. else
  252. ap->setSpecial(false);
  253. }
  254. //currentStep.o = ap = new AutoPilot(vn);
  255. if (currentStep->axis_type == AXIS_DESCENDANT_OR_SELF)
  256. if (currentStep->nt->localName!=NULL)
  257. ap->selectElementNS(currentStep->nt->URL,currentStep->nt->localName);
  258. else
  259. ap->selectElement(helper);
  260. else if (currentStep->axis_type == AXIS_DESCENDANT)
  261. if (currentStep->nt->localName!=NULL)
  262. ap->selectElementNS_D(currentStep->nt->URL,currentStep->nt->localName);
  263. else
  264. ap->selectElement_D(helper);
  265. else if (currentStep->axis_type == AXIS_PRECEDING)
  266. if (currentStep->nt->localName!=NULL)
  267. ap->selectElementNS_P(currentStep->nt->URL,currentStep->nt->localName);
  268. else
  269. ap->selectElement_P(helper);
  270. else
  271. if (currentStep->nt->localName!=NULL)
  272. ap->selectElementNS_F(currentStep->nt->URL,currentStep->nt->localName);
  273. else
  274. ap->selectElement_F(helper);
  275. vn->push2();
  276. while(ap->iterate()){
  277. if (currentStep->evalPredicates2(vn,p)){
  278. i++;
  279. }
  280. }
  281. vn->pop2();
  282. currentStep->resetP2_s(vn,p);
  283. currentStep->o= ap;
  284. //freeAutoPilot(ap);
  285. return i;
  286. case AXIS_PARENT:
  287. vn->push2();
  288. i = 0;
  289. if (vn->toElement( PARENT)){
  290. if (currentStep->eval_s2(vn,p)){
  291. i++;
  292. }
  293. }
  294. vn->pop2();
  295. currentStep->resetP2_s(vn,p);
  296. return i;
  297. case AXIS_ANCESTOR:
  298. vn->push2();
  299. i = 0;
  300. while (vn->toElement(PARENT)) {
  301. if (currentStep->eval_s2(vn, p)) {
  302. i++;
  303. }
  304. }
  305. vn->pop2();
  306. currentStep->resetP2_s(vn,p);
  307. return i;
  308. case AXIS_ANCESTOR_OR_SELF:
  309. vn->push2();
  310. i = 0;
  311. do {
  312. if (currentStep->eval_s2(vn, p)) {
  313. i++;
  314. }
  315. }while(vn->toElement(PARENT));
  316. vn->pop2();
  317. currentStep->resetP2_s(vn,p);
  318. return i;
  319. case AXIS_SELF:
  320. i = 0;
  321. if (vn->toElement(PARENT)){
  322. if (currentStep->eval_s2(vn,p)){
  323. i++;
  324. }
  325. }
  326. currentStep->resetP2_s(vn,p);
  327. return i;
  328. case AXIS_FOLLOWING_SIBLING:
  329. vn->push2();
  330. while(vn->toElement(NEXT_SIBLING)){
  331. if (currentStep->eval_s2(vn,p)){
  332. i++;
  333. }
  334. }
  335. vn->pop2();
  336. currentStep->resetP2_s(vn,p);
  337. return i;
  338. case AXIS_PRECEDING_SIBLING:
  339. vn->push2();
  340. while(vn->toElement(PREV_SIBLING)){
  341. if (currentStep->eval_s2(vn,p)){
  342. i++;
  343. }
  344. }
  345. vn->pop2();
  346. currentStep->resetP2_s(vn,p);
  347. return i;
  348. case AXIS_ATTRIBUTE:
  349. if (ap==NULL)
  350. ap = new AutoPilot(vn);
  351. else
  352. ap->bind(vn);
  353. //ap = createAutoPilot(vn);
  354. if (currentStep->nt->testType == NT_NODE)
  355. ap->selectAttr((UCSChar *)L"*");
  356. else if (currentStep->nt->localName!=NULL)
  357. ap->selectAttrNS(currentStep->nt->URL,
  358. currentStep->nt->localName);
  359. else
  360. ap->selectAttr(currentStep->nt->nodeName);
  361. i = 0;
  362. while(ap->iterateAttr2()!=-1){
  363. if (currentStep->evalPredicates2( vn, p)){
  364. i++;
  365. }
  366. }
  367. currentStep->resetP2_s(vn,p);
  368. currentStep->o= ap;
  369. //freeAutoPilot(ap);
  370. return i;
  371. case AXIS_NAMESPACE:
  372. if (ap==NULL)
  373. ap = new AutoPilot(vn);
  374. else
  375. ap->bind(vn);
  376. if (currentStep->nt->testType == NT_NODE)
  377. ap->selectNameSpace((UCSChar *)L"*");
  378. else
  379. ap->selectNameSpace(currentStep->nt->nodeName);
  380. i = 0;
  381. while(ap->iterateNameSpace()!=-1){
  382. if (currentStep->evalPredicates2( vn, p)){
  383. i++;
  384. }
  385. }
  386. currentStep->resetP2_s(vn,p);
  387. currentStep->o= ap;
  388. //freeAutoPilot(ap);
  389. return i;
  390. default:
  391. throw XPathEvalException("unknown state");
  392. return 0;
  393. }
  394. }
  395. int LocationPathExpr::process_ancestor_or_self(VTDNav *vn){
  396. bool b = false, b1= false;
  397. int result;
  398. //int contextSize;
  399. Predicate *t= NULL;
  400. switch ( state) {
  401. case XPATH_EVAL_START:
  402. t = currentStep->p;
  403. while (t != NULL) {
  404. if (t->requireContextSize_p()) {
  405. int i = computeContextSize(t, vn);
  406. if (i == 0) {
  407. b1 = true;
  408. break;
  409. } else
  410. t->setContextSize_p(i);
  411. }
  412. t = t->nextP;
  413. }
  414. if (b1) {
  415. state = XPATH_EVAL_END;
  416. break;
  417. }
  418. state = XPATH_EVAL_END;
  419. vn->push2();
  420. if (currentStep->get_ft()== true){
  421. currentStep->set_ft(false);
  422. if (currentStep->eval_s(vn)) {
  423. if (currentStep->getNextStep() != NULL) {
  424. state = XPATH_EVAL_FORWARD;
  425. currentStep = currentStep->nextS;
  426. break;
  427. } else {
  428. //vn.pop();
  429. state = XPATH_EVAL_TERMINAL;
  430. if (vn->atTerminal)
  431. result = vn->LN;
  432. else
  433. result = vn->getCurrentIndex();
  434. if ( isUnique(result))
  435. return result;
  436. }
  437. }
  438. }
  439. while (vn->toElement(PARENT)) {
  440. if (currentStep->eval_s(vn)) {
  441. if (currentStep->nextS != NULL) {
  442. state = XPATH_EVAL_FORWARD;
  443. currentStep = currentStep->nextS;
  444. break;
  445. } else {
  446. //vn.pop();
  447. state = XPATH_EVAL_TERMINAL;
  448. result = vn->getCurrentIndex();
  449. if ( isUnique(result))
  450. return result;
  451. }
  452. }
  453. }
  454. if ( state == XPATH_EVAL_END) {
  455. currentStep->resetP_s( vn);
  456. vn->pop2();
  457. }
  458. break;
  459. case XPATH_EVAL_FORWARD:
  460. t = currentStep->p;
  461. while (t != NULL) {
  462. if (t->requireContextSize_p()) {
  463. int i = computeContextSize(t, vn);
  464. if (i == 0) {
  465. b1 = true;
  466. break;
  467. } else
  468. t->setContextSize_p(i);
  469. }
  470. t = t->nextP;
  471. }
  472. if (b1) {
  473. currentStep = currentStep->prevS;
  474. state = XPATH_EVAL_BACKWARD;
  475. break;
  476. }
  477. state = XPATH_EVAL_BACKWARD;
  478. vn->push2();
  479. if (currentStep->ft == true) {
  480. currentStep->ft= false;
  481. if (currentStep->eval_s(vn)) {
  482. if (currentStep->nextS != NULL) {
  483. state = XPATH_EVAL_FORWARD;
  484. currentStep = currentStep->nextS;
  485. break;
  486. } else {
  487. //vn.pop();
  488. state = XPATH_EVAL_TERMINAL;
  489. if (vn->atTerminal)
  490. result = vn->LN;
  491. else
  492. result = vn->getCurrentIndex();
  493. if ( isUnique(result))
  494. return result;
  495. }
  496. }
  497. }
  498. while (vn->toElement(PARENT)) {
  499. if (currentStep->eval_s(vn)) {
  500. if (currentStep->nextS != NULL) {
  501. state = XPATH_EVAL_FORWARD;
  502. currentStep = currentStep->nextS;
  503. break;
  504. } else {
  505. //vn.pop();
  506. state = XPATH_EVAL_TERMINAL;
  507. result = vn->getCurrentIndex();
  508. if ( isUnique(result))
  509. return result;
  510. }
  511. }
  512. }
  513. if ( state == XPATH_EVAL_BACKWARD) {
  514. currentStep->resetP_s(vn);
  515. currentStep->ft = true;
  516. vn->pop2();
  517. currentStep = currentStep->prevS;
  518. }
  519. break;
  520. case XPATH_EVAL_END:
  521. currentStep = NULL;
  522. // reset();
  523. return -1;
  524. case XPATH_EVAL_BACKWARD:
  525. b = false;
  526. vn->push2();
  527. while (vn->toElement(PARENT)) {
  528. if (currentStep->eval_s(vn)) {
  529. if (currentStep->nextS != NULL) {
  530. state = XPATH_EVAL_FORWARD;
  531. currentStep = currentStep->nextS;
  532. b = true;
  533. break;
  534. } else {
  535. //vn.pop();
  536. state = XPATH_EVAL_TERMINAL;
  537. result = vn->getCurrentIndex();
  538. if ( isUnique(result))
  539. return result;
  540. }
  541. }
  542. }
  543. if (b == false) {
  544. vn->pop2();
  545. currentStep->resetP_s(vn);
  546. if (currentStep->prevS != NULL) {
  547. currentStep->ft = true;
  548. state = XPATH_EVAL_BACKWARD;
  549. currentStep = currentStep->prevS;
  550. } else {
  551. state = XPATH_EVAL_END;
  552. }
  553. }
  554. break;
  555. case XPATH_EVAL_TERMINAL:
  556. while (vn->toElement(PARENT)) {
  557. if (currentStep->eval_s(vn)) {
  558. result = vn->getCurrentIndex();
  559. if ( isUnique(result))
  560. return result;
  561. }
  562. }
  563. vn->pop2();
  564. currentStep->resetP_s(vn);
  565. if (currentStep->prevS != NULL) {
  566. currentStep->ft = true;
  567. state = XPATH_EVAL_BACKWARD;
  568. currentStep = currentStep->prevS;
  569. }
  570. else {
  571. state = XPATH_EVAL_END;
  572. }
  573. break;
  574. default:
  575. throw XPathEvalException("unknown state");
  576. }
  577. return -2;
  578. }
  579. int LocationPathExpr::process_ancestor(VTDNav *vn){
  580. int result;
  581. bool b = false, b1 = false;
  582. //int contextSize;
  583. Predicate *t= NULL;
  584. switch(state){
  585. case XPATH_EVAL_START:
  586. t = currentStep->p;
  587. while (t != NULL) {
  588. if (t->requireContextSize_p()) {
  589. int i = computeContextSize(t, vn);
  590. if (i == 0) {
  591. b1 = true;
  592. break;
  593. } else
  594. t->setContextSize_p(i);
  595. }
  596. t = t->nextP;
  597. }
  598. if (b1) {
  599. state = XPATH_EVAL_END;
  600. break;
  601. }
  602. state = XPATH_EVAL_END;
  603. if (vn->getCurrentDepth() != -1) {
  604. vn->push2();
  605. while (vn->toElement(PARENT)) {
  606. if (currentStep->eval_s(vn)) {
  607. if (currentStep->nextS != NULL) {
  608. state = XPATH_EVAL_FORWARD;
  609. currentStep = currentStep->nextS;
  610. break;
  611. } else {
  612. //vn.pop();
  613. state = XPATH_EVAL_TERMINAL;
  614. result = vn->getCurrentIndex();
  615. if (isUnique(result))
  616. return result;
  617. }
  618. }
  619. }
  620. if (state == XPATH_EVAL_END) {
  621. currentStep->resetP_s(vn);
  622. vn->pop2();
  623. }
  624. }
  625. break;
  626. case XPATH_EVAL_END:
  627. currentStep =NULL;
  628. // reset();
  629. return -1;
  630. case XPATH_EVAL_FORWARD:
  631. t = currentStep->p;
  632. while(t!=NULL){
  633. if (t->requireContextSize_p()){
  634. int i = computeContextSize(t,vn);
  635. if (i==0){
  636. b1 = true;
  637. break;
  638. }else
  639. t->setContextSize_p(i);
  640. }
  641. t = t->nextP;
  642. }
  643. if (b1){
  644. currentStep = currentStep->prevS;
  645. state = XPATH_EVAL_BACKWARD;
  646. break;
  647. }
  648. state = XPATH_EVAL_BACKWARD;
  649. vn->push2();
  650. while(vn->toElement(PARENT)){
  651. if (currentStep->eval_s(vn)){
  652. if (currentStep->nextS != NULL){
  653. state = XPATH_EVAL_FORWARD;
  654. currentStep = currentStep->nextS;
  655. break;
  656. }
  657. else {
  658. //vn.pop();
  659. state = XPATH_EVAL_TERMINAL;
  660. result = vn->getCurrentIndex();
  661. if ( isUnique(result))
  662. return result;
  663. }
  664. }
  665. }
  666. if ( state== XPATH_EVAL_BACKWARD){
  667. currentStep->resetP_s(vn);
  668. vn->pop2();
  669. currentStep=currentStep->prevS;
  670. }
  671. break;
  672. case XPATH_EVAL_BACKWARD:
  673. b = false;
  674. vn->push2();
  675. while (vn->toElement(PARENT)) {
  676. if (currentStep->eval_s(vn)) {
  677. if (currentStep->nextS!= NULL) {
  678. state = XPATH_EVAL_FORWARD;
  679. currentStep = currentStep->nextS;
  680. b = true;
  681. break;
  682. } else {
  683. //vn.pop();
  684. state = XPATH_EVAL_TERMINAL;
  685. result = vn->getCurrentIndex();
  686. if ( isUnique(result))
  687. return result;
  688. }
  689. }
  690. }
  691. if (b==false){
  692. vn->pop2();
  693. if (currentStep->prevS!=NULL) {
  694. currentStep->resetP_s(vn);
  695. state = XPATH_EVAL_BACKWARD;
  696. currentStep = currentStep->prevS;
  697. }
  698. else {
  699. state = XPATH_EVAL_END;
  700. }
  701. }
  702. break;
  703. case XPATH_EVAL_TERMINAL:
  704. while (vn->toElement(PARENT)) {
  705. if (currentStep->eval_s(vn)) {
  706. result = vn->getCurrentIndex();
  707. if ( isUnique(result))
  708. return result;
  709. }
  710. }
  711. vn->pop2();
  712. if (currentStep->prevS!=NULL) {
  713. currentStep->resetP_s(vn);
  714. state = XPATH_EVAL_BACKWARD;
  715. currentStep = currentStep->prevS;
  716. }
  717. else {
  718. state = XPATH_EVAL_END;
  719. }
  720. break;
  721. default:
  722. throw XPathEvalException("unknown state");
  723. }
  724. return -2;
  725. }
  726. int LocationPathExpr::process_attribute(VTDNav *vn){
  727. AutoPilot *ap = NULL;
  728. bool b1 = false;
  729. Predicate *t= NULL;
  730. int temp;
  731. switch(state){
  732. case XPATH_EVAL_START:
  733. case XPATH_EVAL_FORWARD:
  734. t = currentStep->p;
  735. while(t!=NULL){
  736. if (t->requireContextSize_p()){
  737. int i = computeContextSize(t,vn);
  738. if (i==0){
  739. b1 = true;
  740. break;
  741. }else
  742. t->setContextSize_p(i);
  743. }
  744. t = t->nextP;
  745. }
  746. if (b1){
  747. if (state == XPATH_EVAL_FORWARD){
  748. state= XPATH_EVAL_BACKWARD;
  749. currentStep = currentStep->prevS;
  750. }else
  751. state= XPATH_EVAL_END;
  752. break;
  753. }
  754. if (vn->getAtTerminal()==true){
  755. if (state ==XPATH_EVAL_START)
  756. state = XPATH_EVAL_END;
  757. else {
  758. state = XPATH_EVAL_BACKWARD;
  759. currentStep = currentStep->prevS;
  760. }
  761. } else {
  762. if (currentStep->ft == true) {
  763. if (currentStep->o == NULL)
  764. currentStep->o = ap = new AutoPilot(vn);
  765. else {
  766. ap = currentStep->o;
  767. ap->bind(vn);
  768. }
  769. if (currentStep->nt->testType== NT_NODE)
  770. ap->selectAttr((UCSChar *)L"*");
  771. else if (currentStep->nt->localName != NULL)
  772. ap->selectAttrNS(currentStep->nt->URL,
  773. currentStep->nt->localName);
  774. else
  775. ap->selectAttr(currentStep->nt->nodeName);
  776. currentStep->ft = false;
  777. }
  778. if ( state== XPATH_EVAL_START)
  779. state= XPATH_EVAL_END;
  780. vn->setAtTerminal(true);
  781. while( (temp = ap->iterateAttr2()) != -1){
  782. if (currentStep->evalPredicates(vn)){
  783. break;
  784. }
  785. }
  786. if (temp == -1){
  787. currentStep->ft = true;
  788. currentStep->resetP_s(vn);
  789. vn->setAtTerminal(false);
  790. if ( state== XPATH_EVAL_FORWARD){
  791. state = XPATH_EVAL_BACKWARD;
  792. currentStep = currentStep->prevS;
  793. }
  794. }else {
  795. if (currentStep->nextS != NULL){
  796. vn->LN = temp;
  797. state= XPATH_EVAL_FORWARD;
  798. currentStep = currentStep->nextS;
  799. }
  800. else {
  801. //vn.pop();
  802. state= XPATH_EVAL_TERMINAL;
  803. if ( isUnique(temp)){
  804. vn->LN = temp;
  805. return temp;
  806. }
  807. }
  808. }
  809. }
  810. break;
  811. case XPATH_EVAL_END:
  812. currentStep = NULL;
  813. // reset();
  814. return -1;
  815. case XPATH_EVAL_BACKWARD:
  816. ap = currentStep->o;
  817. //vn.push();
  818. while( (temp = ap->iterateAttr2()) != -1){
  819. if (currentStep->evalPredicates(vn)){
  820. break;
  821. }
  822. }
  823. if (temp == -1) {
  824. currentStep->ft = true;
  825. //freeAutoPilot(currentStep->o);
  826. //currentStep->o = NULL;
  827. currentStep->resetP_s(vn);
  828. vn->setAtTerminal(false);
  829. if (currentStep->prevS != NULL) {
  830. state = XPATH_EVAL_BACKWARD;
  831. currentStep = currentStep->prevS;
  832. } else
  833. state = XPATH_EVAL_END;
  834. } else {
  835. if (currentStep->nextS != NULL) {
  836. state = XPATH_EVAL_FORWARD;
  837. currentStep = currentStep->nextS;
  838. } else {
  839. state = XPATH_EVAL_TERMINAL;
  840. if ( isUnique(temp)){
  841. vn->LN = temp;
  842. return temp;
  843. }
  844. }
  845. }
  846. break;
  847. case XPATH_EVAL_TERMINAL:
  848. ap = currentStep->o;
  849. while( (temp = ap->iterateAttr2()) != -1){
  850. if (currentStep->evalPredicates(vn)){
  851. break;
  852. }
  853. }
  854. if (temp != -1)
  855. if (isUnique(temp)){
  856. vn->LN = temp;
  857. return temp;
  858. }
  859. vn->setAtTerminal(false);
  860. currentStep->resetP_s(vn);
  861. if (currentStep->prevS == NULL) {
  862. currentStep->ft = true;
  863. //freeAutoPilot(currentStep->o);
  864. //currentStep->o = NULL;
  865. state= XPATH_EVAL_END;
  866. } else {
  867. state= XPATH_EVAL_BACKWARD;
  868. currentStep->ft = true;
  869. //freeAutoPilot(currentStep->o);
  870. //currentStep->o = NULL;
  871. currentStep = currentStep->prevS;
  872. }
  873. break;
  874. default:
  875. throw XPathEvalException("unknown state");
  876. }
  877. return -2;
  878. }
  879. int LocationPathExpr::process_child(VTDNav *vn){
  880. int result;
  881. bool b = false, b1 = false;
  882. Predicate *t= NULL;
  883. switch(state){
  884. case XPATH_EVAL_START:
  885. if (currentStep->nt->testType < NT_TEXT){
  886. /* first search for any predicate that
  887. // requires contextSize
  888. // if so, compute its context size
  889. // if size > 0
  890. // set context
  891. // if size ==0
  892. // immediately set the state to backward or end*/
  893. t = currentStep->p;
  894. while(t!=NULL){
  895. if (t->requireContextSize_p()){
  896. int i = computeContextSize(t,vn);
  897. if (i==0){
  898. b1 = true;
  899. break;
  900. }else
  901. t->setContextSize_p(i);
  902. }
  903. t = t->nextP;
  904. }
  905. if (b1){
  906. state= XPATH_EVAL_END;
  907. break;
  908. }
  909. b=vn->toElement(FIRST_CHILD);
  910. state= XPATH_EVAL_END;
  911. if (b == true){
  912. do {
  913. if (currentStep->eval_s(vn)) {
  914. if (currentStep->nextS != NULL){
  915. //currentStep.position++;
  916. state= XPATH_EVAL_FORWARD;
  917. currentStep = currentStep->nextS;
  918. }
  919. else {
  920. state= XPATH_EVAL_TERMINAL;
  921. result = vn->getCurrentIndex();
  922. if ( isUnique(result)){
  923. return result;
  924. }
  925. }
  926. break;
  927. }
  928. } while (vn->toElement(NEXT_SIBLING));
  929. if (state == XPATH_EVAL_END)
  930. vn->toElement(PARENT);
  931. }
  932. }else {
  933. TextIter *ti = NULL;
  934. if (vn->getAtTerminal()==true){
  935. state = XPATH_EVAL_END;
  936. }else {
  937. // compute context size;
  938. t = currentStep->p;
  939. while(t!=NULL){
  940. if (t->requireContextSize_p()){
  941. int i = computeContextSize(t,vn);
  942. if (i==0){
  943. b1 = true;
  944. break;
  945. }else
  946. t->setContextSize_p(i);
  947. }
  948. t = t->nextP;
  949. }
  950. // b1 false indicate context size is zero. no need to go any further...
  951. if (b1){
  952. state = XPATH_EVAL_END;
  953. break;
  954. }
  955. // get textIter
  956. if (currentStep->o != NULL){
  957. ti = (TextIter*) currentStep->o;
  958. } else {
  959. ti = new TextIter();
  960. currentStep->o = (AutoPilot *)ti;
  961. }
  962. selectNodeType(ti);
  963. ti->touch(vn);
  964. state = XPATH_EVAL_END;
  965. while((result = ti->getNext())!=-1){
  966. vn->LN = result;
  967. vn->atTerminal = true;
  968. if (currentStep->evalPredicates(vn)){
  969. break;
  970. }
  971. }
  972. // old code
  973. //result = vn.getText();
  974. if (result != -1){
  975. vn->setAtTerminal(true);
  976. //currentStep.resetP(vn);
  977. vn->LN = result;
  978. if (currentStep->getNextStep() != NULL){
  979. vn->LN = result;
  980. state = XPATH_EVAL_FORWARD;
  981. currentStep = currentStep->getNextStep();
  982. }
  983. else {
  984. //vn.pop();
  985. state = XPATH_EVAL_TERMINAL;
  986. if (isUnique(result)){
  987. vn->LN = result;
  988. return result;
  989. }
  990. }
  991. } else{
  992. //currentStep.set_ft(true);
  993. currentStep->resetP_s(vn);
  994. vn->setAtTerminal( false);
  995. }
  996. }
  997. }
  998. break;
  999. case XPATH_EVAL_END:
  1000. currentStep =NULL;
  1001. // reset();
  1002. return -1;
  1003. case XPATH_EVAL_FORWARD:
  1004. if (currentStep->nt->testType < NT_TEXT){
  1005. t = currentStep->p;
  1006. while(t!=NULL){
  1007. if (t->requireContextSize_p()){
  1008. int i = computeContextSize( t,vn);
  1009. if (i==0){
  1010. b1 = true;
  1011. break;
  1012. }else
  1013. t->setContextSize_p(i);
  1014. }
  1015. t = t->nextP;
  1016. }
  1017. if (b1){
  1018. currentStep = currentStep->prevS;
  1019. state= XPATH_EVAL_BACKWARD;
  1020. break;
  1021. }
  1022. state = XPATH_EVAL_BACKWARD;
  1023. if (vn->toElement(FIRST_CHILD)) {
  1024. do {
  1025. if (currentStep->eval_s(vn)) {
  1026. if (currentStep->nextS != NULL) {
  1027. state= XPATH_EVAL_FORWARD;
  1028. currentStep = currentStep->nextS;
  1029. } else {
  1030. state= XPATH_EVAL_TERMINAL;
  1031. result = vn->getCurrentIndex();
  1032. if ( isUnique(result))
  1033. return result;
  1034. }
  1035. goto forward;
  1036. }
  1037. } while (vn->toElement(NEXT_SIBLING));
  1038. vn->toElement(PARENT);
  1039. currentStep->resetP_s(vn);
  1040. currentStep = currentStep->prevS;
  1041. } else {
  1042. //vn.toElement(VTDNav.P);
  1043. currentStep = currentStep->prevS;
  1044. }
  1045. forward:;
  1046. }else {
  1047. TextIter *ti = NULL;
  1048. // predicate at an attribute is not evaled
  1049. if (vn->getAtTerminal() == true){
  1050. state = XPATH_EVAL_BACKWARD;
  1051. currentStep = currentStep->getPrevStep();
  1052. }else {
  1053. // compute context size;
  1054. t = currentStep->p;
  1055. while(t!=NULL){
  1056. if (t->requireContextSize_p()){
  1057. int i = computeContextSize(t,vn);
  1058. if (i==0){
  1059. b1 = true;
  1060. break;
  1061. }else
  1062. t->setContextSize_p(i);
  1063. }
  1064. t = t->nextP;
  1065. }
  1066. // b1 false indicate context size is zero. no need to go any further...
  1067. if (b1){
  1068. state = XPATH_EVAL_BACKWARD;
  1069. break;
  1070. }
  1071. // get textIter
  1072. if (currentStep->o != NULL){
  1073. ti = (TextIter*) currentStep->o;
  1074. } else {
  1075. ti = new TextIter();
  1076. currentStep->o = (AutoPilot *)ti;
  1077. }
  1078. ti->touch(vn);
  1079. selectNodeType(ti);
  1080. //result = ti.getNext();
  1081. while((result = ti->getNext())!=-1){
  1082. vn->LN = result;
  1083. vn->atTerminal = true;
  1084. if (currentStep->evalPredicates(vn)){
  1085. break;
  1086. }
  1087. }
  1088. if (result == -1) {
  1089. //currentStep.set_ft(true);
  1090. //currentStep.resetP(vn);
  1091. vn->setAtTerminal( false);
  1092. if (state == XPATH_EVAL_FORWARD) {
  1093. state = XPATH_EVAL_BACKWARD;
  1094. currentStep = currentStep->getPrevStep();
  1095. }
  1096. } else {
  1097. vn->setAtTerminal( true);
  1098. if (currentStep->getNextStep() != NULL) {
  1099. vn->LN = result;
  1100. state = XPATH_EVAL_FORWARD;
  1101. currentStep = currentStep->getNextStep();
  1102. } else {
  1103. //vn.pop();
  1104. state = XPATH_EVAL_TERMINAL;
  1105. if (isUnique(result)) {
  1106. vn->LN = result;
  1107. return result;
  1108. }
  1109. }
  1110. }
  1111. }
  1112. }
  1113. break;
  1114. case XPATH_EVAL_BACKWARD:
  1115. if (currentStep->nt->testType < NT_TEXT) {
  1116. b = false;
  1117. while (vn->toElement(NEXT_SIBLING)) {
  1118. if (currentStep->eval_s(vn)) {
  1119. b = true;
  1120. break;
  1121. }
  1122. }
  1123. if (b == true) {
  1124. state= XPATH_EVAL_FORWARD;
  1125. currentStep = currentStep->nextS;
  1126. } else if (currentStep->prevS == NULL){
  1127. currentStep->resetP_s(vn);
  1128. vn->toElement(PARENT);
  1129. state= XPATH_EVAL_END;
  1130. }
  1131. else {
  1132. currentStep->resetP_s(vn);
  1133. state= XPATH_EVAL_BACKWARD;
  1134. vn->toElement(PARENT);
  1135. currentStep = currentStep->prevS;
  1136. }
  1137. }else {
  1138. vn->setAtTerminal(false);
  1139. if (currentStep->prevS == NULL)
  1140. state= XPATH_EVAL_END;
  1141. else {
  1142. state= XPATH_EVAL_BACKWARD;
  1143. currentStep = currentStep->prevS;
  1144. }
  1145. }
  1146. break;
  1147. case XPATH_EVAL_TERMINAL:
  1148. if (currentStep->nt->testType < NT_TEXT) {
  1149. while (vn->toElement(NEXT_SIBLING)) {
  1150. if (currentStep->eval_s(vn)) {
  1151. result = vn->getCurrentIndex();
  1152. if ( isUnique(result))
  1153. return result;
  1154. }
  1155. }
  1156. currentStep->resetP_s(vn);
  1157. if (currentStep->prevS == NULL){
  1158. state= XPATH_EVAL_END;
  1159. vn->toElement(PARENT);
  1160. }
  1161. else {
  1162. vn->toElement(PARENT);
  1163. state= XPATH_EVAL_BACKWARD;
  1164. currentStep = currentStep->prevS;
  1165. }
  1166. }else {
  1167. TextIter* ti = (TextIter*) currentStep->o;
  1168. while ((result= ti->getNext())!=-1) {
  1169. vn->LN = result;
  1170. vn->atTerminal = true;
  1171. if (currentStep->evalPredicates(vn)) {
  1172. if ( isUnique(result))
  1173. return result;
  1174. }
  1175. }
  1176. currentStep->resetP_s( vn);
  1177. vn->setAtTerminal( false);
  1178. if (currentStep->getPrevStep() == NULL)
  1179. state= XPATH_EVAL_END;
  1180. else {
  1181. state= XPATH_EVAL_BACKWARD;
  1182. currentStep = currentStep->getPrevStep();
  1183. }
  1184. ///////////////////////////////
  1185. }
  1186. break;
  1187. default:
  1188. throw XPathEvalException("unknown state");
  1189. }
  1190. return -2;
  1191. }
  1192. int LocationPathExpr::process_DDFP(VTDNav *vn){
  1193. AutoPilot *ap;
  1194. bool b = false, b1 = false;
  1195. Predicate *t= NULL;
  1196. int result;
  1197. UCSChar *helper;
  1198. switch(state){
  1199. case XPATH_EVAL_START:
  1200. case XPATH_EVAL_FORWARD:
  1201. if (vn->atTerminal){
  1202. if (state == XPATH_EVAL_START)
  1203. state= XPATH_EVAL_END;
  1204. else {
  1205. // no need to set_ft to true
  1206. // no need to resetP
  1207. state= XPATH_EVAL_BACKWARD;
  1208. currentStep = currentStep->prevS;
  1209. }
  1210. break;
  1211. }
  1212. t = currentStep->p;
  1213. while(t!=NULL){
  1214. if (t->requireContextSize_p()){
  1215. int i = computeContextSize( t,vn);
  1216. if (i==0){
  1217. b1 = true;
  1218. break;
  1219. }else
  1220. t->setContextSize_p(i);
  1221. }
  1222. t = t->nextP;
  1223. }
  1224. if (b1){
  1225. if (state ==XPATH_EVAL_START)
  1226. state= XPATH_EVAL_END;
  1227. else {
  1228. currentStep = currentStep->prevS;
  1229. state= XPATH_EVAL_BACKWARD;
  1230. }
  1231. break;
  1232. }
  1233. helper = NULL;
  1234. if (currentStep->nt->testType == NT_NAMETEST){
  1235. helper = currentStep->nt->nodeName;
  1236. }else if (currentStep->nt->testType == NT_NODE){
  1237. helper = (UCSChar *) L"*";
  1238. }else
  1239. throw XPathEvalException(
  1240. "can't run descendant following, or following-sibling axis over comment(), pi(), and text()");
  1241. if (currentStep->o == NULL)
  1242. currentStep->o = ap = new AutoPilot(vn);
  1243. else{
  1244. ap = currentStep->o;
  1245. ap->bind(vn);
  1246. }
  1247. if (currentStep->ft == true) {
  1248. if (currentStep->axis_type == AXIS_DESCENDANT_OR_SELF ){
  1249. if (currentStep->nt->testType == NT_NODE)
  1250. ap->setSpecial(true);
  1251. else
  1252. ap->setSpecial(false);
  1253. }
  1254. //currentStep.o = ap = createAutoPilot(vn);
  1255. if (currentStep->axis_type == AXIS_DESCENDANT_OR_SELF)
  1256. ap->selectElement(helper);
  1257. else if (currentStep->axis_type == AXIS_DESCENDANT)
  1258. ap->selectElement_D(helper);
  1259. else if (currentStep->axis_type == AXIS_PRECEDING)
  1260. ap->selectElement_P(helper);
  1261. else
  1262. ap->selectElement_F(helper);
  1263. currentStep->ft = false;
  1264. }
  1265. if ( state== XPATH_EVAL_START)
  1266. state= XPATH_EVAL_END;
  1267. vn->push2(); // not the most efficient. good for now
  1268. //System.out.println(" --++ push in //");
  1269. b = false;
  1270. while(ap->iterate()){
  1271. if (currentStep->evalPredicates(vn)){
  1272. b = true;
  1273. break;
  1274. }
  1275. }
  1276. if (b == false) {
  1277. vn->pop2();
  1278. //System.out.println(" --++ pop in //");
  1279. currentStep->ft = true;
  1280. currentStep->resetP_s(vn);
  1281. if ( state== XPATH_EVAL_FORWARD){
  1282. state = XPATH_EVAL_BACKWARD;
  1283. currentStep = currentStep->prevS;
  1284. }
  1285. } else {
  1286. if (currentStep->nextS != NULL){
  1287. state = XPATH_EVAL_FORWARD;
  1288. currentStep = currentStep->nextS;
  1289. }
  1290. else {
  1291. //vn.pop();
  1292. state = XPATH_EVAL_TERMINAL;
  1293. result = vn->getCurrentIndex();
  1294. if ( isUnique(result))
  1295. return result;
  1296. }
  1297. }
  1298. break;
  1299. case XPATH_EVAL_END:
  1300. currentStep = NULL;
  1301. // reset();
  1302. return -1;
  1303. case XPATH_EVAL_BACKWARD:
  1304. //currentStep = currentStep->prevS;
  1305. ap = currentStep->o;
  1306. //vn.push();
  1307. b = false;
  1308. while(ap->iterate()){
  1309. if (currentStep->evalPredicates(vn)){
  1310. b = true;
  1311. break;
  1312. }
  1313. }
  1314. if (b == false) {
  1315. vn->pop2();
  1316. currentStep->ft = true;
  1317. currentStep->resetP_s(vn);
  1318. //System.out.println(" --++ pop in //");
  1319. if (currentStep->prevS != NULL) {
  1320. state= XPATH_EVAL_BACKWARD;
  1321. currentStep = currentStep->prevS;
  1322. } else
  1323. state= XPATH_EVAL_END;
  1324. } else {
  1325. if (currentStep->nextS != NULL) {
  1326. //vn.push();
  1327. //System.out.println(" --++ push in //");
  1328. state= XPATH_EVAL_FORWARD;
  1329. currentStep = currentStep->nextS;
  1330. } else {
  1331. state= XPATH_EVAL_TERMINAL;
  1332. result = vn->getCurrentIndex();
  1333. if ( isUnique(result))
  1334. return result;
  1335. }
  1336. }
  1337. break;
  1338. case XPATH_EVAL_TERMINAL:
  1339. ap = currentStep->o;
  1340. b = false;
  1341. while (ap->iterate()) {
  1342. if (currentStep->evalPredicates(vn)) {
  1343. b = true;
  1344. break;
  1345. }
  1346. }
  1347. if (b == true) {
  1348. if (currentStep->evalPredicates(vn)) {
  1349. result = vn->getCurrentIndex();
  1350. if (isUnique(result))
  1351. return result;
  1352. }
  1353. } else if (currentStep->prevS == NULL) {
  1354. currentStep->resetP_s(vn);
  1355. vn->pop2();
  1356. state= XPATH_EVAL_END;
  1357. } else {
  1358. vn->pop2();
  1359. currentStep->ft = true;
  1360. currentStep->resetP_s(vn);
  1361. //System.out.println(" --++ pop in //");
  1362. state= XPATH_EVAL_BACKWARD;
  1363. //currentStep.ft = true;
  1364. currentStep = currentStep->prevS;
  1365. }
  1366. break;
  1367. default:
  1368. throw XPathEvalException(
  1369. "unknown state");
  1370. }
  1371. return -2;
  1372. }
  1373. int LocationPathExpr::process_following_sibling(VTDNav *vn){
  1374. bool b = false, b1 = false;
  1375. //int contextSize;
  1376. Predicate *t= NULL;
  1377. int result;
  1378. switch( state){
  1379. case XPATH_EVAL_START:
  1380. case XPATH_EVAL_FORWARD:
  1381. t = currentStep->p;
  1382. while(t!=NULL){
  1383. if (t->requireContextSize_p()){
  1384. int i = computeContextSize( t,vn);
  1385. if (i==0){
  1386. b1 = true;
  1387. break;
  1388. }else
  1389. t->setContextSize_p(i);
  1390. }
  1391. t = t->nextP;
  1392. }
  1393. if (b1){
  1394. if (state == XPATH_EVAL_FORWARD){
  1395. state= XPATH_EVAL_BACKWARD;
  1396. currentStep = currentStep->prevS;
  1397. }else
  1398. state= XPATH_EVAL_END;
  1399. break;
  1400. }
  1401. if ( state== XPATH_EVAL_START)
  1402. state= XPATH_EVAL_END;
  1403. else
  1404. state= XPATH_EVAL_BACKWARD;
  1405. vn->push2();
  1406. while (vn->toElement(NEXT_SIBLING)){
  1407. if (currentStep->eval_s(vn)){
  1408. if (currentStep->nextS!=NULL){
  1409. state= XPATH_EVAL_FORWARD;
  1410. currentStep = currentStep->nextS;
  1411. break;
  1412. } else {
  1413. state= XPATH_EVAL_TERMINAL;
  1414. result = vn->getCurrentIndex();
  1415. if ( isUnique(result))
  1416. return result;
  1417. }
  1418. }
  1419. }
  1420. if ( state== XPATH_EVAL_END){
  1421. currentStep->resetP_s(vn);
  1422. vn->pop2();
  1423. }else if ( state== XPATH_EVAL_BACKWARD){
  1424. currentStep->resetP_s(vn);
  1425. vn->pop2();
  1426. currentStep = currentStep->prevS;
  1427. }
  1428. break;
  1429. case XPATH_EVAL_END:
  1430. currentStep = NULL;
  1431. // reset();
  1432. return -1;
  1433. case XPATH_EVAL_BACKWARD:
  1434. while (vn->toElement(NEXT_SIBLING)){
  1435. if (currentStep->eval_s(vn)){
  1436. if (currentStep->nextS!=NULL){
  1437. state= XPATH_EVAL_FORWARD;
  1438. currentStep = currentStep->nextS;
  1439. b = true;
  1440. break;
  1441. } else {
  1442. state= XPATH_EVAL_TERMINAL;
  1443. result = vn->getCurrentIndex();
  1444. if ( isUnique(result))
  1445. return result;
  1446. }
  1447. }
  1448. }
  1449. if (b==false){
  1450. vn->pop2();
  1451. currentStep->resetP_s(vn);
  1452. if (currentStep->prevS==NULL){
  1453. state= XPATH_EVAL_END;
  1454. }else{
  1455. state= XPATH_EVAL_BACKWARD;
  1456. currentStep = currentStep->prevS;
  1457. }
  1458. }
  1459. break;
  1460. case XPATH_EVAL_TERMINAL:
  1461. while (vn->toElement(NEXT_SIBLING)){
  1462. if (currentStep->eval_s(vn)){
  1463. // state= XPATH_EVAL_TERMINAL;
  1464. result = vn->getCurrentIndex();
  1465. if ( isUnique(result))
  1466. return result;
  1467. }
  1468. }
  1469. vn->pop2();
  1470. currentStep->resetP_s(vn);
  1471. if(currentStep->prevS!=NULL){
  1472. currentStep = currentStep->prevS;
  1473. state= XPATH_EVAL_BACKWARD;
  1474. }else{
  1475. state= XPATH_EVAL_END;
  1476. }
  1477. break;
  1478. default:
  1479. throw XPathEvalException("unknown state");
  1480. }
  1481. return -2;
  1482. }
  1483. int LocationPathExpr::process_parent(VTDNav *vn){
  1484. bool /*b = false,*/ b1 = false;
  1485. Predicate *t= NULL;
  1486. int result;
  1487. switch ( state) {
  1488. case XPATH_EVAL_START:
  1489. case XPATH_EVAL_FORWARD:
  1490. t = currentStep->p;
  1491. while(t!=NULL){
  1492. if (t->requireContextSize_p()){
  1493. int i = computeContextSize(t,vn);
  1494. if (i==0){
  1495. b1 = true;
  1496. break;
  1497. }else
  1498. t->setContextSize_p(i);
  1499. }
  1500. t = t->nextP;
  1501. }
  1502. if (b1){
  1503. if (state == XPATH_EVAL_FORWARD){
  1504. state= XPATH_EVAL_BACKWARD;
  1505. currentStep = currentStep->prevS;
  1506. }else
  1507. state= XPATH_EVAL_END;
  1508. break;
  1509. }
  1510. if (vn->getCurrentDepth() == -1) {
  1511. if ( state== XPATH_EVAL_START)
  1512. state= XPATH_EVAL_END;
  1513. else {
  1514. //vn.pop();
  1515. state= XPATH_EVAL_BACKWARD;
  1516. currentStep = currentStep->prevS;
  1517. }
  1518. } else {
  1519. vn->push2();
  1520. vn->toElement(PARENT); // must return true
  1521. if (currentStep->eval_s(vn)){
  1522. if (currentStep->nextS != NULL) {
  1523. state= XPATH_EVAL_FORWARD;
  1524. currentStep = currentStep->nextS;
  1525. } else {
  1526. state= XPATH_EVAL_TERMINAL;
  1527. result = vn->getCurrentIndex();
  1528. if ( isUnique(result))
  1529. return result;
  1530. }
  1531. }else{
  1532. vn->pop2();
  1533. currentStep->resetP_s(vn);
  1534. if ( state== XPATH_EVAL_START)
  1535. state= XPATH_EVAL_END;
  1536. else {
  1537. state= XPATH_EVAL_BACKWARD;
  1538. currentStep = currentStep->prevS;
  1539. }
  1540. }
  1541. }
  1542. break;
  1543. case XPATH_EVAL_END:
  1544. currentStep = NULL;
  1545. // reset();
  1546. return -1;
  1547. case XPATH_EVAL_BACKWARD:
  1548. case XPATH_EVAL_TERMINAL:
  1549. if (currentStep->prevS == NULL) {
  1550. vn->pop2();
  1551. state= XPATH_EVAL_END;
  1552. break;
  1553. }else {
  1554. vn->pop2();
  1555. state= XPATH_EVAL_BACKWARD;
  1556. currentStep = currentStep->prevS;
  1557. break;
  1558. }
  1559. default:
  1560. throw XPathEvalException("unknown state");
  1561. }
  1562. return -2;
  1563. }
  1564. int LocationPathExpr::process_preceding_sibling(VTDNav *vn){
  1565. bool b = false, b1 = false;
  1566. Predicate *t= NULL;
  1567. int result;
  1568. switch(state){
  1569. case XPATH_EVAL_START:
  1570. case XPATH_EVAL_FORWARD:
  1571. t = currentStep->p;
  1572. while(t!=NULL){
  1573. if (t->requireContextSize_p()){
  1574. int i = computeContextSize(t,vn);
  1575. if (i==0){
  1576. b1 = true;
  1577. break;
  1578. }else
  1579. t->setContextSize_p(i);
  1580. }
  1581. t = t->nextP;
  1582. }
  1583. if (b1){
  1584. if (state == XPATH_EVAL_FORWARD){
  1585. state= XPATH_EVAL_BACKWARD;
  1586. currentStep = currentStep->prevS;
  1587. }else
  1588. state= XPATH_EVAL_END;
  1589. break;
  1590. }
  1591. if ( state== XPATH_EVAL_START)
  1592. state= XPATH_EVAL_END;
  1593. else
  1594. state= XPATH_EVAL_BACKWARD;
  1595. vn->push2();
  1596. while (vn->toElement(PREV_SIBLING)){
  1597. if (currentStep->eval_s(vn)){
  1598. if (currentStep->nextS!=NULL){
  1599. state= XPATH_EVAL_FORWARD;
  1600. currentStep = currentStep->nextS;
  1601. break;
  1602. } else {
  1603. state= XPATH_EVAL_TERMINAL;
  1604. result = vn->getCurrentIndex();
  1605. if ( isUnique(result))
  1606. return result;
  1607. }
  1608. }
  1609. }
  1610. if ( state== XPATH_EVAL_END){
  1611. currentStep->resetP_s(vn);
  1612. vn->pop2();
  1613. }else if ( state== XPATH_EVAL_BACKWARD){
  1614. currentStep->resetP_s(vn);
  1615. vn->pop2();
  1616. currentStep = currentStep->prevS;
  1617. }
  1618. break;
  1619. case XPATH_EVAL_END:
  1620. currentStep = NULL;
  1621. // reset();
  1622. return -1;
  1623. case XPATH_EVAL_BACKWARD:
  1624. while (vn->toElement(PREV_SIBLING)){
  1625. if (currentStep->eval_s(vn)){
  1626. if (currentStep->nextS!=NULL){
  1627. state= XPATH_EVAL_FORWARD;
  1628. currentStep = currentStep->nextS;
  1629. b = true;
  1630. break;
  1631. } else {
  1632. state= XPATH_EVAL_TERMINAL;
  1633. result = vn->getCurrentIndex();
  1634. if ( isUnique(result))
  1635. return result;
  1636. }
  1637. }
  1638. }
  1639. if (b==false){
  1640. vn->pop2();
  1641. currentStep->resetP_s(vn);
  1642. if (currentStep->prevS==NULL){
  1643. state= XPATH_EVAL_END;
  1644. }else{
  1645. state= XPATH_EVAL_BACKWARD;
  1646. currentStep = currentStep->prevS;
  1647. }
  1648. }
  1649. break;
  1650. case XPATH_EVAL_TERMINAL:
  1651. while (vn->toElement(PREV_SIBLING)){
  1652. if (currentStep->eval_s(vn)){
  1653. // state = XPATH_EVAL_TERMINAL;
  1654. result = vn->getCurrentIndex();
  1655. if ( isUnique(result))
  1656. return result;
  1657. }
  1658. }
  1659. vn->pop2();
  1660. if(currentStep->prevS!=NULL){
  1661. currentStep = currentStep->prevS;
  1662. state= XPATH_EVAL_BACKWARD;
  1663. }else{
  1664. state= XPATH_EVAL_END;
  1665. }
  1666. break;
  1667. default:
  1668. throw XPathEvalException("unknown state");
  1669. }
  1670. return -2;
  1671. }
  1672. int LocationPathExpr::process_self(VTDNav *vn){
  1673. bool /*b = false,*/ b1 = false;
  1674. //int contextSize;
  1675. Predicate *t= NULL;
  1676. int result;
  1677. switch( state){
  1678. case XPATH_EVAL_START:
  1679. case XPATH_EVAL_FORWARD:
  1680. t = currentStep->p;
  1681. while(t!=NULL){
  1682. if (t->requireContextSize_p()){
  1683. int i = computeContextSize(t,vn);
  1684. if (i==0){
  1685. b1 = true;
  1686. break;
  1687. }else
  1688. t->setContextSize_p(i);
  1689. }
  1690. t = t->nextP;
  1691. }
  1692. if (b1){
  1693. if (state == XPATH_EVAL_FORWARD){
  1694. state= XPATH_EVAL_BACKWARD;
  1695. currentStep = currentStep->prevS;
  1696. }else
  1697. state= XPATH_EVAL_END;
  1698. break;
  1699. }
  1700. if (currentStep->eval_s(vn)){
  1701. if (currentStep->nextS!=NULL){
  1702. state= XPATH_EVAL_FORWARD;
  1703. currentStep = currentStep->nextS;
  1704. }
  1705. else{
  1706. state= XPATH_EVAL_TERMINAL;
  1707. if (vn->atTerminal == true)
  1708. result = vn->LN;
  1709. else
  1710. result = vn->getCurrentIndex();
  1711. if ( isUnique(result))
  1712. return result;
  1713. }
  1714. }else {
  1715. currentStep->resetP_s(vn);
  1716. if ( state== XPATH_EVAL_START)
  1717. state= XPATH_EVAL_END;
  1718. else
  1719. state= XPATH_EVAL_BACKWARD;
  1720. }
  1721. break;
  1722. case XPATH_EVAL_END:
  1723. currentStep = NULL;
  1724. // reset();
  1725. return -1;
  1726. case XPATH_EVAL_BACKWARD:
  1727. case XPATH_EVAL_TERMINAL:
  1728. if (currentStep->prevS!=NULL){
  1729. state= XPATH_EVAL_BACKWARD;
  1730. currentStep= currentStep->prevS;
  1731. }else{
  1732. state= XPATH_EVAL_END;
  1733. }
  1734. break;
  1735. default:
  1736. throw XPathEvalException("unknown state");
  1737. }
  1738. return -2;
  1739. }
  1740. int LocationPathExpr::process_namespace(VTDNav *vn){
  1741. AutoPilot *ap = NULL;
  1742. bool b1 = false;
  1743. Predicate *t= NULL;
  1744. int temp;
  1745. switch(state){
  1746. case XPATH_EVAL_START:
  1747. case XPATH_EVAL_FORWARD:
  1748. t = currentStep->p;
  1749. while(t!=NULL){
  1750. if (t->requireContextSize_p()){
  1751. int i = computeContextSize(t,vn);
  1752. if (i==0){
  1753. b1 = true;
  1754. break;
  1755. }else
  1756. t->setContextSize_p(i);
  1757. }
  1758. t = t->nextP;
  1759. }
  1760. if (b1){
  1761. if (state == XPATH_EVAL_FORWARD){
  1762. state= XPATH_EVAL_BACKWARD;
  1763. currentStep = currentStep->prevS;
  1764. }else
  1765. state= XPATH_EVAL_END;
  1766. break;
  1767. }
  1768. if (vn->getAtTerminal()==true){
  1769. if (state ==XPATH_EVAL_START)
  1770. state = XPATH_EVAL_END;
  1771. else {
  1772. state = XPATH_EVAL_BACKWARD;
  1773. currentStep = currentStep->prevS;
  1774. }
  1775. } else {
  1776. if (currentStep->ft == true) {
  1777. if (currentStep->o == NULL)
  1778. currentStep->o = ap = new AutoPilot(vn);
  1779. else {
  1780. ap = currentStep->o;
  1781. ap->bind(vn);
  1782. }
  1783. if (currentStep->nt->testType== NT_NODE)
  1784. ap->selectNameSpace((UCSChar *)L"*");
  1785. else
  1786. ap->selectNameSpace(currentStep->nt->nodeName);
  1787. currentStep->ft = false;
  1788. }
  1789. if ( state== XPATH_EVAL_START)
  1790. state= XPATH_EVAL_END;
  1791. vn->push2();
  1792. //vn->setAtTerminal(true);
  1793. while( (temp = ap->iterateNameSpace()) != -1){
  1794. if (currentStep->evalPredicates(vn)){
  1795. break;
  1796. }
  1797. }
  1798. if (temp == -1){
  1799. currentStep->ft = true;
  1800. currentStep->resetP_s(vn);
  1801. vn->setAtTerminal(false);
  1802. if ( state== XPATH_EVAL_FORWARD){
  1803. state = XPATH_EVAL_BACKWARD;
  1804. currentStep = currentStep->prevS;
  1805. }
  1806. }else {
  1807. if (currentStep->nextS != NULL){
  1808. vn->LN = temp;
  1809. state= XPATH_EVAL_FORWARD;
  1810. currentStep = currentStep->nextS;
  1811. }
  1812. else {
  1813. //vn.pop();
  1814. state= XPATH_EVAL_TERMINAL;
  1815. if ( isUnique(temp)){
  1816. vn->LN = temp;
  1817. return temp;
  1818. }
  1819. }
  1820. }
  1821. }
  1822. break;
  1823. case XPATH_EVAL_END:
  1824. currentStep = NULL;
  1825. // reset();
  1826. return -1;
  1827. case XPATH_EVAL_BACKWARD:
  1828. ap = currentStep->o;
  1829. //vn.push();
  1830. while( (temp = ap->iterateNameSpace()) != -1){
  1831. if (currentStep->evalPredicates(vn)){
  1832. break;
  1833. }
  1834. }
  1835. if (temp == -1) {
  1836. vn->pop2();
  1837. currentStep->ft = true;
  1838. //freeAutoPilot(currentStep->o);
  1839. //currentStep->o = NULL;
  1840. currentStep->resetP_s(vn);
  1841. vn->setAtTerminal(false);
  1842. if (currentStep->prevS != NULL) {
  1843. state = XPATH_EVAL_BACKWARD;
  1844. currentStep = currentStep->prevS;
  1845. } else
  1846. state = XPATH_EVAL_END;
  1847. } else {
  1848. if (currentStep->nextS != NULL) {
  1849. state = XPATH_EVAL_FORWARD;
  1850. currentStep = currentStep->nextS;
  1851. } else {
  1852. state = XPATH_EVAL_TERMINAL;
  1853. if ( isUnique(temp)){
  1854. vn->LN = temp;
  1855. return temp;
  1856. }
  1857. }
  1858. }
  1859. break;
  1860. case XPATH_EVAL_TERMINAL:
  1861. ap = currentStep->o;
  1862. while( (temp = ap->iterateNameSpace()) != -1){
  1863. if (currentStep->evalPredicates(vn)){
  1864. break;
  1865. }
  1866. }
  1867. if (temp != -1)
  1868. if (isUnique(temp)){
  1869. vn->LN = temp;
  1870. return temp;
  1871. }
  1872. vn->setAtTerminal(false);
  1873. currentStep->resetP_s(vn);
  1874. if (currentStep->prevS == NULL) {
  1875. currentStep->ft = true;
  1876. //freeAutoPilot(currentStep->o);
  1877. //currentStep->o = NULL;
  1878. vn->pop2();
  1879. state= XPATH_EVAL_END;
  1880. } else {
  1881. state= XPATH_EVAL_BACKWARD;
  1882. vn->pop2();
  1883. currentStep->ft = true;
  1884. //freeAutoPilot(currentStep->o);
  1885. //currentStep->o = NULL;
  1886. currentStep = currentStep->prevS;
  1887. }
  1888. break;
  1889. default:
  1890. throw XPathEvalException(
  1891. "unknown state");
  1892. }
  1893. return -2;
  1894. }
  1895. void LocationPathExpr::selectNodeType(TextIter *ti){
  1896. if (currentStep->nt->testType == NT_TEXT )
  1897. ti->selectText();
  1898. else if (currentStep->nt->testType == NT_COMMENT )
  1899. ti->selectComment();
  1900. else if (currentStep->nt->testType == NT_PI0 )
  1901. ti->selectPI0();
  1902. else {
  1903. ti->selectPI1(currentStep->nt->nodeName);
  1904. }
  1905. }
  1906. // predicate
  1907. Predicate::Predicate():
  1908. d(0),
  1909. count(0),
  1910. nextP(NULL),
  1911. e(NULL)
  1912. {}
  1913. Predicate::~Predicate(){
  1914. if (e!=NULL)
  1915. delete e;
  1916. }
  1917. bool Predicate::eval_p(VTDNav *vn){
  1918. bool b;
  1919. count++; // increment the position
  1920. e->setPosition(count);
  1921. if (e->isNumerical()){
  1922. b = (e->evalNumber(vn)== count);
  1923. }
  1924. else{
  1925. b = e->evalBoolean(vn);
  1926. }
  1927. return b;
  1928. }
  1929. void Predicate::setIndex_p(int i){
  1930. if (i<=0){
  1931. throw XPathEvalException("Invalid index number");
  1932. }
  1933. d = (double) i;
  1934. }
  1935. void Predicate::setContextSize_p(int size){
  1936. e->setContextSize(size);
  1937. }
  1938. bool Predicate::requireContextSize_p(){
  1939. return e->requireContextSize();
  1940. }
  1941. void Predicate::reset_p(VTDNav *vn){
  1942. count = 0;
  1943. e->reset(vn); // is this really needed?
  1944. }
  1945. void Predicate::toString_p( UCSChar *string){
  1946. //String s = "["+expr+"]";
  1947. if (nextP==NULL){
  1948. wprintf(L"[");
  1949. e->toString(string);
  1950. wprintf(L"]");
  1951. } else {
  1952. wprintf(L"[");
  1953. e->toString(string);
  1954. wprintf(L"]");
  1955. nextP->toString_p(string);
  1956. }
  1957. }
  1958. void Predicate::adjust(int n){e->adjust(n);};
  1959. Step::Step():
  1960. nt(NULL),
  1961. p(NULL),
  1962. pt(NULL),
  1963. nextS(NULL),
  1964. position(1),
  1965. prevS(NULL),
  1966. o(NULL),
  1967. ft(true)
  1968. {}
  1969. Step::~Step(){
  1970. Predicate *tmp, *tmp2;
  1971. if (p != NULL){
  1972. tmp = p;
  1973. tmp2 = tmp->nextP;
  1974. while(tmp2!=NULL){
  1975. delete(tmp);
  1976. tmp= tmp2;
  1977. tmp2 = tmp2->nextP;
  1978. }
  1979. delete(tmp);
  1980. }
  1981. if (nt->testType == NT_TEXT){
  1982. if (o!=NULL)
  1983. delete((TextIter *)o);
  1984. }else
  1985. delete((AutoPilot *)o);
  1986. delete(nt);
  1987. }
  1988. void Step::reset_s(VTDNav *vn){
  1989. ft = true;
  1990. resetP_s(vn);
  1991. position =1;
  1992. }
  1993. void Step::resetP_s(VTDNav *vn){
  1994. Predicate *temp = p;
  1995. while(temp!=NULL){
  1996. temp->reset_p(vn);
  1997. temp = temp->nextP;
  1998. }
  1999. }
  2000. void Step::resetP2_s(VTDNav *vn, Predicate *p1){
  2001. Predicate *temp = p;
  2002. while(temp!=p1){
  2003. temp->reset_p(vn);
  2004. temp = temp->nextP;
  2005. }
  2006. }
  2007. NodeTest *Step::getNodeTest(){
  2008. return nt;
  2009. }
  2010. Step *Step::getNextStep(){
  2011. return nextS;
  2012. }
  2013. bool Step::get_ft(){
  2014. return ft;
  2015. }
  2016. void Step::set_ft(bool b){
  2017. ft = b;
  2018. }
  2019. Step *Step::getPrevStep(){
  2020. return prevS;
  2021. }
  2022. void Step::setNodeTest(NodeTest *n){
  2023. nt = n;
  2024. }
  2025. void Step::setPredicate(Predicate *p1){
  2026. p = p1;
  2027. }
  2028. bool Step::eval_s(VTDNav *vn){
  2029. return nt->eval_nt(vn) && evalPredicates(vn);
  2030. }
  2031. bool Step::eval_s2(VTDNav *vn, Predicate *p){
  2032. return nt->eval_nt(vn) && evalPredicates2(vn,p);
  2033. }
  2034. bool Step::evalPredicates(VTDNav *vn){
  2035. Predicate *temp = p;
  2036. while(temp!=NULL) {
  2037. if (temp->eval_p(vn)== false)
  2038. return false;
  2039. temp = temp->nextP;
  2040. }
  2041. return true;
  2042. }
  2043. bool Step::evalPredicates2(VTDNav *vn, Predicate *p){
  2044. Predicate *temp = p;
  2045. while(temp!=p) {
  2046. if (temp->eval_p(vn)== false)
  2047. return false;
  2048. temp = temp->nextP;
  2049. }
  2050. return true;
  2051. }
  2052. void Step::setAxisType(axisType st){
  2053. axis_type = st;
  2054. }
  2055. void Step::toString_s(UCSChar *string){
  2056. //String s;
  2057. if (p == NULL){
  2058. wprintf(axisName(axis_type));
  2059. nt->toString_nt(string);
  2060. }
  2061. else {
  2062. wprintf(axisName(axis_type));
  2063. nt->toString_nt(string);
  2064. wprintf(L" ");
  2065. p->toString_p(string);
  2066. }
  2067. if (nextS == NULL)
  2068. return;
  2069. else {
  2070. wprintf(L"/");
  2071. nextS->toString_s(string);
  2072. }
  2073. }
  2074. void Step::adjust(int n){
  2075. Predicate* temp = p;
  2076. while(temp!=NULL){
  2077. temp->adjust(n);
  2078. temp = temp->nextP;
  2079. }
  2080. };
  2081. NodeTest::NodeTest():
  2082. nodeName(NULL),
  2083. prefix(NULL),
  2084. localName(NULL),
  2085. URL(NULL),
  2086. nsEnabled(false)
  2087. {
  2088. }
  2089. NodeTest::~NodeTest(){
  2090. delete localName;
  2091. delete nodeName;
  2092. delete prefix;
  2093. }
  2094. bool NodeTest::eval_nt(VTDNav *vn){
  2095. if (testType == NT_NODE)
  2096. return true;
  2097. else if(testType == NT_NAMETEST){
  2098. if (vn->atTerminal == true)
  2099. return false;
  2100. if (localName!=NULL)
  2101. return vn->matchElementNS(URL,localName);
  2102. else
  2103. return vn->matchElement(nodeName);
  2104. }
  2105. return true;
  2106. }
  2107. void NodeTest::setNodeName(UCSChar *name){
  2108. nodeName = name;
  2109. }
  2110. void NodeTest::setNodeNameNS(UCSChar *p, UCSChar *ln){
  2111. localName = ln;
  2112. prefix = p;
  2113. }
  2114. void NodeTest::setTestType(nodeTestType ntt){
  2115. testType = ntt;
  2116. }
  2117. void NodeTest::toString_nt(UCSChar *string){
  2118. switch (testType){
  2119. case NT_NAMETEST :
  2120. if (localName == NULL)
  2121. wprintf(L"%ls",nodeName);
  2122. else
  2123. wprintf(L"%ls:%ls", prefix,localName);
  2124. break;
  2125. case NT_NODE: wprintf(L"node()");break;
  2126. case NT_TEXT: wprintf(L"text()");break;
  2127. case NT_PI0: wprintf(L"processing-instruction()");break;
  2128. case NT_PI1: wprintf(L"processing-instruction(");
  2129. if (wcschr(nodeName,'"')!=NULL){
  2130. wprintf(L"'");
  2131. wprintf(nodeName);
  2132. wprintf(L"'");
  2133. }else{
  2134. wprintf(L"\"");
  2135. wprintf(nodeName);
  2136. wprintf(L"\"");
  2137. }
  2138. wprintf(L")");
  2139. break;
  2140. default: wprintf(L"comment()");
  2141. }
  2142. }
  2143. UCSChar *com_ximpleware::axisName(axisType i){
  2144. switch(i){
  2145. case AXIS_CHILD: return (UCSChar *)L"child::";
  2146. case AXIS_DESCENDANT: return (UCSChar *)L"descendant::";
  2147. case AXIS_PARENT: return (UCSChar *)L"parent::";
  2148. case AXIS_FOLLOWING_SIBLING: return (UCSChar *)L"following-sibling::";
  2149. case AXIS_PRECEDING_SIBLING: return (UCSChar *)L"preceding-sibling::";
  2150. case AXIS_FOLLOWING: return (UCSChar *)L"following::";
  2151. case AXIS_PRECEDING: return (UCSChar *)L"preceding::";
  2152. case AXIS_ATTRIBUTE: return (UCSChar *)L"attribute::";
  2153. case AXIS_NAMESPACE: return (UCSChar *)L"namespace::";
  2154. case AXIS_SELF: return (UCSChar *)L"self::";
  2155. case AXIS_DESCENDANT_OR_SELF: return (UCSChar *)L"descendant-or-self::";
  2156. case AXIS_ANCESTOR: return (UCSChar *)L"ancestor::";
  2157. default: return (UCSChar *)L"ancestor-or-self::";
  2158. }
  2159. }