PageRenderTime 63ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/kombilo/sgfparser.cpp

http://eidogo.googlecode.com/
C++ | 1044 lines | 698 code | 159 blank | 187 comment | 292 complexity | 2b876c2068c2e7719a1c43604c261a3a MD5 | raw file
  1. // File: sgfparser.cpp
  2. // part of libkombilo, http://www.u-go.net/kombilo/
  3. // Copyright (c) 2006-7 Ulrich Goertz <u@g0ertz.de>
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. // this software and associated documentation files (the "Software"), to deal in
  6. // the Software without restriction, including without limitation the rights to
  7. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  8. // of the Software, and to permit persons to whom the Software is furnished to do
  9. // so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in all
  12. // copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. // SOFTWARE.
  21. #include "sgfparser.h"
  22. using std::vector;
  23. using std::stack;
  24. using std::pair;
  25. using std::map;
  26. using std::string;
  27. SGFError::SGFError() {}
  28. ExtendedMoveNumber::ExtendedMoveNumber() {
  29. length = 0;
  30. data = 0;
  31. }
  32. ExtendedMoveNumber::ExtendedMoveNumber(int LENGTH, int* DATA) {
  33. length = LENGTH;
  34. if (length) data = new int[length];
  35. else data = 0;
  36. for(int i=0; i<length; i++) data[i] = DATA[i];
  37. }
  38. ExtendedMoveNumber::ExtendedMoveNumber(int D) {
  39. length = 1;
  40. data = new int[1];
  41. data[0] = D;
  42. }
  43. ExtendedMoveNumber::ExtendedMoveNumber(const ExtendedMoveNumber& emn) {
  44. length = emn.length;
  45. if (length) data = new int[length];
  46. else data = 0;
  47. for(int i=0; i<length; i++) data[i] = emn.data[i];
  48. }
  49. ExtendedMoveNumber::~ExtendedMoveNumber() {
  50. if (data) delete [] data;
  51. }
  52. ExtendedMoveNumber& ExtendedMoveNumber::operator=(const ExtendedMoveNumber& emn) {
  53. if (this != &emn) {
  54. length = emn.length;
  55. if (data) delete [] data;
  56. if (length) {
  57. data = new int[length];
  58. for(int i=0; i<length; i++) data[i] = emn.data[i];
  59. } else data = 0;
  60. }
  61. return *this;
  62. }
  63. void ExtendedMoveNumber::next() {
  64. data[length-1]++;
  65. }
  66. void ExtendedMoveNumber::down() throw(SGFError) {
  67. if (length==0) throw SGFError();
  68. else if (length==1) {
  69. int* newdata = new int[3];
  70. newdata[0] = data[0];
  71. newdata[1] = 1;
  72. newdata[2] = 0;
  73. length = 3;
  74. delete [] data;
  75. data = newdata;
  76. } else {
  77. if (data[length-1]) {
  78. int* newdata = new int[length+2];
  79. for(int i=0; i<length; i++) newdata[i] = data[i];
  80. newdata[length] = 1;
  81. newdata[length+1] = 0;
  82. length += 2;
  83. delete [] data;
  84. data = newdata;
  85. } else data[length-2]++;
  86. }
  87. }
  88. int ExtendedMoveNumber::total_move_num() {
  89. int result = 0;
  90. for(int i=0; i<(length+1)/2; i++) result += data[2*i];
  91. return result;
  92. }
  93. char* SGFescape(const char* s) {
  94. char* t = new char[2*strlen(s)+1];
  95. int j = 0;
  96. for(unsigned int i = 0; i<strlen(s); i++) {
  97. if (s[i] == '\\' || s[i] == ']') t[j++]='\\';
  98. t[j++] = s[i];
  99. }
  100. t[j++] = 0;
  101. char* result = new char[j];
  102. strcpy(result, t);
  103. delete t;
  104. return result;
  105. }
  106. vector<string>* parseRootNode(Node* n, vector<string>* tags) throw(SGFError) {
  107. vector<string>* results = new vector<string>(tags->size());
  108. string s = n->SGFstring;
  109. int lSGFstring = s.size();
  110. int i = 0;
  111. while (i < lSGFstring && s[i] != ';' && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  112. i++;
  113. if (i>=lSGFstring || s[i] != ';') throw SGFError();
  114. i++;
  115. while (i < lSGFstring) {
  116. while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  117. i++;
  118. if (i >= lSGFstring) break;
  119. char ID[30];
  120. int IDindex = 0;
  121. while (i < lSGFstring && s[i] != '[' && IDindex < 30) {
  122. if (65 <= s[i] && s[i] <= 90) {
  123. ID[IDindex++] = s[i];
  124. } else if (!(97 <= s[i] && s[i] <= 122) && (!(s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))) {
  125. throw SGFError();
  126. }
  127. i++;
  128. }
  129. i++;
  130. if (i >= lSGFstring || IDindex >= 30 || !IDindex) {
  131. throw SGFError();
  132. }
  133. ID[IDindex] = 0;
  134. char* propValue = new char[lSGFstring+1];
  135. int propValueIndex = 0;
  136. while (i < lSGFstring) {
  137. while (s[i] != ']') {
  138. if (s[i] == '\t') {
  139. propValue[propValueIndex++] = ' ';
  140. i++;
  141. continue;
  142. }
  143. if (s[i] == '\\') {
  144. i++;
  145. if ((s[i]=='\n' && s[i+1]=='\r') || (s[i]=='\r' && s[i+1]=='\n')) {
  146. i += 2;
  147. continue;
  148. }
  149. else if (s[i]=='\n' || s[i]=='\r') {
  150. i++;
  151. continue;
  152. }
  153. }
  154. propValue[propValueIndex++] = s[i];
  155. i++;
  156. if (i >= lSGFstring) {
  157. throw SGFError();
  158. }
  159. }
  160. propValue[propValueIndex++] = ',';
  161. propValue[propValueIndex++] = ' ';
  162. i++;
  163. while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  164. i++;
  165. if (i >= lSGFstring || s[i] != '[') {
  166. propValue[propValueIndex-2] = 0;
  167. string IDstring = ID;
  168. int ctr = 0;
  169. for(vector<string>::iterator it = tags->begin(); it != tags->end(); it++) {
  170. if (IDstring == *it) {
  171. (*results)[ctr] = propValue;
  172. break;
  173. }
  174. ctr++;
  175. }
  176. delete [] propValue;
  177. break;
  178. }
  179. else i++;
  180. }
  181. }
  182. return results;
  183. }
  184. PropValue::PropValue(std::string IDC, std::vector<std::string>* PV) {
  185. IDcomplete = IDC;
  186. pv = PV;
  187. }
  188. PropValue::~PropValue() {
  189. if (pv) delete pv;
  190. }
  191. Node::Node(Node* prev, char* SGFst, int lvl=0) throw(SGFError) {
  192. next = NULL;
  193. previous = prev;
  194. up = NULL;
  195. down = NULL;
  196. numChildren = 0;
  197. level = lvl;
  198. parsed = 0;
  199. if (SGFst) {
  200. SGFstring = SGFst;
  201. // parseNode();
  202. } else SGFstring = "";
  203. posyD = 0;
  204. }
  205. Node::~Node() {
  206. }
  207. string remove_lowercase(string s) throw(SGFError) {
  208. char ID[s.size()+1];
  209. int IDindex = 0;
  210. for(unsigned int i=0; i<s.size(); i++) {
  211. if (65 <= s[i] && s[i] <= 90) ID[IDindex++] = s[i];
  212. else if (!(97 <= s[i] && s[i] <= 122)) {
  213. throw SGFError();
  214. }
  215. }
  216. ID[IDindex] = 0;
  217. return string(ID);
  218. }
  219. vector<string> Node::gpv(const string& prop) {
  220. vector<string>* result = get_property_value(prop);
  221. if (result) return *result;
  222. else return vector<string>();
  223. }
  224. vector<string>* Node::get_property_value(const string& prop) {
  225. if (!parsed) {
  226. parseNode();
  227. }
  228. map<string, PropValue >::iterator result = data.find(remove_lowercase(prop));
  229. if (result == data.end()) return 0;
  230. else return result->second.pv;
  231. }
  232. ExtendedMoveNumber Node::get_move_number() {
  233. vector<int> l;
  234. Node* n = this;
  235. l.push_back(0);
  236. while (n->previous) {
  237. if (n->level) l.push_back(n->level);
  238. else l[l.size()-1]++;
  239. n = n->previous;
  240. }
  241. int* result = new int[l.size()];
  242. for(int i = l.size()-1; i >= 0; i--) {
  243. result[l.size()-i-1] = l[i];
  244. }
  245. ExtendedMoveNumber emn(l.size(), result);
  246. delete [] result;
  247. return emn;
  248. }
  249. void Node::parseNode() throw(SGFError) {
  250. // printf("Parse node, %s\n", SGFstring);
  251. if (!parsed) {
  252. string s = SGFstring;
  253. int lSGFstring = s.size();
  254. int i = 0;
  255. while (i < lSGFstring && s[i] != ';' && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  256. i++;
  257. if (i>=lSGFstring || s[i] != ';') throw SGFError();
  258. i++;
  259. while (i < lSGFstring) {
  260. while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  261. i++;
  262. if (i >= lSGFstring) break;
  263. char ID[30];
  264. int IDindex = 0;
  265. char IDcomplete[100]; // store long property name here
  266. int IDcompleteIndex = 0;
  267. while (i < lSGFstring && s[i] != '[' && IDindex < 30 && IDcompleteIndex < 100) {
  268. if (65 <= s[i] && s[i] <= 90) {
  269. ID[IDindex++] = s[i];
  270. IDcomplete[IDcompleteIndex++] = s[i];
  271. } else if (97 <= s[i] && s[i] <= 122) {
  272. IDcomplete[IDcompleteIndex++] = s[i];
  273. } else if (!(s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t')) {
  274. throw SGFError();
  275. }
  276. i++;
  277. }
  278. i++;
  279. if (i >= lSGFstring || IDindex >= 30 || !IDindex || IDcompleteIndex >= 100) {
  280. throw SGFError();
  281. }
  282. ID[IDindex] = 0;
  283. IDcomplete[IDcompleteIndex] = 0;
  284. vector<string>* propValueList = new vector<string>;
  285. while (i < lSGFstring) {
  286. string propValue;
  287. while (s[i] != ']') {
  288. //printf("i, s[i]: %d, %c\n", i, s[i]);
  289. if (s[i] == '\t') {
  290. propValue += ' ';
  291. i++;
  292. continue;
  293. }
  294. if (s[i] == '\\') {
  295. i++;
  296. if ((s[i]=='\n' && s[i+1]=='\r') || (s[i]=='\r' && s[i+1]=='\n')) {
  297. i += 2;
  298. continue;
  299. }
  300. else if (s[i]=='\n' || s[i]=='\r') {
  301. i++;
  302. continue;
  303. }
  304. }
  305. if (Node::sloppy && (s[i] == '\n' || s[i] == '\r') && \
  306. (!strcmp(ID, "B") || !strcmp(ID, "W") || !strcmp(ID, "AW") || !strcmp(ID, "AB"))) {
  307. i++;
  308. continue;
  309. }
  310. propValue += s[i]; // building propValue in this way could be a performance problem
  311. // maybe we should use reserve before. FIXME
  312. i++;
  313. if (i >= lSGFstring) throw SGFError();
  314. }
  315. if ((!strcmp(ID,"B") || !strcmp(ID,"W")) && !(propValue.size() == 2 || (propValue.size() == 0))) {
  316. throw SGFError();
  317. }
  318. propValueList->push_back(propValue);
  319. i++;
  320. while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  321. i++;
  322. if (i >= lSGFstring || s[i] != '[') break;
  323. else i++;
  324. }
  325. data.insert(make_pair(string(ID), PropValue(string(IDcomplete), propValueList)));
  326. }
  327. parsed = 1;
  328. }
  329. }
  330. void Node::set_property_value(string& IDcomplete, vector<string>* propValue) throw(SGFError) {
  331. string ID = remove_lowercase(IDcomplete);
  332. map<string, PropValue >::iterator it = data.find(ID);
  333. if (it == data.end()) data.insert(make_pair(ID, PropValue(IDcomplete, propValue)));
  334. else it->second.pv->insert(it->second.pv->end(), propValue->begin(), propValue->end());
  335. SGFstring = nodeToString(data);
  336. parsed = 1;
  337. }
  338. int Node::sloppy = 1;
  339. Cursor::Cursor(const char* sgf, int sloppy) throw(SGFError) {
  340. Node::sloppy = sloppy;
  341. height = 0;
  342. width = 0;
  343. posx = 0;
  344. posy = 0;
  345. root = new Node(NULL, NULL, 0);
  346. parse(sgf);
  347. currentN = root->next;
  348. setFlags();
  349. }
  350. Cursor::~Cursor() {
  351. deltree(root);
  352. }
  353. void Cursor::setFlags() {
  354. if (currentN->next) atEnd = 0;
  355. else atEnd = 1;
  356. if (currentN->previous) atStart = 0;
  357. else atStart = 1;
  358. }
  359. void Cursor::parse(const char* s) throw(SGFError) {
  360. Node* curr = root;
  361. int p = -1; // start of the currently parsed node
  362. stack<Node* > c; // stack of nodes from which variations started
  363. stack<int> c_width;
  364. stack<int> c_height;
  365. int height_previous = 0;
  366. int width_currentVar = 0;
  367. char last = ')'; // type of last parsed bracked ('(' or ')')
  368. bool inbrackets = false; // are the currently parsed characters in []'s?
  369. int i = 0; // current parser position
  370. int lSGFstring = strlen(s);
  371. int found_par = 0;
  372. while (i < lSGFstring) {
  373. if (s[i]=='(') {
  374. found_par = i+1;
  375. i++;
  376. continue;
  377. }
  378. if (found_par && s[i]==';') break;
  379. if (found_par && !(s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  380. found_par = 0;
  381. i++;
  382. }
  383. if (i >= lSGFstring) throw SGFError();
  384. i = found_par-1; // found beginning of SGF file
  385. while (i < lSGFstring) {
  386. while (i < lSGFstring && !(s[i]=='(' || s[i]==')' || s[i]=='[' || s[i]==']' || s[i]==';')) i++;
  387. if (i >= lSGFstring) break;
  388. if (inbrackets) {
  389. if (s[i]==']') {
  390. int numberBackslashes = 0;
  391. int j = i-1;
  392. while (s[j] == '\\') {
  393. numberBackslashes++;
  394. j--;
  395. }
  396. if (!(numberBackslashes % 2))
  397. inbrackets = 0;
  398. }
  399. i++;
  400. continue;
  401. }
  402. if (s[i] == '[') inbrackets = 1;
  403. if (s[i] == '(') {
  404. if (last != ')' && p != -1) curr->SGFstring = string(s+p, i-p);
  405. Node* nn = new Node(0,0,0);
  406. nn->previous = curr;
  407. if (++width_currentVar > width) width = width_currentVar;
  408. if (curr->next) {
  409. Node* last = curr->next;
  410. while (last->down) last = last->down;
  411. nn->up = last;
  412. last->down = nn;
  413. nn->level = last->level + 1;
  414. height++;
  415. nn->posyD = height - height_previous;
  416. }
  417. else {
  418. curr->next = nn;
  419. nn->posyD = 0;
  420. height_previous = height;
  421. }
  422. curr->numChildren++;
  423. c.push(curr);
  424. c_width.push(width_currentVar-1);
  425. c_height.push(height);
  426. curr = nn;
  427. p = -1;
  428. last = '(';
  429. }
  430. if (s[i] == ')') {
  431. if (last != ')' && p != -1) {
  432. curr->SGFstring = string(s+p, i-p);
  433. }
  434. if (c.size()) {
  435. curr = c.top();
  436. c.pop();
  437. width_currentVar = c_width.top();
  438. c_width.pop();
  439. height_previous = c_height.top();
  440. c_height.pop();
  441. }
  442. else throw SGFError();
  443. last = ')';
  444. }
  445. if (s[i] == ';') {
  446. if (p != -1) {
  447. curr->SGFstring = string(s+p, i-p);
  448. Node* nn = new Node(0,0,0);
  449. nn->previous = curr;
  450. if (++width_currentVar > width) width = width_currentVar;
  451. nn->posyD = 0;
  452. curr->numChildren = 1;
  453. curr->next = nn;
  454. curr = nn;
  455. }
  456. p = i;
  457. }
  458. i++;
  459. }
  460. if (inbrackets || c.size()) throw SGFError();
  461. Node* n = curr->next;
  462. n->previous = NULL;
  463. n->up = NULL;
  464. while (n->down) {
  465. n = n->down;
  466. n->previous = NULL;
  467. }
  468. }
  469. void Cursor::game(int n) throw(SGFError) {
  470. if (n < root->numChildren) {
  471. posx = 0;
  472. posy = 0;
  473. currentN = root->next;
  474. for(int i=0; i<n; i++) currentN = currentN->down;
  475. setFlags();
  476. }
  477. else throw SGFError();
  478. }
  479. void Cursor::deltree(Node* node) {
  480. Node* n;
  481. if (node->next) {
  482. n = node->next;
  483. while (n->down) {
  484. n = n->down;
  485. deltree(n->up);
  486. }
  487. deltree(n);
  488. }
  489. delete node;
  490. }
  491. void Cursor::delVariation(Node* c) {
  492. if (c->previous) {
  493. delVar(c);
  494. }
  495. else {
  496. if (c->next) {
  497. Node* node = c->next;
  498. while (node->down) {
  499. node = node->down;
  500. delVar(node->up);
  501. }
  502. delVar(node);
  503. }
  504. c->next = 0;
  505. }
  506. setFlags();
  507. }
  508. void Cursor::delVar(Node* node) {
  509. if (node->up) node->up->down = node->down;
  510. else {
  511. node->previous->next = node->down;
  512. }
  513. if (node->down) {
  514. node->down->up = node->up;
  515. node->down->posyD = node->posyD;
  516. Node* n = node->down;
  517. while (n) {
  518. n->level--;
  519. n = n->down;
  520. }
  521. }
  522. int h = 0;
  523. Node* n = node;
  524. while (n->next) {
  525. n = n->next;
  526. while (n->down) {
  527. n = n->down;
  528. h += n->posyD;
  529. }
  530. }
  531. if (node->up || node->down) h++;
  532. Node* p = node->previous;
  533. p->numChildren--;
  534. while (p) {
  535. if (p->down) p->down->posyD -= h;
  536. p = p->previous;
  537. }
  538. height -= h;
  539. // p = node->down;
  540. deltree(node);
  541. // node = 0;
  542. }
  543. void Cursor::add(char* st) {
  544. Node* node = new Node(currentN,st,0);
  545. node->down = 0;
  546. node->next = 0;
  547. node->numChildren = 0;
  548. if (!currentN->next) {
  549. // printf("new %s at %s\n", node->SGFstring, currentN->SGFstring);
  550. node->level = 0;
  551. node->posyD = 0;
  552. node->up = 0;
  553. currentN->next = node;
  554. currentN->numChildren = 1;
  555. }
  556. else {
  557. // printf("adding %s at %s\n", node->SGFstring, currentN->SGFstring);
  558. Node* n = currentN->next;
  559. while (n->down) {
  560. n = n->down;
  561. posy+=n->posyD;
  562. }
  563. n->down = node;
  564. node->up = n;
  565. node->level = n->level + 1;
  566. node->next= 0;
  567. currentN->numChildren++;
  568. node->posyD = 1;
  569. while (n->next) {
  570. n = n->next;
  571. while (n->down) {
  572. n = n->down;
  573. node->posyD += n->posyD;
  574. }
  575. }
  576. posy += node->posyD;
  577. height++;
  578. n = node;
  579. while (n->previous) {
  580. n = n->previous;
  581. if (n->down) n->down->posyD++;
  582. }
  583. }
  584. currentN = node;
  585. posx++;
  586. setFlags();
  587. if (posx > width) width++;
  588. }
  589. void Cursor::next(int n) throw(SGFError) {
  590. if (n >= currentN->numChildren) {
  591. throw SGFError();
  592. }
  593. posx++;
  594. currentN = currentN->next;
  595. for (int i=0; i<n; i++) {
  596. currentN = currentN->down;
  597. posy += currentN->posyD;
  598. }
  599. setFlags();
  600. }
  601. void Cursor::previous() throw(SGFError) {
  602. if (currentN->previous) {
  603. while (currentN->up) {
  604. posy -= currentN->posyD;
  605. currentN = currentN->up;
  606. }
  607. currentN = currentN->previous;
  608. posx--;
  609. }
  610. else throw SGFError();
  611. setFlags();
  612. }
  613. Node* Cursor::getRootNode(int n) throw(SGFError) {
  614. if (!root) return 0;
  615. if (n >= root->numChildren) throw SGFError();
  616. Node* nn = root->next;
  617. for(int i=0; i<n; i++) nn = nn->down;
  618. if (!nn->parsed) nn->parseNode();
  619. return nn;
  620. }
  621. // void Cursor::updateRootNode(PyObject* data, int n) throw(SGFError) {
  622. // if (n >= root->numChildren) throw SGFError();
  623. // Node* nn = root->next;
  624. // for(int i=0; i<n; i++) nn = nn->down;
  625. // delete[] nn->SGFstring;
  626. // nn->SGFstring = rootNodeToString(data);
  627. // Py_DECREF(nn->data);
  628. // if (!(nn->data=PyDict_New())) throw SGFError();
  629. // nn->parsed = 0;
  630. // nn->parseNode();
  631. // }
  632. // char* Cursor::rootNodeToString(PyObject* data) {
  633. // char result[10000]; // FIXME check whether this is exceeded, on the way
  634. // result[0] = 0;
  635. // strcat(result, ";");
  636. //
  637. // PyObject* item;
  638. // if ((item=PyDict_GetItem(data, PyString_FromString("GM")))) {
  639. // strcat(result, "GM[");
  640. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  641. // strcat(result, t);
  642. // delete[] t;
  643. // strcat(result, "]\n");
  644. // }
  645. // if ((item=PyDict_GetItem(data, PyString_FromString("FF")))) {
  646. // strcat(result, "FF[");
  647. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  648. // strcat(result, t);
  649. // delete[] t;
  650. // strcat(result, "]\n");
  651. // }
  652. // if ((item=PyDict_GetItem(data, PyString_FromString("SZ")))) {
  653. // strcat(result, "SZ[");
  654. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  655. // strcat(result, t);
  656. // delete[] t;
  657. // strcat(result, "]\n");
  658. // }
  659. // if ((item=PyDict_GetItem(data, PyString_FromString("PW")))) {
  660. // strcat(result, "PW[");
  661. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  662. // strcat(result, t);
  663. // delete[] t;
  664. // strcat(result, "]\n");
  665. // }
  666. // if ((item=PyDict_GetItem(data, PyString_FromString("WR")))) {
  667. // strcat(result, "WR[");
  668. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  669. // strcat(result, t);
  670. // delete[] t;
  671. // strcat(result, "]\n");
  672. // }
  673. // if ((item=PyDict_GetItem(data, PyString_FromString("PB")))) {
  674. // strcat(result, "PB[");
  675. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  676. // strcat(result, t);
  677. // delete[] t;
  678. // strcat(result, "]\n");
  679. // }
  680. // if ((item=PyDict_GetItem(data, PyString_FromString("BR")))) {
  681. // strcat(result, "BR[");
  682. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  683. // strcat(result, t);
  684. // delete[] t;
  685. // strcat(result, "]\n");
  686. // }
  687. // if ((item=PyDict_GetItem(data, PyString_FromString("EV")))) {
  688. // strcat(result, "EV[");
  689. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  690. // strcat(result, t);
  691. // delete[] t;
  692. // strcat(result, "]\n");
  693. // }
  694. // if ((item=PyDict_GetItem(data, PyString_FromString("RO")))) {
  695. // strcat(result, "RO[");
  696. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  697. // strcat(result, t);
  698. // delete[] t;
  699. // strcat(result, "]\n");
  700. // }
  701. // if ((item=PyDict_GetItem(data, PyString_FromString("DT")))) {
  702. // strcat(result, "DT[");
  703. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  704. // strcat(result, t);
  705. // delete[] t;
  706. // strcat(result, "]\n");
  707. // }
  708. // if ((item=PyDict_GetItem(data, PyString_FromString("PC")))) {
  709. // strcat(result, "PC[");
  710. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  711. // strcat(result, t);
  712. // delete[] t;
  713. // strcat(result, "]\n");
  714. // }
  715. // if ((item=PyDict_GetItem(data, PyString_FromString("KM")))) {
  716. // strcat(result, "KM[");
  717. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  718. // strcat(result, t);
  719. // delete[] t;
  720. // strcat(result, "]\n");
  721. // }
  722. // if ((item=PyDict_GetItem(data, PyString_FromString("RE")))) {
  723. // strcat(result, "RE[");
  724. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  725. // strcat(result, t);
  726. // delete[] t;
  727. // strcat(result, "]\n");
  728. // }
  729. // if ((item=PyDict_GetItem(data, PyString_FromString("US")))) {
  730. // strcat(result, "US[");
  731. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  732. // strcat(result, t);
  733. // delete[] t;
  734. // strcat(result, "]\n");
  735. // }
  736. // if ((item=PyDict_GetItem(data, PyString_FromString("GC")))) {
  737. // strcat(result, "GC[");
  738. // char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
  739. // strcat(result, t);
  740. // delete[] t;
  741. // strcat(result, "]\n");
  742. // }
  743. //
  744. // int l = 0;
  745. //
  746. // PyObject *key, *value;
  747. // int pos = 0;
  748. //
  749. // while (PyDict_Next(data, &pos, &key, &value)) {
  750. // char* s = PyString_AsString(key);
  751. // if (strcmp(s, "GM") && strcmp(s, "FF") && strcmp(s, "SZ") && strcmp(s, "PW") && strcmp(s, "WR") &&
  752. // strcmp(s, "PB") && strcmp(s, "BR") && strcmp(s, "EV") && strcmp(s, "RO") && strcmp(s, "DT") &&
  753. // strcmp(s, "PC") && strcmp(s, "KM") && strcmp(s, "RE") && strcmp(s, "US") && strcmp(s, "GC")) {
  754. //
  755. // strcat(result, s);
  756. //
  757. // for(int k = 0; k < PyList_Size(value); k++) {
  758. // PyObject* item = PyList_GetItem(value, k);
  759. // char* t = SGFescape(PyString_AsString(item));
  760. // strcat(result, "[");
  761. // strcat(result, t);
  762. // strcat(result, "]");
  763. // l += strlen(t) + 2;
  764. // delete[] t;
  765. // if (l>72) {
  766. // strcat(result, "\n");
  767. // l = 0;
  768. // }
  769. // }
  770. // }
  771. // }
  772. // strcat(result, "\n");
  773. // char* t = new char[strlen(result)+1];
  774. // strcpy(t, result);
  775. // return t;
  776. // }
  777. string nodeToString(map<string, PropValue >& data) throw(SGFError) {
  778. string result = ";";
  779. int l = 0;
  780. for(map<string, PropValue >::iterator kv = data.begin(); kv != data.end(); kv++) {
  781. if (!kv->second.pv || !kv->second.pv->size()) continue;
  782. result += kv->second.IDcomplete;
  783. for(vector<string>::iterator it = kv->second.pv->begin(); it != kv->second.pv->end(); it++) {
  784. char* t = SGFescape(it->c_str());
  785. result += "[";
  786. result += t;
  787. result += "]";
  788. l += strlen(t) + 2;
  789. delete [] t;
  790. if (l>72) {
  791. result += '\n';
  792. l = 0;
  793. }
  794. }
  795. }
  796. result += '\n';
  797. return result;
  798. }
  799. char* Cursor::outputVar(Node* node) {
  800. int s = 1000;
  801. char* result = new char[s];
  802. result[0] = 0;
  803. if ((int)(node->SGFstring.size() + strlen(result)) >= s-5) {
  804. s += 1000 + node->SGFstring.size();
  805. char* res = new char[s];
  806. strcpy(res, result);
  807. delete [] result;
  808. result = res;
  809. }
  810. strcat(result, node->SGFstring.c_str());
  811. // printf("%s\n", node->SGFstring);
  812. while (node->next) {
  813. node = node->next;
  814. if (node->down) {
  815. strcat(result, "(");
  816. char* r = outputVar(node);
  817. if ((int)(strlen(r) + strlen(result)) >= s-5) {
  818. s += 1000 + strlen(r);
  819. char* res = new char[s];
  820. strcpy(res, result);
  821. delete [] result;
  822. result = res;
  823. }
  824. strcat(result, r);
  825. delete [] r;
  826. while(node->down) {
  827. node = node->down;
  828. strcat(result, ")(");
  829. char* r = outputVar(node);
  830. if ((int)(strlen(r) + strlen(result)) >= s-5) {
  831. s += 1000 + strlen(r);
  832. char* res = new char[s];
  833. strcpy(res, result);
  834. delete [] result;
  835. result = res;
  836. }
  837. strcat(result, r);
  838. delete [] r;
  839. }
  840. strcat(result, ")");
  841. break;
  842. }
  843. else {
  844. if ((int)(node->SGFstring.size() + strlen(result)) >= s) {
  845. s += 1000 + node->SGFstring.size();
  846. char* res = new char[s];
  847. strcpy(res, result);
  848. delete [] result;
  849. result = res;
  850. }
  851. strcat(result, node->SGFstring.c_str());
  852. // printf("%s\n", node->SGFstring);
  853. }
  854. }
  855. // printf("r: %d \n", strlen(result));
  856. char* t = new char[strlen(result)+1];
  857. strcpy(t, result);
  858. delete [] result;
  859. return t;
  860. }
  861. char* Cursor::output() {
  862. int s = 2000;
  863. char* result = new char[s];
  864. result[0] = 0;
  865. Node* n = root->next;
  866. while (n) {
  867. char* t = outputVar(n);
  868. if ((int)(strlen(t) + strlen(result)) >= s-5) {
  869. s += 2000 + strlen(t);
  870. char* res = new char[s];
  871. strcpy(res, result);
  872. delete [] result;
  873. result = res;
  874. }
  875. strcat(result, "(");
  876. strcat(result, t);
  877. strcat(result, ")\n");
  878. delete [] t;
  879. n = n->down;
  880. }
  881. char* t = new char[strlen(result)+1];
  882. strcpy(t, result);
  883. delete [] result;
  884. return t;
  885. }