| | 45 | |
| | 46 | SnapshotVector::SnapshotVector() : vector<unsigned char>() { |
| | 47 | current = begin(); |
| | 48 | } |
| | 49 | |
| | 50 | SnapshotVector::SnapshotVector(char* c, int size) : vector<unsigned char>() { |
| | 51 | for(int i=0; i<size; i++) push_back(c[i]); |
| | 52 | current = begin(); |
| | 53 | } |
| | 54 | |
| | 55 | void SnapshotVector::pb_int(int d) { |
| | 56 | for(int i = 0; i < 4; i++) { |
| | 57 | push_back((unsigned char)(d % 256)); |
| | 58 | d = d >> 8; |
| | 59 | } |
| | 60 | } |
| | 61 | |
| | 62 | void SnapshotVector::pb_charp(char* c, int size) { |
| | 63 | pb_int(size); |
| | 64 | for(int i=0; i<size; i++) push_back(c[i]); |
| | 65 | } |
| | 66 | |
| | 67 | void SnapshotVector::pb_intp(int* p, int size) { |
| | 68 | pb_int(size); |
| | 69 | for(int i=0; i<size; i++) pb_int(p[i]); |
| | 70 | } |
| | 71 | |
| | 72 | void SnapshotVector::pb_string(string s) { |
| | 73 | pb_int(s.size()+1); |
| | 74 | for(unsigned int i=0; i<s.size(); i++) push_back(s[i]); |
| | 75 | push_back(0); |
| | 76 | } |
| | 77 | |
| | 78 | void SnapshotVector::pb_char(char c) { |
| | 79 | push_back(c); |
| | 80 | } |
| | 81 | |
| | 82 | int SnapshotVector::retrieve_int() { |
| | 83 | int result = 0; |
| | 84 | for(int i=0; i<4; i++) { |
| | 85 | result += *current << (i*8); |
| | 86 | current++; |
| | 87 | } |
| | 88 | return result; |
| | 89 | } |
| | 90 | |
| | 91 | int* SnapshotVector::retrieve_intp() { |
| | 92 | int sz = retrieve_int(); |
| | 93 | int* result = new int[sz]; |
| | 94 | for(int i=0; i<sz; i++) |
| | 95 | result[i] = retrieve_int(); |
| | 96 | return result; |
| | 97 | } |
| | 98 | |
| | 99 | char SnapshotVector::retrieve_char() { |
| | 100 | char c = *current; |
| | 101 | current++; |
| | 102 | return c; |
| | 103 | } |
| | 104 | |
| | 105 | char* SnapshotVector::retrieve_charp() { |
| | 106 | int sz = retrieve_int(); |
| | 107 | char* result = new char[sz]; |
| | 108 | for(int i=0; i<sz; i++) { |
| | 109 | result[i] = *current; |
| | 110 | current++; |
| | 111 | } |
| | 112 | return result; |
| | 113 | } |
| | 114 | |
| | 115 | string SnapshotVector::retrieve_string() { |
| | 116 | char* cp = retrieve_charp(); |
| | 117 | string s(cp); |
| | 118 | delete [] cp; |
| | 119 | return s; |
| | 120 | } |
| | 121 | |
| | 122 | char* SnapshotVector::to_charp() { |
| | 123 | char* result = new char[size()]; |
| | 124 | int counter = 0; |
| | 125 | for(SnapshotVector::iterator it = begin(); it != end(); it++) result[counter++] = *it; |
| | 126 | return result; |
| | 127 | } |
| | 128 | |
| | 429 | } |
| | 430 | |
| | 431 | Pattern::Pattern(SnapshotVector& snv) { |
| | 432 | flip = snv.retrieve_int(); |
| | 433 | colorSwitch = snv.retrieve_int(); |
| | 434 | left = snv.retrieve_int(); |
| | 435 | right = snv.retrieve_int(); |
| | 436 | top = snv.retrieve_int(); |
| | 437 | bottom = snv.retrieve_int(); |
| | 438 | boardsize = snv.retrieve_int(); |
| | 439 | sizeX = snv.retrieve_int(); |
| | 440 | sizeY = snv.retrieve_int(); |
| | 441 | if (snv.retrieve_char()) { // contLabels? |
| | 442 | contLabels = snv.retrieve_charp(); |
| | 443 | } else contLabels = 0; |
| | 444 | initialPos = snv.retrieve_charp(); |
| | 445 | finalPos = snv.retrieve_charp(); |
| | 446 | |
| | 447 | int size = snv.retrieve_int(); |
| | 448 | for(int i=0; i<size; i++) |
| | 449 | contList.push_back(MoveNC(snv.retrieve_char(), snv.retrieve_char(), snv.retrieve_char())); // x, y, color |
| | 450 | } |
| | 451 | |
| | 452 | void Pattern::to_snv(SnapshotVector& snv) { |
| | 453 | snv.pb_int(flip); |
| | 454 | snv.pb_int(colorSwitch); |
| | 455 | snv.pb_int(left); |
| | 456 | snv.pb_int(right); |
| | 457 | snv.pb_int(top); |
| | 458 | snv.pb_int(bottom); |
| | 459 | snv.pb_int(boardsize); |
| | 460 | snv.pb_int(sizeX); |
| | 461 | snv.pb_int(sizeY); |
| | 462 | if (contLabels) { |
| | 463 | snv.pb_char(1); |
| | 464 | snv.pb_charp(contLabels, sizeX*sizeY); |
| | 465 | } else snv.pb_char(0); |
| | 466 | snv.pb_charp(initialPos, sizeX*sizeY); |
| | 467 | snv.pb_charp(finalPos, sizeX*sizeY); |
| | 468 | snv.pb_int(contList.size()); |
| | 469 | for(vector<MoveNC>::iterator it = contList.begin(); it != contList.end(); it++) { |
| | 470 | snv.pb_char(it->x); |
| | 471 | snv.pb_char(it->y); |
| | 472 | snv.pb_char(it->color); |
| | 473 | } |
| | 5195 | int GameList::snapshot() throw(DBError) { |
| | 5196 | // return a handle to a snapshot stored in the main GameList db |
| | 5197 | // the snapshot contains copies of |
| | 5198 | // - orderby, format1, format2 |
| | 5199 | // - currentList |
| | 5200 | // - all hits in the GameListEntry's of currentList |
| | 5201 | // - pattern, labels, continuations, num_hits, num_switched, Bwins, Wwins |
| | 5202 | |
| | 5203 | SnapshotVector snapshot; |
| | 5204 | snapshot.pb_string(orderby); |
| | 5205 | snapshot.pb_string(format1); |
| | 5206 | snapshot.pb_string(format2); |
| | 5207 | |
| | 5208 | snapshot.pb_int(currentList->size()); |
| | 5209 | for(vector<pair<int,int> >::iterator it = currentList->begin(); it != currentList->end(); it++) { |
| | 5210 | snapshot.pb_int(it->first); |
| | 5211 | snapshot.pb_int(it->second); |
| | 5212 | vector<Hit* >* hits = (*all)[it->second]->hits; |
| | 5213 | snapshot.pb_int(hits->size()); |
| | 5214 | for (vector<Hit* >::iterator it_h = hits->begin(); it_h != hits->end(); it_h++) { |
| | 5215 | (*it_h)->to_snv(snapshot); |
| | 5216 | } |
| | 5217 | } |
| | 5218 | |
| | 5219 | if (mrs_pattern) { |
| | 5220 | snapshot.pb_char(1); |
| | 5221 | mrs_pattern->to_snv(snapshot); |
| | 5222 | } else snapshot.pb_char(0); |
| | 5223 | if (searchOptions) { |
| | 5224 | snapshot.pb_char(1); |
| | 5225 | searchOptions->to_snv(snapshot); |
| | 5226 | } else snapshot.pb_char(0); |
| | 5227 | if (mrs_pattern && labels && continuations) { |
| | 5228 | snapshot.pb_char(1); |
| | 5229 | snapshot.pb_charp(labels, mrs_pattern->sizeX * mrs_pattern->sizeY); |
| | 5230 | for(int i=0; i<mrs_pattern->sizeX * mrs_pattern->sizeY; i++) continuations[i].to_snv(snapshot); |
| | 5231 | } else snapshot.pb_char(0); |
| | 5232 | snapshot.pb_int(num_hits); |
| | 5233 | snapshot.pb_int(num_switched); |
| | 5234 | snapshot.pb_int(Bwins); |
| | 5235 | snapshot.pb_int(Wwins); |
| | 5236 | |
| | 5237 | // insert snapshot into database |
| | 5238 | sqlite3_stmt *ppStmt=0; |
| | 5239 | int rc = sqlite3_prepare(db, "insert into snapshots (data) values (?)", -1, &ppStmt, 0); |
| | 5240 | if (rc != SQLITE_OK || ppStmt==0) throw DBError(); |
| | 5241 | char* snchp = snapshot.to_charp(); |
| | 5242 | rc = sqlite3_bind_blob(ppStmt, 1, snchp, snapshot.size(), SQLITE_TRANSIENT); |
| | 5243 | delete [] snchp; |
| | 5244 | if (rc != SQLITE_OK) throw DBError(); |
| | 5245 | rc = sqlite3_step(ppStmt); |
| | 5246 | if (rc != SQLITE_DONE) throw DBError(); |
| | 5247 | rc = sqlite3_finalize(ppStmt); |
| | 5248 | if (rc != SQLITE_OK) throw DBError(); |
| | 5249 | return sqlite3_last_insert_rowid(db); |
| | 5250 | } |
| | 5251 | |
| | 5252 | void GameList::restore(int handle, bool del) throw(DBError) { |
| | 5253 | // restore the state of the GameList associated with handle |
| | 5254 | |
| | 5255 | // retrieve info associated with handle from db |
| | 5256 | |
| | 5257 | char* sn = 0; |
| | 5258 | int sn_size = 0; |
| | 5259 | sqlite3_stmt *ppStmt=0; |
| | 5260 | int rc = sqlite3_prepare(db, "select data from snapshots where rowid = ?", -1, &ppStmt, 0); |
| | 5261 | if (rc != SQLITE_OK || ppStmt==0) { |
| | 5262 | printf("%d\n", rc); |
| | 5263 | throw DBError(); |
| | 5264 | } |
| | 5265 | rc = sqlite3_bind_int(ppStmt, 1, handle); |
| | 5266 | if (rc != SQLITE_OK) throw DBError(); |
| | 5267 | rc = sqlite3_step(ppStmt); |
| | 5268 | if (rc == SQLITE_ROW) { |
| | 5269 | sn = (char*)sqlite3_column_blob(ppStmt, 0); |
| | 5270 | sn_size = sqlite3_column_bytes(ppStmt, 0); |
| | 5271 | } else throw DBError(); |
| | 5272 | |
| | 5273 | SnapshotVector snapshot(sn, sn_size); |
| | 5274 | |
| | 5275 | // parse info |
| | 5276 | |
| | 5277 | string ob = snapshot.retrieve_string(); |
| | 5278 | string f1 = snapshot.retrieve_string(); |
| | 5279 | string f2 = snapshot.retrieve_string(); |
| | 5280 | if (ob != orderby || f1 != format1 || f2 != format2) resetFormat(); |
| | 5281 | |
| | 5282 | if (oldList) delete oldList; |
| | 5283 | oldList = 0; |
| | 5284 | if (currentList) delete currentList; |
| | 5285 | currentList = new vector<pair<int,int> >; |
| | 5286 | for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++) { |
| | 5287 | if ((*it)->hits) { |
| | 5288 | for(vector<Hit* >::iterator ith = (*it)->hits->begin(); ith != (*it)->hits->end(); ith++) |
| | 5289 | delete *ith; |
| | 5290 | delete (*it)->hits; |
| | 5291 | (*it)->hits = 0; |
| | 5292 | } |
| | 5293 | if ((*it)->candidates) { |
| | 5294 | for(vector<Candidate* >::iterator itc = (*it)->candidates->begin(); itc != (*it)->candidates->end(); itc++) |
| | 5295 | delete *itc; |
| | 5296 | delete (*it)->candidates; |
| | 5297 | (*it)->candidates = 0; |
| | 5298 | } |
| | 5299 | } |
| | 5300 | |
| | 5301 | int cl_size = snapshot.retrieve_int(); |
| | 5302 | for(int i=0; i<cl_size; i++) { |
| | 5303 | currentList->push_back(make_pair(snapshot.retrieve_int(), snapshot.retrieve_int())); |
| | 5304 | (*all)[(*currentList)[currentList->size()-1].second]->hits_from_snv(snapshot); |
| | 5305 | } |
| | 5306 | |
| | 5307 | if (mrs_pattern) delete mrs_pattern; |
| | 5308 | if (snapshot.retrieve_char()) mrs_pattern = new Pattern(snapshot); |
| | 5309 | else mrs_pattern = 0; |
| | 5310 | |
| | 5311 | if (searchOptions) delete searchOptions; |
| | 5312 | if (snapshot.retrieve_char()) searchOptions = new SearchOptions(snapshot); |
| | 5313 | else searchOptions = 0; |
| | 5314 | |
| | 5315 | if (labels) delete [] labels; |
| | 5316 | if (continuations) delete [] continuations; // FIXME check (cf. ~GameList) |
| | 5317 | if (snapshot.retrieve_char()) { |
| | 5318 | labels = snapshot.retrieve_charp(); |
| | 5319 | continuations = new Continuation[mrs_pattern->sizeX * mrs_pattern->sizeY]; |
| | 5320 | for(int i=0; i<mrs_pattern->sizeX * mrs_pattern->sizeY; i++) |
| | 5321 | continuations[i].from_snv(snapshot); |
| | 5322 | } else { |
| | 5323 | labels = 0; |
| | 5324 | continuations = 0; |
| | 5325 | } |
| | 5326 | num_hits = snapshot.retrieve_int(); |
| | 5327 | num_switched = snapshot.retrieve_int(); |
| | 5328 | Bwins = snapshot.retrieve_int(); |
| | 5329 | Wwins = snapshot.retrieve_int(); |
| | 5330 | |
| | 5331 | rc = sqlite3_finalize(ppStmt); |
| | 5332 | if (rc != SQLITE_OK) throw DBError(); |
| | 5333 | if (del) { // delete snapshot from db |
| | 5334 | char sql[100]; |
| | 5335 | sprintf(sql, "delete from snapshots where rowid = %d", handle); |
| | 5336 | rc = sqlite3_exec(db, sql, 0, 0, 0); |
| | 5337 | if (rc != SQLITE_OK) throw DBError(); |
| | 5338 | } |
| | 5339 | } |
| | 5340 | |
| | 5341 | void GameList::delete_snapshot(int handle) throw(DBError) { |
| | 5342 | char sql[100]; |
| | 5343 | sprintf(sql, "delete from snapshots where rowid = %d", handle); |
| | 5344 | int rc = sqlite3_exec(db, sql, 0, 0, 0); |
| | 5345 | if (rc != SQLITE_OK) throw DBError(); |
| | 5346 | } |
| | 5347 | |
| | 5348 | void GameList::delete_all_snapshots() throw(DBError) { |
| | 5349 | int rc = sqlite3_exec(db, "delete from snapshots", 0, 0, 0); |
| | 5350 | if (rc != SQLITE_OK) throw DBError(); |
| | 5351 | } |
| | 5352 | |