Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
scidbase.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2014-2016 Fulvio Benini
3 
4 * This file is part of Scid (Shane's Chess Information Database).
5 *
6 * Scid is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation.
9 *
10 * Scid is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Scid. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "scidbase.h"
20 #include "codec_memory.h"
21 #include "codec_pgn.h"
22 #include "codec_scid4.h"
23 #include "common.h"
24 #include "sortcache.h"
25 #include "stored.h"
26 #include <algorithm>
27 #include <math.h>
28 
29 std::pair<ICodecDatabase*, errorT>
30 ICodecDatabase::open(Codec codec, fileModeT fMode, const char* filename,
31  const Progress& progress, Index* idx, NameBase* nb) {
32  auto createCodec = [](auto codec) -> ICodecDatabase* {
33  switch (codec) {
35  return new CodecMemory();
37  return new CodecSCID4();
39  return new CodecPgn();
40  }
41  ASSERT(0);
42  return nullptr;
43  };
44 
45  auto obj = createCodec(codec);
46  auto err = obj->dyn_open(fMode, filename, progress, idx, nb);
47  if (err != OK && err != ERROR_NameDataLoss) {
48  delete obj;
49  obj = nullptr;
50  }
51  return {obj, err};
52 }
53 
55  idx = new Index;
56  nb_ = new NameBase;
57  game = new Game;
58  gameNumber = -1;
59  gameAltered = false;
60  inUse = false;
61  tree.moveCount = tree.totalCount = 0;
62  fileMode_ = FMODE_None;
63  bbuf = new ByteBuffer(BBUF_SIZE);
64  dbFilter = new Filter(0);
65  treeFilter = new Filter(0);
66  duplicates_ = NULL;
67  stats_ = NULL;
68 }
69 
71  if (inUse)
72  Close();
73 
74  delete[] duplicates_;
75  delete idx;
76  delete nb_;
77  delete game;
78  delete bbuf;
79  delete stats_;
80  delete dbFilter;
81  delete treeFilter;
82 }
83 
85  const char* filename, const Progress& progress) {
86  if (inUse)
87  return ERROR_FileInUse;
88  if (filename == 0)
89  filename = "";
90 
91  auto obj = ICodecDatabase::open(dbtype, fMode, filename, progress, idx, nb_);
92  if (obj.first) {
93  codec_.reset(obj.first);
94  inUse = true;
95  fileMode_ = (fMode == FMODE_Create) ? FMODE_Both : fMode;
96  fileName_ = filename;
97  gameNumber = -1;
98 
99  // Initialize the filters: all the games are included by default.
100  dbFilter->Init(numGames());
101  treeFilter->Init(numGames());
102  ASSERT(filters_.empty());
103 
104  // Default treeCache size: 250
105  treeCache.CacheResize(250);
106  } else {
107  idx->Close();
108  nb_->Clear();
109  }
110 
111  return obj.second;
112 }
113 
115  ASSERT(inUse);
116 
117  for (auto& sortCache : sortCaches_) {
118  delete sortCache.second;
119  }
120  sortCaches_.clear();
121 
122  errorT errIdx = idx->Close();
123  nb_->Clear();
124  codec_ = nullptr;
125 
126  clear();
127  game->Clear();
128  fileMode_ = FMODE_None;
129  fileName_ = "<empty>";
130  gameNumber = -1;
131  gameAltered = false;
132  dbFilter->Init(0);
133  treeFilter->Init(0);
134  for (size_t i=0, n = filters_.size(); i < n; i++) delete filters_[i].second;
135  filters_.clear();
136  inUse = false;
137 
138  return errIdx;
139 }
140 
141 
142 void scidBaseT::clear() {
143  if (stats_ != NULL) { delete stats_; stats_ = NULL;}
144  if (duplicates_ != NULL) { delete[] duplicates_; duplicates_ = NULL; }
145  treeCache.Clear();
146  for (nameT nt = NAME_PLAYER; nt < NUM_NAME_TYPES; nt++) {
147  nameFreq_[nt].resize(0);
148  }
149 }
150 
152  for (auto& sortCache : sortCaches_) {
153  sortCache.second->prepareForChanges();
154  }
155 }
156 
158  clear();
159  errorT res = codec_->flush();
160 
161  auto n_games = numGames();
162  if (dbFilter->Size() != n_games) {
163  dbFilter->Resize(n_games);
164  treeFilter->Resize(n_games);
165  for (auto& filter : filters_) {
166  filter.second->Resize(n_games);
167  }
168  }
169 
170  for (auto& sortCache : sortCaches_) {
171  sortCache.second->checkForChanges(gNum);
172  }
173 
174  return res;
175 }
176 
178  beginTransaction();
179  errorT err1 = saveGameHelper(game, replacedGameId);
180  errorT err2 = endTransaction(replacedGameId);
181  return (err1 != OK) ? err1 : err2;
182 }
183 
185  if (isReadOnly())
186  return ERROR_FileReadOnly;
187 
188  if (gameId < numGames())
189  return codec_->saveGame(game, gameId);
190 
191  return codec_->addGame(game);
192 }
193 
195  if (srcBase == this) return ERROR_BadArg;
196  if (isReadOnly()) return ERROR_FileReadOnly;
197  if (gNum >= srcBase->numGames()) return ERROR_BadArg;
198 
199  beginTransaction();
200  errorT err = importGameHelper(srcBase, gNum);
201  errorT errClear = endTransaction();
202  return (err == OK) ? errClear : err;
203 }
204 
205 errorT scidBaseT::importGames(const scidBaseT* srcBase, const HFilter& filter, const Progress& progress) {
206  ASSERT(srcBase != 0);
207  ASSERT(filter != 0);
208  if (srcBase == this) return ERROR_BadArg;
209  if (isReadOnly()) return ERROR_FileReadOnly;
210 
211  beginTransaction();
212  errorT err = OK;
213  size_t iProgress = 0;
214  size_t totGames = filter->size();
215  for (gamenumT gNum = 0, n = srcBase->numGames(); gNum < n; gNum++) {
216  if (filter.get(gNum) == 0) continue;
217  err = importGameHelper(srcBase, gNum);
218  if (err != OK) break;
219  if (++iProgress % 8192 == 0) {
220  if (!progress.report(iProgress, totGames)) break;
221  }
222  }
223  errorT errClear = endTransaction();
224  return (err == OK) ? errClear : err;
225 }
226 
227 errorT scidBaseT::importGameHelper(const scidBaseT* srcBase, gamenumT gNum) {
228  auto srcIe = srcBase->getIndexEntry(gNum);
229  auto dataSz = srcIe->GetLength();
230  auto data = srcBase->codec_->getGameData(srcIe->GetOffset(), dataSz);
231  if (data == nullptr)
232  return ERROR_FileRead;
233 
234  return codec_->addGame(srcIe, srcBase->getNameBase(), data, dataSz);
235 }
236 
238  const char* filename, const Progress& progress,
239  std::string& errorMsg) {
240  ASSERT(dbtype == ICodecDatabase::PGN);
241 
242  if (isReadOnly())
243  return ERROR_FileReadOnly;
244 
245  beginTransaction();
246 
247  CodecPgn pgn;
248  auto res = pgn.open(filename, FMODE_ReadOnly);
249  if (res == OK) {
250  res = CodecPgn::parseGames(
251  progress, pgn, [&](Game& game) { return codec_->addGame(&game); });
252  errorMsg = pgn.parseErrors();
253  }
254 
255  auto res_endTrans = endTransaction();
256  return (res != OK) ? res : res_endTrans;
257 }
258 
259 /**
260  * Filters
261  */
262 std::string scidBaseT::newFilter() {
263  std::string newname = (filters_.size() == 0)
264  ? "a_"
265  : filters_.back().first;
266  if (newname[0] == 'z') {
267  newname = 'a' + newname;
268  } else {
269  newname = ++(newname[0]) + newname.substr(1);
270  }
271  filters_.push_back(std::make_pair(newname, new Filter(numGames())));
272  return newname;
273 }
274 
275 std::string scidBaseT::composeFilter(const std::string& mainFilter,
276  const std::string& maskFilter) const {
277  std::string res;
278  if (mainFilter.empty()) return res;
279 
280  if (mainFilter[0] != '+') {
281  res = mainFilter;
282  } else {
283  size_t maskName = mainFilter.find('+', 1);
284  if (maskName != std::string::npos)
285  res = mainFilter.substr(1, maskName - 1);
286  }
287 
288  if (!maskFilter.empty()) {
289  res = '+' + res + "+" + maskFilter;
290  }
291 
292  if (getFilter(res) == 0) res.clear();
293  return res;
294 }
295 
296 void scidBaseT::deleteFilter(const char* filterId) {
297  for (size_t i = 0, n = filters_.size(); i < n; i++) {
298  if (filters_[i].first == filterId) {
299  delete filters_[i].second;
300  filters_.erase(filters_.begin() + i);
301  break;
302  }
303  }
304 }
305 
306 Filter* scidBaseT::fetchFilter(const std::string& filterId) const {
307  if (filterId == "dbfilter") return dbFilter;
308  if (filterId == "tree") return treeFilter;
309 
310  for (size_t i = 0, n = filters_.size(); i < n; i++) {
311  if (filterId == filters_[i].first)
312  return filters_[i].second;
313  }
314  return 0;
315 }
316 
317 HFilter scidBaseT::getFilterHelper(const std::string& filterId,
318  bool unmasked) const {
319  Filter* main = 0;
320  const Filter* mask = 0;
321  if (filterId.empty() || filterId[0] != '+') {
322  main = fetchFilter(filterId);
323  } else {
324  size_t maskName = filterId.find('+', 1);
325  if (maskName != std::string::npos) {
326  main = fetchFilter(filterId.substr(1, maskName - 1));
327  if (!unmasked) mask = fetchFilter(filterId.substr(maskName + 1));
328  }
329  }
330  return HFilter(main, mask);
331 }
332 
333 /**
334  * Statistics
335  */
337  if (stats_ == NULL) stats_ = new scidBaseT::Stats(this);
338  return *stats_;
339 }
340 
342 : count(0) {
343  std::fill_n(results, NUM_RESULT_TYPES, 0);
344 }
345 
348  minDate = ZERO_DATE;
349  maxDate = ZERO_DATE;
350  nYears = 0;
351  sumYears = 0;
352  std::fill_n(nResults, NUM_RESULT_TYPES, 0);
353  nRatings = 0;
354  sumRatings = 0;
355  minRating = 0;
356  maxRating = 0;
357 
358  // Read stats from index entry of each game:
359  for (gamenumT gnum=0, n = dbase->numGames(); gnum < n; gnum++) {
360  const IndexEntry* ie = dbase->getIndexEntry(gnum);
361  nResults[ie->GetResult()]++;
362  eloT elo = ie->GetWhiteElo();
363  if (elo > 0) {
364  nRatings++;
365  sumRatings += elo;
366  if (minRating == 0) { minRating = elo; }
367  if (elo < minRating) { minRating = elo; }
368  if (elo > maxRating) { maxRating = elo; }
369  }
370  elo = ie->GetBlackElo();
371  if (elo > 0) {
372  nRatings++;
373  sumRatings += elo;
374  if (minRating == 0) { minRating = elo; }
375  if (elo < minRating) { minRating = elo; }
376  if (elo > maxRating) { maxRating = elo; }
377  }
378  dateT date = ie->GetDate();
379  if (gnum == 0) {
380  maxDate = minDate = date;
381  }
382  if (date_GetYear(date) > 0) {
383  if (date < minDate) { minDate = date; }
384  if (date > maxDate) { maxDate = date; }
385  nYears++;
386  sumYears += date_GetYear (date);
387  }
388 
389  for (uint flag = 0; flag < IndexEntry::IDX_NUM_FLAGS; flag++) {
390  bool value = ie->GetFlag (1 << flag);
391  if (value) {
392  flagCount[flag]++;
393  }
394  }
395 
396  resultT result = ie->GetResult();
397  ecoT eco = ie->GetEcoCode();
398  if (eco == 0) {
399  ecoEmpty_.count++;
400  ecoEmpty_.results[result]++;
401  } else {
402  ecoValid_.count++;
403  ecoValid_.results[result]++;
404  eco = eco_Reduce(eco);
405  ecoStats_[eco].count++;
406  ecoStats_[eco].results[result]++;
407  eco /= 27;
408  ecoGroup3_[eco].count++;
409  ecoGroup3_[eco].results[result]++;
410  eco /= 10;
411  ecoGroup2_[eco].count++;
412  ecoGroup2_[eco].results[result]++;
413  eco /= 10;
414  ecoGroup1_[eco].count++;
415  ecoGroup1_[eco].results[result]++;
416  }
417  }
418 }
419 
420 const scidBaseT::Stats::Eco* scidBaseT::Stats::getEcoStats(const char* ecoStr) const {
421  ASSERT(ecoStr != 0);
422 
423  if (*ecoStr == 0) return &ecoValid_;
424 
425  ecoT eco = eco_FromString(ecoStr);
426  if (eco == 0) return 0;
427  eco = eco_Reduce(eco);
428 
429  switch(strlen(ecoStr)) {
430  case 0:
431  return &ecoValid_;
432  case 1:
433  return &(ecoGroup1_[eco / 2700]);
434  case 2:
435  return &(ecoGroup2_[eco / 270]);
436  case 3:
437  return &(ecoGroup3_[eco / 27]);
438  case 4:
439  case 5:
440  return &(ecoStats_[eco]);
441  }
442 
443  return 0;
444 }
445 
446 
447 
448 double scidBaseT::TreeStat::expVect_[1600];
449 
451 : toMove(NOCOLOR), resultW(0), resultD(0), resultB(0), exp(0), ngames(0), nexp(0)
452 {
453  if (TreeStat::expVect_[0] == 0) {
454  for (int i=-800; i < 800; i++) TreeStat::expVect_[i+800] = 1/(1 + pow(10, i/400.0));
455  }
456 }
457 
458 std::vector<scidBaseT::TreeStat> scidBaseT::getTreeStat(const HFilter& filter) {
459  ASSERT(filter != 0);
460 
461  std::vector<scidBaseT::TreeStat> res;
462  std::vector<FullMove> v;
463  auto nb = getNameBase();
464  for (gamenumT gnum = 0, n = numGames(); gnum < n; gnum++) {
465  uint ply = filter.get(gnum);
466  if (ply == 0) continue;
467  else ply--;
468 
469  const IndexEntry* ie = getIndexEntry(gnum);
471  if (!move)
472  move = getGame(ie).getMove(ply);
473 
474  size_t i = 0;
475  while (i < v.size() && v[i] != move) i++;
476  if (i == v.size()) {
477  v.push_back(move);
478  res.push_back(scidBaseT::TreeStat());
479  }
480  res[i].add(ie->GetResult(), ie->GetWhiteElo(nb), ie->GetBlackElo(nb));
481  }
482 
483  for (size_t i = 0, n = v.size(); i < n; i++) {
484  res[i].SAN = !v[i] ? "[end]" : v[i].getSAN(&(res[i].toMove));
485  }
486 
487  std::sort(res.begin(), res.end());
488  return res;
489 }
490 
491 errorT scidBaseT::getCompactStat(unsigned long long* n_deleted,
492  unsigned long long* n_unused,
493  unsigned long long* n_sparse,
494  unsigned long long* n_badNameId) {
495  std::vector<uint> nbFreq[NUM_NAME_TYPES];
496  for (nameT n = NAME_PLAYER; n < NUM_NAME_TYPES; n++) {
497  nbFreq[n].resize(getNameBase()->GetNumNames(n), 0);
498  }
499 
500  uint64_t last_offset = 0;
501  *n_sparse = 0;
502  *n_deleted = 0;
503  for (gamenumT i=0, n = numGames(); i < n; i++) {
504  const IndexEntry* ie = getIndexEntry (i);
505  if (ie->GetDeleteFlag()) { *n_deleted += 1; continue; }
506 
507  auto offset = ie->GetOffset();
508  if (offset < last_offset) *n_sparse += 1;
509  last_offset = offset;
510 
511  nbFreq[NAME_PLAYER][ie->GetWhite()] += 1;
512  nbFreq[NAME_PLAYER][ie->GetBlack()] += 1;
513  nbFreq[NAME_EVENT][ie->GetEvent()] += 1;
514  nbFreq[NAME_SITE][ie->GetSite()] += 1;
515  nbFreq[NAME_ROUND][ie->GetRound()] += 1;
516  }
517 
518  *n_unused = 0;
519  for (nameT n = NAME_PLAYER; n < NUM_NAME_TYPES; n++) {
520  *n_unused += std::count(nbFreq[n].begin(), nbFreq[n].end(), 0);
521  }
522 
523  *n_badNameId = idx->GetBadNameIdCount();
524  return OK;
525 }
526 
528  std::vector<std::string> filenames = codec_->getFilenames();
529  if (filenames.empty()) return ERROR_CodecUnsupFeat;
530 
531  if (fileMode_ != FMODE_Both) {
532  //Older scid version to be upgraded are opened read only
533  if (idx->GetVersion() == SCID_VERSION) return ERROR_FileMode;
534  }
535 
536  //1) Create a new temporary database
537  std::string filename = fileName_;
538  std::string tmpfile = filename + "__COMPACT__";
539  ICodecDatabase::Codec dbtype = codec_->getType();
540  scidBaseT tmp;
541  errorT err_Create = tmp.Open(dbtype, FMODE_Create, tmpfile.c_str());
542  if (err_Create != OK) return err_Create;
543 
544  //2) Copy the Index Header
545  tmp.beginTransaction();
546  tmp.idx->copyHeaderInfo(*idx);
547  gamenumT autoloadOld = idx->GetAutoLoad();
548  gamenumT autoloadNew = 1;
549 
550  //3) Create the list of games to be copied
551  std::vector< std::pair<uint64_t, gamenumT> > sort;
552  uint n_deleted = 0;
553  for (gamenumT i = 0, n = numGames(); i < n; i++) {
554  const IndexEntry* ie = getIndexEntry(i);
555  if (ie->GetDeleteFlag()) {
556  n_deleted++;
557  continue;
558  }
559  uint64_t order = static_cast<uint64_t>(ie->GetStoredLineCode()) << 56;
560  const byte* hp = ie->GetHomePawnData();
561  order |= static_cast<uint64_t>(hp[0]) << 48;
562  order |= static_cast<uint64_t>(hp[1]) << 40;
563  order |= static_cast<uint64_t>(hp[2]) << 32;
564  order |= static_cast<uint64_t>(hp[3]) << 24;
565  order |= ie->GetFinalMatSig() & 0xFFFFFF;
566  sort.emplace_back(order, i);
567  }
568  std::stable_sort(sort.begin(), sort.end());
569 
570  //4) Copy the games
571  uint iProgress = 0;
572  bool err_UserCancel = false;
573  errorT err_AddGame = OK;
574  for (auto it = sort.cbegin(); it != sort.cend(); ++it) {
575  err_AddGame = tmp.importGameHelper(this, it->second);
576  if (err_AddGame != OK) break;
577 
578  gamenumT oldGnum = it->second + 1;
579  if (oldGnum == autoloadOld) autoloadNew = tmp.numGames();
580  //TODO:
581  //- update bookmarks game number
582  // (*it).second == old game number
583  // tmp.numGames() == new game number
584  if (++iProgress % 8192 == 0) {
585  if (!progress.report(iProgress, sort.size())) {
586  err_UserCancel = true;
587  break;
588  }
589  }
590  }
591 
592  //5) Finalize the new database
593  tmp.idx->SetAutoLoad(autoloadNew);
594  std::vector<std::string> tmp_filenames = tmp.codec_->getFilenames();
595  errorT err_NbWrite = tmp.endTransaction();
596  errorT err_Close = tmp.Close();
597  if (err_Close == OK) err_Close = (filenames.size() == tmp_filenames.size()) ? OK : ERROR;
598 
599  //6) Error: cleanup and report
600  if (err_NbWrite != OK || err_Close != OK || err_UserCancel || err_AddGame != OK) {
601  for (size_t i = 0, n = tmp_filenames.size(); i < n; i++) {
602  std::remove(tmp_filenames[i].c_str());
603  }
604  if (err_AddGame != OK)
605  return err_AddGame;
606  if (err_UserCancel)
607  return ERROR_UserCancel;
608  if (err_NbWrite != OK)
609  return err_NbWrite;
610  ASSERT(err_Close != OK);
611  return err_Close;
612  }
613 
614  //7) Remember the active filters and SortCaches
615  std::vector<std::string> filters(filters_.size());
616  for (size_t i = 0, n = filters_.size(); i < n; i++) {
617  filters[i] = filters_[i].first;
618  }
619  std::vector< std::pair<std::string, int> > oldSC;
620  for (auto& sortCache : sortCaches_) {
621  int refCount = sortCache.second->incrRef(0);
622  if (refCount >= 0)
623  oldSC.emplace_back(sortCache.first, refCount);
624  }
625 
626  //8) Remove the old database
627  if (Close() != OK) return ERROR_FileInUse;
628  for (size_t i = 0, n = filenames.size(); i < n; i++) {
629  if (std::remove(filenames[i].c_str()) != 0) return ERROR_CompactRemove;
630  }
631 
632  //9) Success: rename the files and open the new database
633  for (size_t i = 0, n = filenames.size(); i < n; i++) {
634  const char* s1 = tmp_filenames[i].c_str();
635  const char* s2 = filenames[i].c_str();
636  std::rename(s1, s2);
637  }
638  errorT res = Open(dbtype, FMODE_Both, filename.c_str());
639 
640  //10) Re-create filters and SortCaches
641  if (res == OK || res == ERROR_NameDataLoss) {
642  for (size_t i = 0, n = filters.size(); i < n; i++) {
643  filters_.push_back(
644  std::make_pair(filters[i], new Filter(numGames())));
645  }
646  for (size_t i = 0, n = oldSC.size(); i < n; i++) {
647  const std::string& criteria = oldSC[i].first;
648  SortCache* sc = SortCache::create(idx, nb_, criteria.c_str());
649  if (sc != NULL) {
650  sc->incrRef(oldSC[i].second);
651  sortCaches_.emplace_back(criteria, sc);
652  }
653  }
654  }
655 
656  return res;
657 }
658 
659 /**
660  * Retrieve a SortCache object matching the supplied @e criteria.
661  * A new SortCache with refCount equal to 0 is created if a suitable object is
662  * not found in @e sortCaches_. Objects with refCount <= 0 are destroyed by the
663  * @e releaseSortCache function independently from the provided @e criteria
664  * argument (implementing a rudimentary garbage collector).
665  * @param criteria: the list of fields by which games will be ordered.
666  * Each field should be followed by '+' to indicate an
667  * ascending order or by '-' for a descending order.
668  * @returns a pointer to a SortCache object in case of success, NULL otherwise.
669  */
670 SortCache* scidBaseT::getSortCache(const char* criteria) {
671  ASSERT(criteria != NULL);
672 
673  for (auto& sortCache : sortCaches_) {
674  if (sortCache.first == criteria)
675  return sortCache.second;
676  }
677 
678  SortCache* sc = SortCache::create(idx, getNameBase(), criteria);
679  if (sc != NULL)
680  sortCaches_.emplace_back(criteria, sc);
681 
682  return sc;
683 }
684 
685 void scidBaseT::releaseSortCache(const char* criteria) {
686  size_t i = 0;
687  while (i < sortCaches_.size()) {
688  const char* tmp = sortCaches_[i].first.c_str();
689  int decr = std::strcmp(criteria, tmp) ? 0 : -1;
690  if (sortCaches_[i].second->incrRef(decr) <= 0) {
691  delete sortCaches_[i].second;
692  sortCaches_.erase(sortCaches_.begin() + i);
693  continue; //do not increment i
694  }
695  i += 1;
696  }
697 }
698 
699 SortCache* scidBaseT::createSortCache(const char* criteria) {
700  SortCache* sc = getSortCache(criteria);
701  if (sc != NULL)
702  sc->incrRef(1);
703 
704  return sc;
705 }
706 
707 size_t scidBaseT::listGames(const char* criteria, size_t start, size_t count,
708  const HFilter& filter, gamenumT* destCont) {
709  const SortCache* sc = getSortCache(criteria);
710  if (sc == NULL)
711  return 0;
712 
713  return sc->select(start, count, filter, destCont);
714 }
715 
716 size_t scidBaseT::sortedPosition(const char* criteria, const HFilter& filter,
717  gamenumT gameId) {
718  ASSERT(filter != NULL && filter->size() <= numGames());
719 
720  if (gameId >= numGames() || filter->get(gameId) == 0)
721  return INVALID_GAMEID;
722 
723  SortCache* sc = getSortCache(criteria);
724  if (sc == NULL)
725  return INVALID_GAMEID;
726 
727  return sc->sortedPosition(gameId, filter);
728 }
unsigned char byte
Definition: common.h:89
const IndexEntry * getIndexEntry(gamenumT g) const
Definition: scidbase.h:131
errorT SetAutoLoad(gamenumT gnum)
Definition: index.h:182
const errorT ERROR_CodecUnsupFeat
Definition: error.h:82
uint date_GetYear(dateT date)
Definition: date.h:52
Manages memory databases that do not have associated files.
Definition: codec_memory.h:34
byte resultT
Definition: common.h:187
void deleteFilter(const char *filterId)
Definition: scidbase.cpp:296
dateT GetDate() const
Definition: indexentry.h:107
FullMove getMove(int ply_to_skip)
Definition: fastgame.h:422
const byte * GetHomePawnData() const
Definition: indexentry.h:118
const errorT OK
Definition: error.h:23
FastGame getGame(const IndexEntry *ie) const
Definition: scidbase.h:141
const uint NUM_RESULT_TYPES
Definition: common.h:186
const errorT ERROR_FileInUse
Definition: error.h:37
resultT GetResult() const
Definition: indexentry.h:109
const colorT NOCOLOR
Definition: common.h:209
SortCache * createSortCache(const char *criteria)
Increment the reference count of a SortCache object matching criteria.
Definition: scidbase.cpp:699
const Stats & getStats() const
Statistics.
Definition: scidbase.cpp:336
Definition: indexentry.h:295
idNumberT GetSite() const
Definition: indexentry.h:105
size_t select(size_t row_offset, size_t row_count, const HFilter &filter, gamenumT *result) const
Retrieve the sorted list of games&#39; ids.
Definition: sortcache.cpp:160
uint dateT
Definition: common.h:147
static FullMove getMove(uint code, uint ply=0)
Definition: stored.h:40
#define ASSERT(f)
Definition: common.h:59
const errorT ERROR_BadArg
Definition: error.h:28
int incrRef(int incr)
Definition: sortcache.h:144
idNumberT GetEvent() const
Definition: indexentry.h:104
Definition: misc.h:63
static std::pair< ICodecDatabase *, errorT > open(Codec codec, fileModeT fMode, const char *filename, const Progress &progress, Index *idx, NameBase *nb)
Creates a new object and calls the virtual function dyn_open().
Definition: scidbase.cpp:30
errorT Close()
Definition: scidbase.cpp:114
byte get(gamenumT gnum) const
Definition: hfilter.h:260
uint64_t sumYears
Definition: scidbase.h:45
errorT saveGame(Game *game, gamenumT replacedGameId=INVALID_GAMEID)
Add or replace a game into the database.
Definition: scidbase.cpp:177
errorT endTransaction(gamenumT gameId=INVALID_GAMEID)
Update caches and flush the database&#39;s files.
Definition: scidbase.cpp:157
const gamenumT INVALID_GAMEID
Definition: scidbase.h:37
Index * idx
Definition: scidbase.h:346
gamenumT GetAutoLoad() const
Definition: index.h:144
matSigT GetFinalMatSig() const
Definition: indexentry.h:114
This class manages databases encoded in SCID format v4.
Definition: codec_scid4.h:35
uint results[NUM_RESULT_TYPES]
Definition: scidbase.h:56
#define BBUF_SIZE
Definition: common.h:36
size_t sortedPosition(gamenumT gameId, const HFilter &filter) const
Get the sorted position of a game.
Definition: sortcache.cpp:213
errorT importGame(const scidBaseT *srcBase, uint gNum)
Definition: scidbase.cpp:194
const dateT ZERO_DATE
Definition: date.h:35
void beginTransaction()
This function must be called before modifying the games of the database.
Definition: scidbase.cpp:151
eloT GetWhiteElo() const
Definition: indexentry.h:99
const errorT ERROR_CompactRemove
Definition: error.h:42
Defines the SortCache class, which sorts the games of an Index.
std::string newFilter()
A Filter is a selection of games, usually obtained searching the database.
Definition: scidbase.cpp:262
bool GetFlag(uint32_t mask) const
Definition: indexentry.h:117
This class stores the database&#39;s names (players, events, sites and rounds).
Definition: namebase.h:33
uint64_t sumRatings
Definition: scidbase.h:48
int main(int argc, char *argv[])
Definition: tkscid.cpp:83
const errorT ERROR_FileRead
Definition: error.h:33
ecoT eco_Reduce(ecoT eco)
ecoReduce() - maps eco to a smaller set
Definition: misc.cpp:130
const errorT ERROR_UserCancel
Definition: error.h:27
sort?type?
Definition: analysis.tcl:320
~scidBaseT()
Definition: scidbase.cpp:70
This interface separates the logic of a database from its representation.
Definition: codec.h:43
size_t sortedPosition(const char *criteria, const HFilter &filter, gamenumT gameId)
Get the sorted position of a game.
Definition: scidbase.cpp:716
uint32_t uint
Definition: common.h:91
errorT saveGameHelper(Game *game, gamenumT gameId)
Definition: scidbase.cpp:184
static errorT parseGames(const TProgress &progress, TSource &src, TDestFn destFn)
Definition: codec_proxy.h:172
idNumberT GetRound() const
Definition: indexentry.h:106
idNumberT GetWhite() const
Definition: indexentry.h:98
bool GetDeleteFlag() const
Definition: indexentry.h:258
Definition: move.tcl:20
Stats(const scidBaseT *dbase)
Definition: scidbase.cpp:346
Definition: index.h:58
const Eco * getEcoStats(const char *ecoStr) const
Definition: scidbase.cpp:420
byte GetStoredLineCode() const
Definition: indexentry.h:115
eloT GetBlackElo() const
Definition: indexentry.h:102
int GetBadNameIdCount() const
GetBadNameIdCount() - return the number of invalid name handles.
Definition: index.h:109
Close?base?
Definition: file.tcl:234
ushort eloT
Definition: common.h:164
errorT getCompactStat(unsigned long long *n_deleted, unsigned long long *n_unused, unsigned long long *n_sparse, unsigned long long *n_badNameId)
Definition: scidbase.cpp:491
void releaseSortCache(const char *criteria)
Decrement the reference count of the SortCache object matching criteria.
Definition: scidbase.cpp:685
ushort ecoT
Definition: common.h:165
ecoT GetEcoCode() const
Definition: indexentry.h:116
std::string composeFilter(const std::string &mainFilter, const std::string &maskFilter) const
Definition: scidbase.cpp:275
idNumberT GetBlack() const
Definition: indexentry.h:101
errorT copyHeaderInfo(const Index &src)
Header setter functions.
Definition: index.h:151
unsigned short errorT
Definition: error.h:20
uint nResults[NUM_RESULT_TYPES]
Definition: scidbase.h:46
Definition: errors.tcl:17
uint flagCount[IndexEntry::IDX_NUM_FLAGS]
Definition: scidbase.h:41
errorT importGames(const scidBaseT *srcBase, const HFilter &filter, const Progress &progress)
Definition: scidbase.cpp:205
const errorT ERROR_FileReadOnly
Definition: error.h:41
errorT compact(const Progress &progress)
Definition: scidbase.cpp:527
This class sorts games contained into an Index.
Definition: sortcache.h:46
size_t size() const
Definition: hfilter.h:240
clear?pattern?
We don&#39;t remove TooltipMenu because there.
bool report(size_t done, size_t total) const
Definition: misc.h:75
Definition: game.h:167
std::vector< scidBaseT::TreeStat > getTreeStat(const HFilter &filter)
Definition: scidbase.cpp:458
gamenumT numGames() const
Definition: scidbase.h:99
ecoT eco_FromString(const char *ecoStr)
Definition: misc.cpp:36
Definition: hfilter.h:35
versionT GetVersion() const
Definition: index.h:138
unsigned nameT
Definition: common.h:153
removewin args
Definition: board.tcl:923
uint32_t GetLength() const
Definition: indexentry.h:97
static SortCache * create(const Index *idx, const NameBase *nb, const char *criteria)
Create a new SortCache object, builds the hash table, and asynchronously sorts all the games...
Definition: sortcache.cpp:116
errorT open(const char *filename, fileModeT fmode)
Opens/creates a PGN database.
Definition: codec_pgn.h:66
errorT Open(ICodecDatabase::Codec dbtype, fileModeT mode, const char *filename=0, const Progress &progress=Progress())
Definition: scidbase.cpp:84
uint gamenumT
Definition: common.h:163
const versionT SCID_VERSION
Definition: common.h:43
fileModeT
Definition: common.h:136
const errorT ERROR_FileMode
Definition: error.h:38
uint64_t GetOffset() const
Definition: indexentry.h:96
Definition: tree.tcl:6
const NameBase * getNameBase() const
Definition: scidbase.h:138
const errorT ERROR_NameDataLoss
Definition: error.h:54
uint64_t nYears
Definition: scidbase.h:44
Implements the CodecSCID4 class that manages databases encoded in SCID format v4. ...
Definition: pgn_lexer.h:359
const char * parseErrors()
Returns the list of errors produced by parseNext() calls.
Definition: codec_pgn.h:144
Definition: indexentry.h:54
Implements the CodecPgn class, which manages the databases encoded in PGN format. ...
Implements the CodecMemory class, which represent a memory database.
size_t listGames(const char *criteria, size_t start, size_t count, const HFilter &filter, gamenumT *destCont)
Retrieve a list of ordered game indexes sorted by criteria.
Definition: scidbase.cpp:707
std::string getSAN(colorT *toMove=0) const
Definition: fullmove.h:72