29 std::pair<ICodecDatabase*, errorT>
45 auto obj = createCodec(codec);
46 auto err = obj->dyn_open(fMode, filename, progress, idx, nb);
61 tree.moveCount =
tree.totalCount = 0;
65 treeFilter =
new Filter(0);
85 const char* filename,
const Progress& progress) {
93 codec_.reset(obj.first);
100 dbFilter->Init(numGames());
101 treeFilter->Init(numGames());
105 treeCache.CacheResize(250);
117 for (
auto& sortCache : sortCaches_) {
118 delete sortCache.second;
122 errorT errIdx = idx->Close();
129 fileName_ =
"<empty>";
134 for (
size_t i=0, n = filters_.size(); i < n; i++)
delete filters_[i].second;
142 void scidBaseT::clear() {
143 if (stats_ != NULL) {
delete stats_; stats_ = NULL;}
144 if (duplicates_ != NULL) {
delete[] duplicates_; duplicates_ = NULL; }
147 nameFreq_[nt].resize(0);
152 for (
auto& sortCache : sortCaches_) {
153 sortCache.second->prepareForChanges();
159 errorT res = codec_->flush();
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);
170 for (
auto& sortCache : sortCaches_) {
171 sortCache.second->checkForChanges(gNum);
179 errorT err1 = saveGameHelper(game, replacedGameId);
180 errorT err2 = endTransaction(replacedGameId);
181 return (err1 !=
OK) ? err1 : err2;
188 if (gameId < numGames())
189 return codec_->saveGame(game, gameId);
191 return codec_->addGame(game);
200 errorT err = importGameHelper(srcBase, gNum);
201 errorT errClear = endTransaction();
202 return (err ==
OK) ? errClear : err;
213 size_t iProgress = 0;
214 size_t totGames = filter->
size();
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;
223 errorT errClear = endTransaction();
224 return (err ==
OK) ? errClear : err;
230 auto data = srcBase->codec_->getGameData(srcIe->GetOffset(), dataSz);
238 const char* filename,
const Progress& progress,
239 std::string& errorMsg) {
251 progress, pgn, [&](
Game&
game) {
return codec_->addGame(&game); });
255 auto res_endTrans = endTransaction();
256 return (res !=
OK) ? res : res_endTrans;
263 std::string newname = (filters_.size() == 0)
265 : filters_.back().first;
266 if (newname[0] ==
'z') {
267 newname =
'a' + newname;
269 newname = ++(newname[0]) + newname.substr(1);
271 filters_.push_back(std::make_pair(newname,
new Filter(numGames())));
276 const std::string& maskFilter)
const {
278 if (mainFilter.empty())
return res;
280 if (mainFilter[0] !=
'+') {
283 size_t maskName = mainFilter.find(
'+', 1);
284 if (maskName != std::string::npos)
285 res = mainFilter.substr(1, maskName - 1);
288 if (!maskFilter.empty()) {
289 res =
'+' + res +
"+" + maskFilter;
292 if (getFilter(res) == 0) res.clear();
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);
306 Filter* scidBaseT::fetchFilter(
const std::string& filterId)
const {
307 if (filterId ==
"dbfilter")
return dbFilter;
308 if (filterId ==
"tree")
return treeFilter;
310 for (
size_t i = 0, n = filters_.size(); i < n; i++) {
311 if (filterId == filters_[i].first)
312 return filters_[i].second;
317 HFilter scidBaseT::getFilterHelper(
const std::string& filterId,
318 bool unmasked)
const {
321 if (filterId.empty() || filterId[0] !=
'+') {
322 main = fetchFilter(filterId);
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));
390 bool value = ie->
GetFlag (1 << flag);
400 ecoEmpty_.results[result]++;
403 ecoValid_.results[result]++;
405 ecoStats_[eco].count++;
406 ecoStats_[eco].results[result]++;
408 ecoGroup3_[eco].count++;
409 ecoGroup3_[eco].results[result]++;
411 ecoGroup2_[eco].count++;
412 ecoGroup2_[eco].results[result]++;
414 ecoGroup1_[eco].count++;
415 ecoGroup1_[eco].results[result]++;
423 if (*ecoStr == 0)
return &ecoValid_;
426 if (eco == 0)
return 0;
429 switch(strlen(ecoStr)) {
433 return &(ecoGroup1_[eco / 2700]);
435 return &(ecoGroup2_[eco / 270]);
437 return &(ecoGroup3_[eco / 27]);
440 return &(ecoStats_[eco]);
448 double scidBaseT::TreeStat::expVect_[1600];
451 : toMove(
NOCOLOR), resultW(0), resultD(0), resultB(0), exp(0), ngames(0), nexp(0)
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));
461 std::vector<scidBaseT::TreeStat> res;
462 std::vector<FullMove> v;
466 if (ply == 0)
continue;
475 while (i < v.size() && v[i] !=
move) i++;
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));
492 unsigned long long* n_unused,
493 unsigned long long* n_sparse,
494 unsigned long long* n_badNameId) {
497 nbFreq[n].resize(
getNameBase()->GetNumNames(n), 0);
500 uint64_t last_offset = 0;
508 if (offset < last_offset) *n_sparse += 1;
509 last_offset = offset;
520 *n_unused += std::count(nbFreq[n].begin(), nbFreq[n].end(), 0);
528 std::vector<std::string> filenames = codec_->getFilenames();
537 std::string filename = fileName_;
538 std::string tmpfile = filename +
"__COMPACT__";
542 if (err_Create !=
OK)
return err_Create;
551 std::vector< std::pair<uint64_t, gamenumT> >
sort;
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;
566 sort.emplace_back(order, i);
568 std::stable_sort(sort.begin(), sort.end());
572 bool err_UserCancel =
false;
574 for (
auto it = sort.cbegin(); it != sort.cend(); ++it) {
575 err_AddGame = tmp.importGameHelper(
this, it->second);
576 if (err_AddGame !=
OK)
break;
579 if (oldGnum == autoloadOld) autoloadNew = tmp.
numGames();
584 if (++iProgress % 8192 == 0) {
585 if (!progress.
report(iProgress, sort.size())) {
586 err_UserCancel =
true;
594 std::vector<std::string> tmp_filenames = tmp.codec_->getFilenames();
597 if (err_Close ==
OK) err_Close = (filenames.size() == tmp_filenames.size()) ?
OK :
ERROR;
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++) {
604 if (err_AddGame !=
OK)
608 if (err_NbWrite !=
OK)
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;
619 std::vector< std::pair<std::string, int> > oldSC;
620 for (
auto& sortCache : sortCaches_) {
621 int refCount = sortCache.second->incrRef(0);
623 oldSC.emplace_back(sortCache.first, refCount);
628 for (
size_t i = 0, n = filenames.size(); i < n; i++) {
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();
642 for (
size_t i = 0, n = filters.size(); i < n; i++) {
646 for (
size_t i = 0, n = oldSC.size(); i < n; i++) {
647 const std::string& criteria = oldSC[i].first;
651 sortCaches_.emplace_back(criteria, sc);
670 SortCache* scidBaseT::getSortCache(
const char* criteria) {
673 for (
auto& sortCache : sortCaches_) {
674 if (sortCache.first == criteria)
675 return sortCache.second;
680 sortCaches_.emplace_back(criteria, sc);
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);
709 const SortCache* sc = getSortCache(criteria);
713 return sc->
select(start, count, filter, destCont);
720 if (gameId >=
numGames() || filter->
get(gameId) == 0)
const IndexEntry * getIndexEntry(gamenumT g) const
errorT SetAutoLoad(gamenumT gnum)
const errorT ERROR_CodecUnsupFeat
uint date_GetYear(dateT date)
Manages memory databases that do not have associated files.
void deleteFilter(const char *filterId)
FullMove getMove(int ply_to_skip)
const byte * GetHomePawnData() const
FastGame getGame(const IndexEntry *ie) const
const uint NUM_RESULT_TYPES
const errorT ERROR_FileInUse
resultT GetResult() const
SortCache * createSortCache(const char *criteria)
Increment the reference count of a SortCache object matching criteria.
const Stats & getStats() const
Statistics.
idNumberT GetSite() const
size_t select(size_t row_offset, size_t row_count, const HFilter &filter, gamenumT *result) const
Retrieve the sorted list of games' ids.
static FullMove getMove(uint code, uint ply=0)
const errorT ERROR_BadArg
idNumberT GetEvent() const
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().
byte get(gamenumT gnum) const
errorT saveGame(Game *game, gamenumT replacedGameId=INVALID_GAMEID)
Add or replace a game into the database.
errorT endTransaction(gamenumT gameId=INVALID_GAMEID)
Update caches and flush the database's files.
const gamenumT INVALID_GAMEID
gamenumT GetAutoLoad() const
matSigT GetFinalMatSig() const
This class manages databases encoded in SCID format v4.
uint results[NUM_RESULT_TYPES]
size_t sortedPosition(gamenumT gameId, const HFilter &filter) const
Get the sorted position of a game.
errorT importGame(const scidBaseT *srcBase, uint gNum)
void beginTransaction()
This function must be called before modifying the games of the database.
const errorT ERROR_CompactRemove
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.
bool GetFlag(uint32_t mask) const
This class stores the database's names (players, events, sites and rounds).
int main(int argc, char *argv[])
const errorT ERROR_FileRead
ecoT eco_Reduce(ecoT eco)
ecoReduce() - maps eco to a smaller set
const errorT ERROR_UserCancel
This interface separates the logic of a database from its representation.
size_t sortedPosition(const char *criteria, const HFilter &filter, gamenumT gameId)
Get the sorted position of a game.
errorT saveGameHelper(Game *game, gamenumT gameId)
static errorT parseGames(const TProgress &progress, TSource &src, TDestFn destFn)
idNumberT GetRound() const
idNumberT GetWhite() const
bool GetDeleteFlag() const
Stats(const scidBaseT *dbase)
const Eco * getEcoStats(const char *ecoStr) const
byte GetStoredLineCode() const
int GetBadNameIdCount() const
GetBadNameIdCount() - return the number of invalid name handles.
errorT getCompactStat(unsigned long long *n_deleted, unsigned long long *n_unused, unsigned long long *n_sparse, unsigned long long *n_badNameId)
void releaseSortCache(const char *criteria)
Decrement the reference count of the SortCache object matching criteria.
std::string composeFilter(const std::string &mainFilter, const std::string &maskFilter) const
idNumberT GetBlack() const
errorT copyHeaderInfo(const Index &src)
Header setter functions.
uint nResults[NUM_RESULT_TYPES]
uint flagCount[IndexEntry::IDX_NUM_FLAGS]
errorT importGames(const scidBaseT *srcBase, const HFilter &filter, const Progress &progress)
const errorT ERROR_FileReadOnly
errorT compact(const Progress &progress)
This class sorts games contained into an Index.
bool report(size_t done, size_t total) const
std::vector< scidBaseT::TreeStat > getTreeStat(const HFilter &filter)
gamenumT numGames() const
ecoT eco_FromString(const char *ecoStr)
versionT GetVersion() const
uint32_t GetLength() const
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...
errorT open(const char *filename, fileModeT fmode)
Opens/creates a PGN database.
errorT Open(ICodecDatabase::Codec dbtype, fileModeT mode, const char *filename=0, const Progress &progress=Progress())
const versionT SCID_VERSION
const errorT ERROR_FileMode
uint64_t GetOffset() const
const NameBase * getNameBase() const
const errorT ERROR_NameDataLoss
Implements the CodecSCID4 class that manages databases encoded in SCID format v4. ...
const char * parseErrors()
Returns the list of errors produced by parseNext() calls.
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.
std::string getSAN(colorT *toMove=0) const