48 const char* NAMEBASE_MAGIC =
"Scid.sn";
59 auto& map = std::get<0>(nb_data);
60 auto& names = std::get<1>(nb_data);
61 auto& eloV = std::get<2>(nb_data);
64 if (file.Open(filename, fmode) !=
OK)
67 char Header_magic[9] = {0};
68 file.sgetn(Header_magic, 8);
69 if (strcmp(Header_magic, NAMEBASE_MAGIC) != 0)
78 Header_numNames[
NAME_PLAYER] = file.ReadThreeBytes();
79 Header_numNames[
NAME_EVENT] = file.ReadThreeBytes();
80 Header_numNames[
NAME_SITE] = file.ReadThreeBytes();
81 Header_numNames[
NAME_ROUND] = file.ReadThreeBytes();
86 obsolete_maxFreq[
NAME_PLAYER] = file.ReadThreeBytes();
87 obsolete_maxFreq[
NAME_EVENT] = file.ReadThreeBytes();
88 obsolete_maxFreq[
NAME_SITE] = file.ReadThreeBytes();
89 obsolete_maxFreq[
NAME_ROUND] = file.ReadThreeBytes();
94 names[nt].resize(Header_numNames[nt]);
97 for (
idNumberT i = 0; i < Header_numNames[nt]; i++) {
98 if (Header_numNames[nt] >= 65536) {
99 id = file.ReadThreeBytes();
101 id = file.ReadTwoBytes();
107 if (obsolete_maxFreq[nt] >= 65536) {
108 file.ReadThreeBytes();
109 }
else if (obsolete_maxFreq[nt] >= 256) {
118 int length = file.ReadOneByte();
119 int prefix = (i > 0) ? file.ReadOneByte() : 0;
123 char*
name =
new char[length + 1];
124 std::copy_n(prevName.c_str(), prefix,
name);
125 std::streamsize extra_chars = length - prefix;
126 if (extra_chars != file.sgetn(name + prefix, extra_chars)) {
131 prevName.assign(name, length);
133 if (
id < Header_numNames[nt] && names[nt][
id] == 0) {
134 names[nt][id].reset(name);
135 map[nt].insert(map[nt].end(), std::make_pair(name,
id));
142 if (map[nt].
size() != names[nt].
size())
149 bool assert_sorted(
const char* str1,
const char* str2) {
164 return static_cast<uint>(*str1) <
static_cast<uint>(*str2);
173 template <
typename TCont,
typename TFreq>
174 errorT namefileWrite(
const char* filename,
const TCont& names_ids,
180 file.sputn(NAMEBASE_MAGIC, 8);
187 ASSERT(1ULL << 24 > names_ids[NAME_PLAYER].
size());
200 auto it = std::max_element(freq[nt].begin(), freq[nt].end());
201 maxFreq[nt] = (it == freq[nt].end()) ? 0 : *it;
207 const char* prevName =
nullptr;
208 size_t numNames = names_ids[nt].size();
209 for (
const auto& it : names_ids[nt]) {
210 const char* name = it.first;
213 ASSERT(prevName ==
nullptr || assert_sorted(prevName, name));
216 if (numNames >= 65536) {
224 if (maxFreq[nt] >= 65536) {
226 }
else if (maxFreq[nt] >= 256) {
233 ASSERT(strlen(name) < 256);
234 byte length =
static_cast<byte>(strlen(name));
241 file.sputn(name + prefix, (length - prefix));
259 auto ReadOneByte = [&buf_it]() {
260 uint8_t res = *buf_it++;
263 auto ReadTwoBytes = [&ReadOneByte]() {
264 uint16_t high = ReadOneByte();
265 uint16_t res = (high << 8) | ReadOneByte();
268 auto ReadFourBytes = [&ReadTwoBytes]() {
269 uint32_t high = ReadTwoBytes();
270 uint32_t res = (high << 16) | ReadTwoBytes();
281 uint32_t len_Low = ReadTwoBytes();
282 uint32_t len_flags = (version < 400) ? 0 : ReadOneByte();
283 ie->
SetLength(((len_flags & 0x80) << 9) | len_Low);
284 uint32_t Flags = ReadTwoBytes();
286 ie->
SetFlag(((len_flags & 0x3F) << 16) | Flags,
true);
295 uint32_t WhiteBlack_High = ReadOneByte();
296 uint32_t WhiteID_Low = ReadTwoBytes();
297 ie->
SetWhite(((WhiteBlack_High & 0xF0) << 12) | WhiteID_Low);
298 uint32_t BlackID_Low = ReadTwoBytes();
299 ie->
SetBlack(((WhiteBlack_High & 0x0F) << 16) | BlackID_Low);
300 uint32_t EventSiteRnd_High = ReadOneByte();
301 uint32_t EventID_Low = ReadTwoBytes();
302 ie->
SetEvent(((EventSiteRnd_High & 0xE0) << 11) | EventID_Low);
303 uint32_t SiteID_Low = ReadTwoBytes();
304 ie->
SetSite(((EventSiteRnd_High & 0x1C) << 14) | SiteID_Low);
305 uint32_t RoundID_Low = ReadTwoBytes();
306 ie->
SetRound(((EventSiteRnd_High & 0x03) << 16) | RoundID_Low);
310 uint32_t varCounts = ReadTwoBytes();
322 uint32_t date_edate = ReadFourBytes();
323 uint32_t
date = date_edate & 0xFFFFF;
325 uint32_t edate = date_edate >> 20;
331 eyear = (eyear < 4) ? 0 : eyear - 4;
337 uint16_t whiteElo = ReadTwoBytes();
340 uint16_t blackElo = ReadTwoBytes();
346 uint32_t finalMatSig = ReadFourBytes();
353 uint16_t NumHalfMoves = ReadOneByte();
354 uint16_t pawnData0 = ReadOneByte();
357 *pb++ = pawnData0 & 0x3F;
364 if (filename ==
nullptr || idx ==
nullptr || nb ==
nullptr)
366 if (*filename ==
'\0')
371 filenames_.resize(3);
372 filenames_[0] = std::string(filename) +
".si4";
373 filenames_[1] = std::string(filename) +
".sn4";
374 filenames_[2] = std::string(filename) +
".sg4";
376 errorT err = gfile_.
open(filenames_[2], fMode);
381 err = idx->
Create(filename);
383 err = namefileWrite(filenames_[1].c_str(),
nb_->
getNames(),
387 err = idx->
Open(filename, fMode);
389 err = namefileRead(filenames_[1].c_str(), fMode, *
nb_);
391 err = readIndex(progress);
404 err = namefileWrite(filenames_[1].c_str(),
nb_->
getNames(),
409 return (err ==
OK) ? errGfile : err;
427 if (unknown.first !=
OK)
429 ie->SetWhite(unknown.second);
434 if (unknown.first !=
OK)
436 ie->SetBlack(unknown.second);
441 if (unknown.first !=
OK)
443 ie->SetEvent(unknown.second);
448 if (unknown.first !=
OK)
450 ie->SetSite(unknown.second);
455 if (unknown.first !=
OK)
457 ie->SetRound(unknown.second);
463 auto idxFile =
idx_->FilePtr;
469 for (
gamenumT gNum = 0; idxFile->sgetc() != EOF; ++gNum) {
473 if ((gNum % 8192) == 0) {
474 if (!progress.
report(gNum, nGames))
479 if (idxFile->sgetn(buf, nBytes) != nBytes)
485 if (!validateNameIDs(ie))
496 idx_->nInvalidNameId_ = nUnknowIDs;
void SetNumHalfMoves(ushort b)
void SetBlack(idNumberT id)
uint date_GetYear(dateT date)
int WriteFourBytes(uint32_t value)
Writes a 32-bit unsigned integer.
const uint INDEX_ENTRY_SIZE
void resize(size_t count)
const byte * GetHomePawnData() const
const errorT ERROR_BadMagic
std::pair< errorT, idNumberT > dyn_addName(nameT nt, const char *name)
Given a name (string), retrieve the corresponding ID.
const errorT ERROR_FileWrite
void SetBlackRatingType(byte b)
std::array< std::vector< int >, NUM_NAME_TYPES > calcNameFreq(const NameBase &nb) const
Counts how many times every names contained in nb is used.
int WriteOneByte(byte value)
Writes a 8-bit unsigned integer.
void AddElo(idNumberT id, eloT elo)
A NameBase stores the max ELO for each player.
errorT open(const std::string &filename, fileModeT fmode)
Opens a file and store its size.
void SetWhite(idNumberT id)
gamenumT GetNumGames() const
Header getter functions.
int WriteThreeBytes(uint32_t value)
Writes a 24-bit unsigned integer.
uint strPrefix(const char *s1, const char *s2)
void SetRound(idNumberT id)
void SetStoredLineCode(byte b)
void SetEcoCode(ecoT eco)
#define DATE_MAKE(y, m, d)
errorT flush() final
Writes all pending output to the files.
int WriteTwoBytes(uint32_t value)
Writes a 16-bit unsigned integer.
This class stores the database's names (players, events, sites and rounds).
const errorT ERROR_FileRead
void SetRawNagCount(unsigned x)
void SetRawCommentCount(unsigned x)
int pubsync()
Invokes std::filebuf::sync() to write all pending output to the file.
const errorT ERROR_UserCancel
errorT flush()
flush() - writes all cached data to the file
idNumberT GetWhite() const
void SetSite(idNumberT id)
IndexEntry * FetchEntry(gamenumT g)
FetchEntry() - return a modifiable pointer to a game's IndexEntry.
void SetLength(size_t length)
errorT Open(const char *filename, fileModeT fmode)
Opens a file.
void SetEventDate(dateT edate)
const errorT ERROR_CorruptData
idNumberT GetBlack() const
errorT Open(const char *filename, fileModeT fmode)
std::tuple< decltype(idx_) &, decltype(names_) &, decltype(eloV_) & > getData()
errorT Create(const char *filename)
bool report(size_t done, size_t total) const
void SetWhiteElo(eloT elo)
void decodeIndexEntry(const char *buf_it, versionT version, IndexEntry *ie)
Decode SCID4 (or SCID3) data into an IndexEntry object.
void SetFinalMatSig(matSigT ms)
void SetResult(resultT res)
Adds some helper functions to std::filebuf:
const errorT ERROR_Corrupt
errorT dyn_open(fileModeT, const char *, const Progress &, Index *, NameBase *) final
Opens/Creates a database.
void SetEvent(idNumberT id)
idNumberT GetNumNames(nameT nt) const
void SetFlag(uint32_t flagMask, bool set)
void SetBlackElo(eloT elo)
decltype(idx_) const & getNames() const
const uint OLD_INDEX_ENTRY_SIZE
const errorT ERROR_NameDataLoss
Implements the CodecSCID4 class that manages databases encoded in SCID format v4. ...
void SetWhiteRatingType(byte b)
void SetOffset(uint64_t offset)
int strCompare(const char *s1, const char *s2)
uint date_GetMonth(dateT date)
const errorT ERROR_FileOpen
void SetRawVariationCount(unsigned x)
uint date_GetDay(dateT date)