Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
index.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 1999-2002 Shane Hudson
3 * Copyright (c) 2006-2009 Pascal Georges
4 * Copyright (C) 2014-2016 Fulvio Benini
5 
6 * This file is part of Scid (Shane's Chess Information Database).
7 *
8 * Scid is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation.
11 *
12 * Scid is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Scid. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef SCID_INDEX_H
22 #define SCID_INDEX_H
23 
24 #include "common.h"
25 #include "containers.h"
26 #include "date.h"
27 #include "indexentry.h"
28 #include "filebuf.h"
29 #include "hfilter.h"
30 #include <array>
31 #include <string>
32 #include <vector>
33 #include <cstring>
34 
35 class NameBase;
36 
37 //////////////////////////////////////////////////////////////////////
38 // Index: Constants
39 
40 const char INDEX_SUFFIX[] = ".si4";
41 const char OLD_INDEX_SUFFIX[] = ".si3";
42 
43 // Descriptions can be up to 107 bytes long.
44 const uint SCID_DESC_LENGTH = 107;
47 
48 // Header on-disk size: magic=8, version=2, numGames=3, baseType=4, autoLoad=3
49 // Description length = 111 bytes including trailing '\0'.
50 // Custom flag desc length = 9 bytes including trailing '\0'.
51 // So total is 128 bytes + 9*6 = 182 bytes for the whole header.
54 
55 //////////////////////////////////////////////////////////////////////
56 // Index: Class Definition
57 
58 class Index
59 {
60 private:
61  // The complete index will be loaded in memory and can be pretty huge.
62  // To avoid the slow reallocation when adding games we split the data in chunks.
63  // CHUNKSHIFT is the base-2 logarithm of the number of index entries allocated as one chunk.
64  // i.e 16 = 2^16 = 65536 (total size of one chunk: 65536*48 = 3MB)
65  VectorChunked<IndexEntry, 16> entries_; // A two-level array of the entire index.
66  Filebuf* FilePtr; // filehandle for opened index file.
67  fileModeT fileMode_; // Mode: e.g. FILE_WRITEONLY
68  int nInvalidNameId_;
69  gamenumT seqWrite_;
70 
71  struct { // one at the start of the index file.
72  versionT version; // version number. 2 bytes.
73  uint baseType; // Type, e.g. tournament, theory, etc.
74  gamenumT numGames; // number of games in file.
75  gamenumT autoLoad; // game number to autoload: 0=none, 1=1st, >numGames=last
76  // description is a fixed-length string describing the database.
78  // short description (8 chars) for the CUSTOM_FLAG_MAX bits for CUSTOM flags
80  bool dirty_; // If true, Header needs rewriting to disk.
81  } Header;
82 
83  friend class CodecSCID4;
84 
85 public:
86  Index() { Init(); }
87  Index(const Index&);
88  Index& operator=(const Index&);
89  ~Index() { Clear(); }
90 
91  errorT Open(const char* filename, fileModeT fmode);
92  errorT Create(const char* filename);
93  errorT Close() { return Clear(); }
94 
95  const IndexEntry* GetEntry (gamenumT g) const {
96  ASSERT(g < GetNumGames());
97  return &(entries_[g]);
98  }
99 
100  /**
101  * GetBadNameIdCount() - return the number of invalid name handles.
102  *
103  * To save space, avoiding duplicates, the index keep handles
104  * to strings stored in the namebase file.
105  * If one of the two files is corrupted, the index may have
106  * handles to strings that do not exists.
107  * This functions returns the number of invalid name handles.
108  */
109  int GetBadNameIdCount() const { return nInvalidNameId_; }
110 
111  /**
112  * Counts how many times every names contained in @e nb is used.
113  * @param nb: the NameBase linked to this Index
114  * @returns an array of std::vectors containing the count of each name.
115  */
116  std::array<std::vector<int>, NUM_NAME_TYPES>
117  calcNameFreq(const NameBase& nb) const {
118  std::array<std::vector<int>, NUM_NAME_TYPES> resVec;
119  for (nameT n = NAME_PLAYER; n < NUM_NAME_TYPES; n++) {
120  resVec[n].resize(nb.GetNumNames(n), 0);
121  }
122  for (gamenumT i = 0, n = GetNumGames(); i < n; i++) {
123  const IndexEntry* ie = GetEntry(i);
124  resVec[NAME_PLAYER][ie->GetWhite()] += 1;
125  resVec[NAME_PLAYER][ie->GetBlack()] += 1;
126  resVec[NAME_EVENT][ie->GetEvent()] += 1;
127  resVec[NAME_SITE][ie->GetSite()] += 1;
128  resVec[NAME_ROUND][ie->GetRound()] += 1;
129  }
130  return resVec;
131  }
132 
133  /**
134  * Header getter functions
135  */
136  gamenumT GetNumGames () const { return Header.numGames; }
137  uint GetType () const { return Header.baseType; }
138  versionT GetVersion () const { return Header.version; }
139  const char* GetDescription () const { return Header.description; }
140  const char* GetCustomFlagDesc (byte c) const {
141  if (c < IndexEntry::IDX_FLAG_CUSTOM1 || c > IndexEntry::IDX_FLAG_CUSTOM6) return 0;
142  return Header.customFlagDesc[c - IndexEntry::IDX_FLAG_CUSTOM1];
143  }
145  return (Header.autoLoad <= Header.numGames) ? Header.autoLoad : Header.numGames;
146  }
147 
148  /**
149  * Header setter functions
150  */
152  if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
153  Header.baseType = src.Header.baseType;
154  Header.autoLoad = src.Header.autoLoad;
155  std::memcpy(Header.description, src.Header.description, sizeof Header.description);
156  std::memcpy(Header.customFlagDesc, src.Header.customFlagDesc, sizeof Header.customFlagDesc);
157  Header.dirty_ = true;
158  return flush();
159  }
161  if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
162  Header.baseType = t;
163  Header.dirty_ = true;
164  return flush();
165  }
166  errorT SetDescription (const char* str) {
167  if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
168  strncpy(Header.description, str, SCID_DESC_LENGTH);
169  Header.description[SCID_DESC_LENGTH] = 0;
170  Header.dirty_ = true;
171  return flush();
172  }
173  errorT SetCustomFlagDesc (byte c, const char* str) {
174  if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
175  if (c < IndexEntry::IDX_FLAG_CUSTOM1 || c > IndexEntry::IDX_FLAG_CUSTOM6) return ERROR_BadArg;
176  char* flagDesc = Header.customFlagDesc[c - IndexEntry::IDX_FLAG_CUSTOM1];
177  strncpy(flagDesc, str, CUSTOM_FLAG_DESC_LENGTH);
178  flagDesc[CUSTOM_FLAG_DESC_LENGTH] = 0;
179  Header.dirty_ = true;
180  return flush();
181  }
183  if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
184  Header.autoLoad = gnum;
185  Header.dirty_ = true;
186  return flush();
187  }
188 
189  /**
190  * FetchEntry() - return a modifiable pointer to a game's IndexEntry
191  *
192  * The pointer returned by this function allow to modify the IndexEntry
193  * informations of a game. If modified, the IndexEntry object must be
194  * passed to WriteEntry() to write the changes to the disks.
195  * This functions is very error prone. For example:
196  * IndexEntry* ie = FetchEntry(0);
197  * ie->SetWhiteName(nb, "New player with white");
198  * oops(); // the function oops() may call GetEntry(0) and get a messy object.
199  * ie->SetBlackName(nb, "New player with black");
200  *
201  * A safer alternative is to create a temporary copy of the IndexEntry object
202  * returned by GetEntry() and then write all the changes in a single step
203  */
205  ASSERT(g < GetNumGames());
206  return &(entries_[g]);
207  }
208 
209  /**
210  * WriteEntry() - modify a game in the Index
211  */
212  errorT WriteEntry(const IndexEntry* ie, gamenumT idx);
213 
214  /**
215  * flush() - writes all cached data to the file
216  */
218  if (FilePtr == 0) return OK;
219  errorT errHeader = (Header.dirty_) ? WriteHeader() : OK;
220  errorT errSync = (FilePtr->pubsync() != 0) ? ERROR_FileWrite : OK;
221  return (errHeader == OK) ? errSync : errHeader;
222  }
223 
224 private:
225  void Init ();
226  errorT Clear ();
227  errorT WriteHeader ();
228 };
229 
230 
231 #endif // #ifdef SCID_INDEX_H
232 
233 //////////////////////////////////////////////////////////////////////
234 // EOF: index.h
235 //////////////////////////////////////////////////////////////////////
236 
gamenumT autoLoad
Definition: index.h:75
unsigned char byte
Definition: common.h:89
const char * GetCustomFlagDesc(byte c) const
Definition: index.h:140
errorT SetAutoLoad(gamenumT gnum)
Definition: index.h:182
const uint INDEX_HEADER_SIZE
Definition: index.h:52
Definition: indexentry.h:289
const errorT OK
Definition: error.h:23
const uint CUSTOM_FLAG_DESC_LENGTH
Definition: index.h:45
unsigned short versionT
Definition: common.h:38
idNumberT GetSite() const
Definition: indexentry.h:105
const errorT ERROR_FileWrite
Definition: error.h:32
std::array< std::vector< int >, NUM_NAME_TYPES > calcNameFreq(const NameBase &nb) const
Counts how many times every names contained in nb is used.
Definition: index.h:117
#define ASSERT(f)
Definition: common.h:59
~Index()
Definition: index.h:89
const char OLD_INDEX_SUFFIX[]
Definition: index.h:41
const errorT ERROR_BadArg
Definition: error.h:28
uint GetType() const
Definition: index.h:137
const uint SCID_DESC_LENGTH
Definition: index.h:44
idNumberT GetEvent() const
Definition: indexentry.h:104
bool dirty_
Definition: index.h:80
const IndexEntry * GetEntry(gamenumT g) const
Definition: index.h:95
gamenumT GetNumGames() const
Header getter functions.
Definition: index.h:136
uint baseType
Definition: index.h:73
Definition: indexentry.h:294
errorT Close()
Definition: index.h:93
gamenumT GetAutoLoad() const
Definition: index.h:144
This class manages databases encoded in SCID format v4.
Definition: codec_scid4.h:35
Index()
Definition: index.h:86
versionT version
Definition: index.h:72
This class stores the database&#39;s names (players, events, sites and rounds).
Definition: namebase.h:33
Index & operator=(const Index &)
errorT SetDescription(const char *str)
Definition: index.h:166
uint32_t uint
Definition: common.h:91
errorT flush()
flush() - writes all cached data to the file
Definition: index.h:217
idNumberT GetRound() const
Definition: indexentry.h:106
idNumberT GetWhite() const
Definition: indexentry.h:98
IndexEntry * FetchEntry(gamenumT g)
FetchEntry() - return a modifiable pointer to a game&#39;s IndexEntry.
Definition: index.h:204
Definition: index.h:58
int GetBadNameIdCount() const
GetBadNameIdCount() - return the number of invalid name handles.
Definition: index.h:109
Clear
Definition: game.tcl:8
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
errorT Open(const char *filename, fileModeT fmode)
Definition: index.cpp:80
errorT SetType(uint t)
Definition: index.h:160
const char INDEX_SUFFIX[]
Definition: index.h:40
errorT Create(const char *filename)
Definition: index.cpp:56
errorT WriteEntry(const IndexEntry *ie, gamenumT idx)
WriteEntry() - modify a game in the Index.
Definition: index.cpp:160
char description[SCID_DESC_LENGTH+1]
Definition: index.h:77
Adds some helper functions to std::filebuf:
Definition: filebuf.h:35
versionT GetVersion() const
Definition: index.h:138
const char * GetDescription() const
Definition: index.h:139
char customFlagDesc[CUSTOM_FLAG_MAX][CUSTOM_FLAG_DESC_LENGTH+1]
Definition: index.h:79
idNumberT GetNumNames(nameT nt) const
Definition: namebase.h:178
const uint OLD_INDEX_HEADER_SIZE
Definition: index.h:53
unsigned nameT
Definition: common.h:153
gamenumT numGames
Definition: index.h:74
Extends the std:filebuf class with performance improvements.
uint gamenumT
Definition: common.h:163
fileModeT
Definition: common.h:136
const errorT ERROR_FileMode
Definition: error.h:38
errorT SetCustomFlagDesc(byte c, const char *str)
Definition: index.h:173
const uint CUSTOM_FLAG_MAX
Definition: index.h:46
Definition: indexentry.h:54