//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PBook::StripOpcode: // Strips the specified opcode from every position in the book. // Only the first occurrence of an opcode is removed for any position, // but opcodes are not supposed to occur more than once anyway. // Returns the number of positions where an opcode was removed. uint PBook::StripOpcode (const char * opcode) { char * searchCode = new char [strLength(opcode) + 2]; strCopy (searchCode, opcode); strAppend (searchCode, " "); DString dstr; uint countFound = 0; for (uint i=0; i < NodeListCount; i++) { bookNodeT * node = NodeList[i]; if (node == NULL) { continue; } const char * s = node->data.comment; int startIndex = -1; int index = 0; // Look for a line with a matching opcode: while (*s != 0) { while (*s == '\n' || *s == ' ') { s++; index++; } if (strIsPrefix (searchCode, s)) { startIndex = index; countFound++; break; } while (*s != 0 && *s != '\n') { s++; index++; } } if (startIndex > -1) { s = node->data.comment; index = 0; // Add all characters before the line to be stripped: dstr.Clear(); while (index < startIndex) { dstr.AddChar (s[index]); index++; } // Now find the end of this line: s = &(s[startIndex + 1]); while (*s != 0 && *s != '\n') { s++; } if (*s == '\n') { s++; } while (*s != 0) { dstr.AddChar (*s); s++; } delete[] node->data.comment; node->data.comment = strDuplicate (dstr.Data()); } } delete[] searchCode; return countFound; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PBook::ReadFile(): read in a file. errorT PBook::ReadFile () { ASSERT (FileName != NULL); ReadOnly = false; MFile fp; if (fp.Open (FileName, FMODE_Both) != OK) { ReadOnly = true; if (fp.Open (FileName, FMODE_ReadOnly) != OK) { return ERROR_FileOpen; } } LineCount = 1; Position * pos = new Position; DString * line = new DString; ReadLine(line, &fp); DString dstr; while (line->Length() || ! fp.EndOfFile()) { if (pos->ReadFromFEN (line->Data()) != OK) { fprintf (stderr, "Error reading line: %u\n", LineCount); LineCount++; line->Clear(); ReadLine(line, &fp); continue; //exit (1); } char * s = (char *) line->Data(); // Skip over first four fields, which were the position: while (*s == ' ') { s++; } for (uint i=0; i < 4; i++) { while (*s != ' ' && *s != 0) { s++; } while (*s == ' ') { s++; } } // Now process each field in turn: while (*s == ';' || *s == ' ') { s++; } dstr.Clear(); while (*s != 0) { while (*s == ';' || *s == ' ') { s++; } bool seenCode = false; while (*s != ';' && *s != 0) { seenCode = true; char ch = *s; // Check for backslash (escape) character: if (ch == '\\') { s++; ch = *s; // "\s" -> semicolon within a field: if (ch == 's') { ch = ';'; } } dstr.AddChar (ch); s++; } if (seenCode) { dstr.AddChar ('\n'); } } if (Insert (pos, dstr.Data()) != OK) { //fprintf (stderr, "Warning: position already exists! Line %u\n", // LineCount); } LineCount++; line->Clear(); ReadLine(line, &fp); } delete pos; delete line; Altered = false; NextIndex = NodeListCount - 1; return OK; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PBook::ReadEcoFile(): // Read an ECO (not EPD) format file. errorT PBook::ReadEcoFile () { MFile fp; if (fp.Open (FileName, FMODE_ReadOnly) != OK) { return ERROR_FileOpen; } ReadOnly = true; LineCount = 1; Position std_start; std_start.StdStart(); DString text; DString moves; ecoStringT ecoStr; ecoT ecoCode; int ch; errorT err = OK; bool done = false; // Loop to read in and add all positions: while (!done) { // Find the next ECO code: while (true) { ch = fp.ReadOneByte(); if (ch == EOF) { done = true; break; } if (ch == '\n') { LineCount++; } if (ch >= 'A' && ch <= 'E') { break; } if (ch == '#') { while (ch != '\n' && ch != EOF) { ch = fp.ReadOneByte(); } if (ch == EOF) { done = true; } LineCount++; } } if (done) { break; } // Read in the rest of the ECO code: ecoStr[0] = ch; ch = fp.ReadOneByte(); if (ch < '0' || ch > '9') { goto corrupt; } ecoStr[1] = ch; ch = fp.ReadOneByte(); if (ch < '0' || ch > '9') { goto corrupt; } ecoStr[2] = ch; ecoStr[3] = 0; // Now check for optional extra part of code, e.g. "A00a1": ch = fp.ReadOneByte(); if (ch >= 'a' && ch <= 'z') { ecoStr[3] = ch; ecoStr[4] = 0; ch = fp.ReadOneByte(); if (ch >= '1' && ch <= '4') { ecoStr[4] = ch; ecoStr[5] = 0; } } // Now put ecoCode in the text string and read the text in quotes: ecoCode = eco_FromString (ecoStr); eco_ToExtendedString (ecoCode, ecoStr); text.Clear(); text.Append ("eco ", ecoStr, " ["); // Find the start of the text: while ((ch = fp.ReadOneByte()) != '"') { if (ch == EOF) { goto corrupt; } } while ((ch = fp.ReadOneByte()) != '"') { if (ch == EOF) { goto corrupt; } text.AddChar ((char) ch); } text.Append ("]\n"); // Now read the position: moves.Clear(); char prev = 0; while ((ch = fp.ReadOneByte()) != '*') { if (ch == EOF) { goto corrupt; } if (ch == '\n') { ch = ' '; LineCount++; } if (ch != ' ' || prev != ' ') { moves.AddChar ((char) ch); } prev = ch; } Position pos (std_start); err = pos.ReadLine (moves.Data()); if (err != OK) { goto corrupt; } text.Append ("moves ", strTrimLeft (moves.Data()), "\n"); if (Insert (&pos, text.Data()) != OK) { // Position already exists: just ignore it. } } return OK; corrupt: return ERROR_Corrupt; }