Scid  4.7.0
codec_scid4.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-2018 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 
20 /** @file
21  * Implements the CodecSCID4 class that manages databases encoded in SCID
22  * format v4.
23  */
24 
25 #ifndef CODEC_SCID4_H
26 #define CODEC_SCID4_H
27 
28 #include "codec_native.h"
29 #include "filebuf.h"
30 #include <limits>
31 
32 /**
33  * This class manages databases encoded in SCID format v4.
34  */
35 class CodecSCID4 : public CodecNative<CodecSCID4> {
36  std::vector<std::string> filenames_;
37  FilebufAppend gfile_;
38  char gamecache_[1ULL << 17];
39 
40  enum : uint64_t {
41  LIMIT_GAMEOFFSET = 1ULL << 32,
42  LIMIT_GAMELEN = 1ULL << 17,
43  LIMIT_NUMGAMES = 16777214ULL, // Three bytes -1 because GetAutoLoad uses
44  // 0 to mean "no autoload"
45  LIMIT_NAMELEN = 255
46  };
47 
48 public: // ICodecDatabase interface
49  Codec getType() const final { return ICodecDatabase::SCID4; }
50 
51  /**
52  * Returns the full path of the three files (index, namebase and gamefile)
53  * used by the database.
54  */
55  std::vector<std::string> getFilenames() const final { return filenames_; };
56 
57  std::vector<std::pair<const char*, std::string>>
58  getExtraInfo() const final {
59  std::vector<std::pair<const char*, std::string>> res;
60  res.emplace_back("type", std::to_string(idx_->GetType()));
61  res.emplace_back("description", idx_->GetDescription());
62  res.emplace_back("autoload", std::to_string(idx_->GetAutoLoad()));
63  res.emplace_back("flag1",
65  res.emplace_back("flag2",
67  res.emplace_back("flag3",
69  res.emplace_back("flag4",
71  res.emplace_back("flag5",
73  res.emplace_back("flag6",
75  return res;
76  }
77 
78  const byte* getGameData(uint64_t offset, uint32_t length) final {
79  if (offset >= gfile_.size())
80  return NULL;
81  if (length >= LIMIT_GAMELEN)
82  return NULL;
83 
84  if (gfile_.pubseekpos(offset) == -1)
85  return NULL;
86  if (gfile_.sgetn(gamecache_, length) != std::streamsize(length))
87  return NULL;
88 
89  return reinterpret_cast<const byte*>(gamecache_);
90  }
91 
92  errorT flush() final;
93 
94  errorT dyn_open(fileModeT, const char*, const Progress&, Index*,
95  NameBase*) final;
96 
97 public: // CodecNative interface
98  /**
99  * Stores the data into the .sg4 file.
100  * @param src: valid pointer to a buffer that contains the game data
101  * (encoded in native format).
102  * @param length: the length of the buffer @e src (in bytes).
103  * @returns
104  * - on success, a @e std::pair containing OK and the offset of the stored
105  * data (needed for retrieving the data with getGameData()).
106  * - on failure, a @e std::pair containing an error code and 0.
107  */
108  std::pair<errorT, uint64_t> dyn_addGameData(const byte* src,
109  size_t length) {
110  ASSERT(src != 0);
111  const char* data = reinterpret_cast<const char*>(src);
112 
113  if (length >= LIMIT_GAMELEN)
114  return std::make_pair(ERROR_GameLengthLimit, 0);
115 
116  // The SCID4 format uses 32-bits to store games' offset.
117  uint64_t offset = gfile_.size();
118  if (offset >= LIMIT_GAMEOFFSET - length)
119  return std::make_pair(ERROR_OffsetLimit, 0);
120 
121  // The SCID4 format stores games into blocks of 128KB.
122  // If the current block does not have enough space, we fill it with
123  // random data and use the next one.
124  uint64_t blockSpace = LIMIT_GAMELEN - (offset % LIMIT_GAMELEN);
125  if (blockSpace < length) {
126  errorT err = gfile_.append(data, blockSpace);
127  if (err != OK)
128  return std::make_pair(err, 0);
129  offset += blockSpace;
130  }
131 
132  errorT err = gfile_.append(data, length);
133  return std::make_pair(err, offset);
134  }
135 
136  /**
137  * Given a name (string), retrieve the corresponding ID.
138  * The name is added to @e nb_ if do not already exists in the NameBase.
139  * @param nt: nameT type of the name to retrieve.
140  * @param name: the name to retrieve.
141  * @returns
142  * - on success, a @e std::pair containing OK and the ID.
143  * - on failure, a @e std::pair containing an error code and 0.
144  */
145  std::pair<errorT, idNumberT> dyn_addName(nameT nt, const char* name) {
146  const idNumberT MAX_ID[] = {
147  1048575, /* Player names: Maximum of 2^20 -1 = 1,048,575 */
148  524287, /* Event names: Maximum of 2^19 -1 = 524,287 */
149  524287, /* Site names: Maximum of 2^19 -1 = 524,287 */
150  262143 /* Round names: Maximum of 2^18 -1 = 262,143 */
151  };
152  return nb_->addName(nt, name, LIMIT_NAMELEN, MAX_ID[nt]);
153  }
154 
155  /**
156  * Add an IndexEntry to @e idx_.
157  * @param ie: the IndexEntry object to add.
158  * @returns OK if successful or an error code.
159  */
161  auto nGames = idx_->GetNumGames();
162  if (nGames >= LIMIT_NUMGAMES)
163  return ERROR_NumGamesLimit;
164 
165  return idx_->WriteEntry(&ie, nGames);
166  }
167 
168  /**
169  * Replace an IndexEntry.
170  * @param ie: the IndexEntry with the new data.
171  * @param replaced: valid gamenumT of the game to be replaced.
172  * @returns OK if successful or an error code.
173  */
175  return idx_->WriteEntry(&ie, replaced);
176  }
177 
178 private:
179  errorT readIndex(const Progress& progress);
180 };
181 
182 #endif
unsigned char byte
Definition: common.h:89
const char * GetCustomFlagDesc(byte c) const
Definition: index.h:140
errorT append(const char_type *s, std::streamsize count)
Writes, at the end of the file, count characters from the character array whose first element is poin...
Definition: filebuf.h:223
const errorT ERROR_NumGamesLimit
Definition: error.h:59
errorT dyn_addIndexEntry(const IndexEntry &ie)
Add an IndexEntry to idx_.
Definition: codec_scid4.h:160
Definition: indexentry.h:291
Definition: indexentry.h:289
std::pair< errorT, idNumberT > addName(nameT nt, const char *name, size_t MAX_LEN, idNumberT MAX_ID)
Add a name (string) to the NameBase.
Definition: namebase.h:81
std::streamoff pubseekpos(std::streamoff pos)
Repositions the internal buffer or invoke filebuf::seekpos().
Definition: filebuf.h:252
const errorT OK
Definition: error.h:23
std::pair< errorT, idNumberT > dyn_addName(nameT nt, const char *name)
Given a name (string), retrieve the corresponding ID.
Definition: codec_scid4.h:145
Codec getType() const final
Returns the Codec type.
Definition: codec_scid4.h:49
const errorT ERROR_OffsetLimit
Definition: error.h:57
#define ASSERT(f)
Definition: common.h:59
uint GetType() const
Definition: index.h:137
Definition: misc.h:63
names
Definition: tablebase.tcl:257
gamenumT GetNumGames() const
Header getter functions.
Definition: index.h:136
Definition: indexentry.h:294
Definition: indexentry.h:292
gamenumT GetAutoLoad() const
Definition: index.h:144
This class manages databases encoded in SCID format v4.
Definition: codec_scid4.h:35
std::vector< std::string > getFilenames() const final
Returns the full path of the three files (index, namebase and gamefile) used by the database...
Definition: codec_scid4.h:55
std::pair< errorT, uint64_t > dyn_addGameData(const byte *src, size_t length)
Stores the data into the .sg4 file.
Definition: codec_scid4.h:108
uint32_t idNumberT
Definition: common.h:152
unsigned long long size() const
Returns the size of the file.
Definition: filebuf.h:210
errorT flush() final
Writes all pending output to the files.
Definition: indexentry.h:293
This class stores the database&#39;s names (players, events, sites and rounds).
Definition: namebase.h:33
errorT dyn_saveIndexEntry(const IndexEntry &ie, gamenumT replaced)
Replace an IndexEntry.
Definition: codec_scid4.h:174
This class stores the pointers to the Index and NameBase objects used by a native codec...
Definition: codec_native.h:43
Definition: index.h:58
unsigned short errorT
Definition: error.h:20
Implements CodecNative, which is used as base class by native codecs.
const errorT ERROR_GameLengthLimit
Definition: error.h:58
std::vector< std::pair< const char *, std::string > > getExtraInfo() const final
Returns a vector of tag pairs containing extra information about the database (type, description, autoload, etc..)
Definition: codec_scid4.h:58
errorT WriteEntry(const IndexEntry *ie, gamenumT idx)
WriteEntry() - modify a game in the Index.
Definition: index.cpp:160
Optimizes std::filebuf for random-access reading.
Definition: filebuf.h:184
const byte * getGameData(uint64_t offset, uint32_t length) final
Fetches the data of a game (excluding index info), encoded in native format.
Definition: codec_scid4.h:78
std::streamsize sgetn(char_type *s, std::streamsize count)
Invoke filebuf::xsgetn() and update filePos_.
Definition: filebuf.h:241
errorT dyn_open(fileModeT, const char *, const Progress &, Index *, NameBase *) final
Opens/Creates a database.
const char * GetDescription() const
Definition: index.h:139
unsigned nameT
Definition: common.h:153
Extends the std:filebuf class with performance improvements.
Definition: indexentry.h:290
uint gamenumT
Definition: common.h:163
fileModeT
Definition: common.h:136
Definition: indexentry.h:54