Scid  4.6.5
index.cpp
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 #include "index.h"
22 #include "namebase.h"
23 #include <cstring>
24 
25 void Index::Init ()
26 {
27  strCopy (Header.magic, INDEX_MAGIC);
28  Header.numGames = 0;
29  Header.version = SCID_VERSION;
30  Header.baseType = 0;
31  Header.autoLoad = 1;
32  Header.description[0] = 0;
33  std::memset(Header.customFlagDesc, 0, sizeof(Header.customFlagDesc));
34  Header.dirty_ = false;
35  FilePtr = NULL;
36  fileMode_ = FMODE_Memory;
37  nInvalidNameId_ = 0;
38  seqWrite_ = 0;
39  entries_.resize(0);
40 }
41 
42 errorT Index::Clear ()
43 {
44  errorT res = flush();
45  delete FilePtr;
46  Init();
47  return res;
48 }
49 
50 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51 // Index::CreateIndexFile():
52 // Creates and opens a new empty index file.
53 //
54 errorT
55 Index::Create(const char* filename)
56 {
57  ASSERT(filename != 0);
58 
59  Clear();
60  FilePtr = new Filebuf;
61  std::string fname = filename;
62  fname += INDEX_SUFFIX;
63  //Check that the file does not exists and then create it
64  if (FilePtr->Open(fname.c_str(), FMODE_ReadOnly) == OK ||
65  FilePtr->Open(fname.c_str(), FMODE_Create) != OK) {
66  delete FilePtr;
67  FilePtr = NULL;
68  return ERROR_FileOpen;
69  }
70  fileMode_ = FMODE_Both;
71  return WriteHeader();
72 }
73 
74 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
75 // Index::Open():
76 // Open an index file and read the header.
77 //
78 errorT
79 Index::Open (const char* filename, fileModeT fmode)
80 {
81  ASSERT(filename != 0);
82 
83  Clear();
84  if (fmode == FMODE_WriteOnly) return ERROR_FileMode;
85  FilePtr = new Filebuf;
86  std::string fname = filename;
87  fname += INDEX_SUFFIX;
88 
89  if (FilePtr->Open (fname.c_str(), fmode) != OK) {
90  delete FilePtr;
91  FilePtr = NULL;
92  return ERROR_FileOpen;
93  }
94 
95  FilePtr->sgetn(Header.magic, 8);
96  Header.magic[8] = 0;
97  if (strCompare (Header.magic, INDEX_MAGIC) != 0) {
98  delete FilePtr;
99  FilePtr = NULL;
100  return ERROR_BadMagic;
101  }
102 
103  Header.version = FilePtr->ReadTwoBytes ();
104  if (Header.version < SCID_OLDEST_VERSION || Header.version > SCID_VERSION) {
105  delete FilePtr;
106  FilePtr = NULL;
107  return ERROR_FileVersion;
108  }
109  if (Header.version != SCID_VERSION && fmode != FMODE_ReadOnly) {
110  //Old versions must be opened readonly
111  delete FilePtr;
112  FilePtr = NULL;
113  return ERROR_FileMode;
114  }
115 
116  Header.baseType = FilePtr->ReadFourBytes ();
117  Header.numGames = FilePtr->ReadThreeBytes ();
118  Header.autoLoad = FilePtr->ReadThreeBytes ();
119  FilePtr->sgetn(Header.description, SCID_DESC_LENGTH + 1);
120  Header.description[SCID_DESC_LENGTH] = 0;
121  if (Header.version >= 400) {
122  for (uint i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
123  FilePtr->sgetn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
124  Header.customFlagDesc[i][CUSTOM_FLAG_DESC_LENGTH] = 0;
125  }
126  }
127 
128  fileMode_ = fmode;
129  return OK;
130 }
131 
132 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
133 // Index::ReadEntireFile():
134 // Reads in the entire index into memory.
135 //
136 errorT
138 {
139  ASSERT (FilePtr != NULL);
140  ASSERT (entries_.size() == 0);
141 
142  if (fileMode_ == FMODE_WriteOnly) { return ERROR_FileMode; }
143  entries_.resize(Header.numGames);
144 
145  idNumberT maxIdx[NUM_NAME_TYPES];
146  for (nameT nt = NAME_PLAYER; nt < NUM_NAME_TYPES; nt++) {
147  maxIdx[nt] = nb->GetNumNames(nt);
148  }
149 
150  gamenumT gNum = 0;
151  for (; FilePtr->sgetc() != EOF; gNum++) {
152  if (gNum == Header.numGames) return ERROR_CorruptData;
153 
154  if ((gNum % 10000) == 0) {
155  if (!progress.report(gNum, Header.numGames)) return ERROR_UserCancel;
156  }
157 
158  IndexEntry* ie = &(entries_[gNum]);
159  errorT err = ie->Read(FilePtr, Header.version);
160  if (err != OK) return err;
161 
162  if (ie->GetWhite() >= maxIdx[NAME_PLAYER]) {
163  ie->SetWhiteName(nb, "?");
164  nInvalidNameId_++;
165  }
166  if (ie->GetBlack() >= maxIdx[NAME_PLAYER]) {
167  ie->SetBlackName(nb, "?");
168  nInvalidNameId_++;
169  }
170  if (ie->GetEvent() >= maxIdx[NAME_EVENT] ) {
171  ie->SetEventName(nb, "?");
172  nInvalidNameId_++;
173  }
174  if (ie->GetSite() >= maxIdx[NAME_SITE] ) {
175  ie->SetSiteName(nb, "?");
176  nInvalidNameId_++;
177  }
178  if (ie->GetRound() >= maxIdx[NAME_ROUND] ) {
179  ie->SetRoundName(nb, "?");
180  nInvalidNameId_++;
181  }
182 
183  eloT eloW = ie->GetWhiteElo();
184  if (eloW > 0) nb->AddElo (ie->GetWhite(), eloW);
185  eloT eloB = ie->GetBlackElo();
186  if (eloB > 0) nb->AddElo (ie->GetBlack(), eloB);
187  }
188  progress.report(1,1);
189 
190  if (gNum != Header.numGames) return ERROR_FileRead;
191  if (nInvalidNameId_ != 0) return ERROR_NameDataLoss;
192  return OK;
193 }
194 
195 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196 // Index::WriteHeader():
197 // Write the header to the open index file.
198 //
199 errorT
200 Index::WriteHeader ()
201 {
202  ASSERT(FilePtr != NULL);
203  if (FilePtr->pubseekpos(0) != std::streampos(0)) return ERROR_FileWrite;
204 
205  seqWrite_ = 0;
206  size_t n = 0;
207  n += FilePtr->sputn(Header.magic, 8);
208  n += FilePtr->WriteTwoBytes (Header.version);
209  n += FilePtr->WriteFourBytes (Header.baseType);
210  n += FilePtr->WriteThreeBytes (Header.numGames);
211  n += FilePtr->WriteThreeBytes (Header.autoLoad);
212  n += FilePtr->sputn(Header.description, SCID_DESC_LENGTH + 1);
213  for (size_t i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
214  n += FilePtr->sputn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
215  }
216  if (n != INDEX_HEADER_SIZE || FilePtr->pubsync() == -1) return ERROR_FileWrite;
217  Header.dirty_ = false;
218  return OK;
219 }
220 
221 errorT Index::write (const IndexEntry* ie, gamenumT idx)
222 {
223  if (idx > Header.numGames) return ERROR_BadArg;
224  if (idx >= MAX_GAMES) return ERROR_IndexFull;
225  if (fileMode_ == FMODE_ReadOnly) { return ERROR_FileMode; }
226 
227  if (idx == Header.numGames) {
228  entries_.push_back(*ie);
229  Header.numGames++;
230  Header.dirty_ = true;
231  } else {
232  IndexEntry* copyToMemory = &(entries_[idx]);
233  *copyToMemory = *ie;
234  }
235  if (FilePtr == NULL) return OK;
236 
237  if ((seqWrite_ == 0) || (idx != seqWrite_ + 1)) {
238  std::streampos pos = INDEX_ENTRY_SIZE * idx + INDEX_HEADER_SIZE;
239  if (FilePtr->pubseekpos(pos) != pos) {
240  seqWrite_ = 0;
241  return ERROR_FileWrite;
242  }
243  }
244  errorT res = ie->Write (FilePtr, Header.version);
245  seqWrite_ = (res == OK) ? idx : 0;
246  return res;
247 }
248 
249 //////////////////////////////////////////////////////////////////////
250 // EOF: index.cpp
251 //////////////////////////////////////////////////////////////////////
252 
const uint INDEX_HEADER_SIZE
Definition: index.h:55
const versionT SCID_OLDEST_VERSION
Definition: common.h:50
bool report(size_t done, size_t total) const
Definition: misc.h:136
int WriteFourBytes(uint32_t value)
Writes a 32-bit unsigned integer.
Definition: filebuf.h:161
const uint INDEX_ENTRY_SIZE
Definition: indexentry.h:41
void resize(size_t count)
Definition: misc.h:99
idNumberT GetEvent() const
Definition: indexentry.h:127
uint idNumberT
Definition: namebase.h:39
const errorT OK
Definition: error.h:23
const errorT ERROR_BadMagic
Definition: error.h:35
const uint CUSTOM_FLAG_DESC_LENGTH
Definition: index.h:48
errorT Write(T *file, versionT version) const
Definition: indexentry.h:584
const errorT ERROR_FileWrite
Definition: error.h:32
#define ASSERT(f)
Definition: common.h:67
void AddElo(idNumberT id, eloT elo)
Definition: namebase.h:101
const errorT ERROR_BadArg
Definition: error.h:28
const uint SCID_DESC_LENGTH
Definition: index.h:47
Definition: misc.h:124
uint16_t ReadTwoBytes()
Reads a 16-bit unsigned integer.
Definition: filebuf.h:117
int WriteThreeBytes(uint32_t value)
Writes a 24-bit unsigned integer.
Definition: filebuf.h:152
eloT GetBlackElo() const
Definition: indexentry.h:252
void push_back(const T &e)
Definition: misc.h:117
const gamenumT MAX_GAMES
Definition: index.h:44
errorT SetSiteName(NameBase *nb, const char *s)
Definition: indexentry.h:217
int WriteTwoBytes(uint32_t value)
Writes a 16-bit unsigned integer.
Definition: filebuf.h:144
const char INDEX_MAGIC[8]
Definition: index.h:40
const errorT ERROR_FileRead
Definition: error.h:33
uint nameT
Definition: namebase.h:29
uint32_t ReadThreeBytes()
Reads a 24-bit unsigned integer.
Definition: filebuf.h:123
errorT SetEventName(NameBase *nb, const char *s)
Definition: indexentry.h:211
const errorT ERROR_UserCancel
Definition: error.h:27
uint32_t uint
Definition: common.h:99
errorT flush()
flush() - writes all cached data to the file
Definition: index.h:239
errorT Open(const char *filename, fileModeT fmode)
Opens a file.
Definition: filebuf.h:43
errorT Read(T *file, versionT version)
Definition: indexentry.h:522
ushort eloT
Definition: common.h:160
errorT SetRoundName(NameBase *nb, const char *s)
Definition: indexentry.h:223
errorT ReadEntireFile(NameBase *nb, const Progress &progress)
Definition: index.cpp:137
const errorT ERROR_CorruptData
Definition: error.h:46
unsigned short errorT
Definition: error.h:20
const errorT ERROR_FileVersion
Definition: error.h:39
errorT Open(const char *filename, fileModeT fmode)
Definition: index.cpp:79
idNumberT GetNumNames(nameT n) const
Definition: namebase.h:107
const char INDEX_SUFFIX[]
Definition: index.h:38
errorT Create(const char *filename)
Definition: index.cpp:55
errorT SetWhiteName(NameBase *nb, const char *s)
Definition: indexentry.h:199
idNumberT GetRound() const
Definition: indexentry.h:141
size_t size() const
Definition: misc.h:91
errorT SetBlackName(NameBase *nb, const char *s)
Definition: indexentry.h:205
const errorT ERROR_IndexFull
Definition: error.h:57
void strCopy(char *target, const char *original)
Definition: misc.h:379
idNumberT GetBlack() const
Definition: indexentry.h:116
Adds some helper functions to std::filebuf:
Definition: filebuf.h:35
uint32_t ReadFourBytes()
Reads a 32-bit unsigned integer.
Definition: filebuf.h:129
uint gamenumT
Definition: common.h:159
const versionT SCID_VERSION
Definition: common.h:49
fileModeT
Definition: common.h:144
const errorT ERROR_FileMode
Definition: error.h:38
eloT GetWhiteElo() const
Definition: indexentry.h:246
const errorT ERROR_NameDataLoss
Definition: error.h:54
idNumberT GetSite() const
Definition: indexentry.h:134
int strCompare(const char *s1, const char *s2)
Definition: misc.h:361
idNumberT GetWhite() const
Definition: indexentry.h:109
const uint CUSTOM_FLAG_MAX
Definition: index.h:49
const errorT ERROR_FileOpen
Definition: error.h:31
Definition: indexentry.h:54