bool LoadCHKD(Puzzle * puz, const std::string & data) { std::istringstream stream(data); istream_wrapper f(stream); std::string::const_iterator it = data.begin(); for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { if (f.ReadChar() != 0) square->AddFlag(FLAG_CORRECT); } if (! f.CheckEof()) return false; return true; }
void LoadPuz(Puzzle * puz, const std::string & filename, void * /* dummy */) { std::ifstream stream(filename.c_str(), std::ios::in | std::ios::binary); if (stream.fail()) throw FileError(filename); istream_wrapper f(stream); const unsigned short c_primary = f.ReadShort(); if (strcmp(f.ReadString(12).c_str(), "ACROSS&DOWN") != 0) throw FileTypeError("puz"); const unsigned short c_cib = f.ReadShort(); unsigned char c_masked[8]; f.ReadCharArray(c_masked, 8); // Version is "[major].[minor]\0" // We can read puzzles of 1.[anything] std::string versionstr = f.ReadString(4); if (versionstr[0] != '1' || ! isdigit(versionstr[2])) throw LoadError("Unknown puz version."); const unsigned short version = 10 + versionstr[2] - 0x30; f.Skip(2); // 1 unknown short const unsigned short c_grid = f.ReadShort(); f.Skip(2 * 6); // 6 noise shorts const unsigned char width = f.ReadChar(); const unsigned char height = f.ReadChar(); const unsigned short num_clues = f.ReadShort(); const unsigned short grid_type = f.ReadShort(); const unsigned short grid_flag = f.ReadShort(); puz->GetGrid().SetCksum(c_grid); puz->GetGrid().SetType(grid_type); puz->GetGrid().SetFlag(grid_flag); puz->GetGrid().SetSize(width, height); // Read user text and solution std::string solution = f.ReadString(width * height); std::string text = f.ReadString(width * height); // Set the grid's solution and text std::string::iterator sol_it = solution.begin(); std::string::iterator text_it = text.begin(); for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { // Solution if (*sol_it == '.' || *sol_it == ':' && puz->IsDiagramless()) square->SetSolution(puz::Square::Black); else if (*sol_it == '-') square->SetSolution(puz::Square::Blank); else square->SetSolution(decode_puz(std::string(1, *sol_it))); ++sol_it; // Text if (square->IsBlack() && ! puz->IsDiagramless()) square->SetText(puz::Square::Black); else if (*text_it == '-' || *text_it == 0) square->SetText(puz::Square::Blank); else if (puz->IsDiagramless() && (*text_it == '.' || *text_it == ':')) { // Black squares in a diagramless puzzle. if (*text_it == '.') square->SetText(puz::Square::Black); else if (*text_it == ':') square->SetText(puz::Square::Blank); } else { square->SetText(decode_puz(std::string(1, *text_it))); if (islower(*text_it)) square->AddFlag(FLAG_PENCIL); } ++text_it; } assert(sol_it == solution.end() && text_it == text.end()); puz->NumberGrid(); // General puzzle info puz->SetTitle(decode_puz(f.ReadString())); puz->SetAuthor(decode_puz(f.ReadString())); puz->SetCopyright(decode_puz(f.ReadString())); // Clues std::vector<string_t> clues; clues.reserve(num_clues); // Save unaltered clues for the checksums std::vector<std::string> cksum_clues; cksum_clues.reserve(num_clues); for (size_t i = 0; i < num_clues; ++i) { cksum_clues.push_back(f.ReadString()); clues.push_back(escape_xml(decode_puz(cksum_clues.back()))); } puz->SetAllClues(clues); // Notes std::string notes = f.ReadString(); puz->SetNotes(escape_xml(decode_puz(notes))); puz->SetOk(true); // Try to load the extra sections (i.e. GEXT, LTIM, etc). try { LoadSections(puz, f); } catch (std::ios::failure &) { // EOF here doesn't matter. } // Don't even bother with the checksums, since we check the validity // of the puzzle anyways }