Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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 static constexpr char INDEX_MAGIC[8] = "Scid.si";
26 
27 void Index::Init ()
28 {
29  Header.numGames = 0;
30  Header.version = SCID_VERSION;
31  Header.baseType = 0;
32  Header.autoLoad = 1;
33  Header.description[0] = 0;
34  std::memset(Header.customFlagDesc, 0, sizeof(Header.customFlagDesc));
35  Header.dirty_ = false;
36  FilePtr = NULL;
37  fileMode_ = FMODE_Memory;
38  nInvalidNameId_ = 0;
39  seqWrite_ = 0;
40  entries_.resize(0);
41 }
42 
43 errorT Index::Clear ()
44 {
45  errorT res = flush();
46  delete FilePtr;
47  Init();
48  return res;
49 }
50 
51 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 // Index::CreateIndexFile():
53 // Creates and opens a new empty index file.
54 //
55 errorT
56 Index::Create(const char* filename)
57 {
58  ASSERT(filename != 0);
59 
60  Clear();
61  FilePtr = new Filebuf;
62  std::string fname = filename;
63  fname += INDEX_SUFFIX;
64  //Check that the file does not exists and then create it
65  if (FilePtr->Open(fname.c_str(), FMODE_ReadOnly) == OK ||
66  FilePtr->Open(fname.c_str(), FMODE_Create) != OK) {
67  delete FilePtr;
68  FilePtr = NULL;
69  return ERROR_FileOpen;
70  }
71  fileMode_ = FMODE_Both;
72  return WriteHeader();
73 }
74 
75 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76 // Index::Open():
77 // Open an index file and read the header.
78 //
79 errorT
80 Index::Open (const char* filename, fileModeT fmode)
81 {
82  ASSERT(filename != 0);
83 
84  Clear();
85  if (fmode == FMODE_WriteOnly) return ERROR_FileMode;
86  FilePtr = new Filebuf;
87  std::string fname = filename;
88  fname += INDEX_SUFFIX;
89 
90  if (FilePtr->Open (fname.c_str(), fmode) != OK) {
91  delete FilePtr;
92  FilePtr = NULL;
93  return ERROR_FileOpen;
94  }
95 
96  char magic[8];
97  FilePtr->sgetn(magic, 8);
98  if (!std::equal(std::begin(magic), std::end(magic), std::begin(INDEX_MAGIC),
99  std::end(INDEX_MAGIC))) {
100  delete FilePtr;
101  FilePtr = NULL;
102  return ERROR_BadMagic;
103  }
104 
105  Header.version = FilePtr->ReadTwoBytes ();
106  if (Header.version < SCID_OLDEST_VERSION || Header.version > SCID_VERSION) {
107  delete FilePtr;
108  FilePtr = NULL;
109  return ERROR_FileVersion;
110  }
111  if (Header.version != SCID_VERSION && fmode != FMODE_ReadOnly) {
112  //Old versions must be opened readonly
113  delete FilePtr;
114  FilePtr = NULL;
115  return ERROR_FileMode;
116  }
117 
118  Header.baseType = FilePtr->ReadFourBytes ();
119  Header.numGames = FilePtr->ReadThreeBytes ();
120  Header.autoLoad = FilePtr->ReadThreeBytes ();
121  FilePtr->sgetn(Header.description, SCID_DESC_LENGTH + 1);
122  Header.description[SCID_DESC_LENGTH] = 0;
123  if (Header.version >= 400) {
124  for (uint i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
125  FilePtr->sgetn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
126  Header.customFlagDesc[i][CUSTOM_FLAG_DESC_LENGTH] = 0;
127  }
128  }
129 
130  fileMode_ = fmode;
131  return OK;
132 }
133 
134 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
135 // Index::WriteHeader():
136 // Write the header to the open index file.
137 //
138 errorT
139 Index::WriteHeader ()
140 {
141  ASSERT(FilePtr != NULL);
142  if (FilePtr->pubseekpos(0) != std::streampos(0)) return ERROR_FileWrite;
143 
144  seqWrite_ = 0;
145  std::streamsize n = 0;
146  n += FilePtr->sputn(INDEX_MAGIC, 8);
147  n += FilePtr->WriteTwoBytes (Header.version);
148  n += FilePtr->WriteFourBytes (Header.baseType);
149  n += FilePtr->WriteThreeBytes (Header.numGames);
150  n += FilePtr->WriteThreeBytes (Header.autoLoad);
151  n += FilePtr->sputn(Header.description, SCID_DESC_LENGTH + 1);
152  for (size_t i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
153  n += FilePtr->sputn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
154  }
155  if (n != INDEX_HEADER_SIZE || FilePtr->pubsync() == -1) return ERROR_FileWrite;
156  Header.dirty_ = false;
157  return OK;
158 }
159 
161 {
162  if (idx > Header.numGames) return ERROR_BadArg;
163  if (fileMode_ == FMODE_ReadOnly) { return ERROR_FileMode; }
164 
165  if (idx == Header.numGames) {
166  entries_.push_back(*ie);
167  Header.numGames++;
168  Header.dirty_ = true;
169  } else {
170  IndexEntry* copyToMemory = &(entries_[idx]);
171  *copyToMemory = *ie;
172  }
173  if (FilePtr == NULL) return OK;
174 
175  if ((seqWrite_ == 0) || (idx != seqWrite_ + 1)) {
176  std::streampos pos = INDEX_ENTRY_SIZE * idx + INDEX_HEADER_SIZE;
177  if (FilePtr->pubseekpos(pos) != pos) {
178  seqWrite_ = 0;
179  return ERROR_FileWrite;
180  }
181  }
182  errorT res = ie->Write (FilePtr, Header.version);
183  seqWrite_ = (res == OK) ? idx : 0;
184  return res;
185 }
186 
187 //////////////////////////////////////////////////////////////////////
188 // EOF: index.cpp
189 //////////////////////////////////////////////////////////////////////
190 
const uint INDEX_HEADER_SIZE
Definition: index.h:52
const versionT SCID_OLDEST_VERSION
Definition: common.h:44
int WriteFourBytes(uint32_t value)
Writes a 32-bit unsigned integer.
Definition: filebuf.h:161
const uint INDEX_ENTRY_SIZE
Definition: indexentry.h:42
void resize(size_t count)
Definition: containers.h:149
const errorT OK
Definition: error.h:23
const errorT ERROR_BadMagic
Definition: error.h:35
const uint CUSTOM_FLAG_DESC_LENGTH
Definition: index.h:45
const errorT ERROR_FileWrite
Definition: error.h:32
#define ASSERT(f)
Definition: common.h:59
const errorT ERROR_BadArg
Definition: error.h:28
const uint SCID_DESC_LENGTH
Definition: index.h:44
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
int WriteTwoBytes(uint32_t value)
Writes a 16-bit unsigned integer.
Definition: filebuf.h:144
uint32_t ReadThreeBytes()
Reads a 24-bit unsigned integer.
Definition: filebuf.h:123
uint32_t uint
Definition: common.h:91
errorT flush()
flush() - writes all cached data to the file
Definition: index.h:217
errorT Open(const char *filename, fileModeT fmode)
Opens a file.
Definition: filebuf.h:43
errorT Write(T *file, versionT version) const
Definition: indexentry.h:320
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:80
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
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:163
void push_back(const T &e)
Definition: containers.h:143
const versionT SCID_VERSION
Definition: common.h:43
fileModeT
Definition: common.h:136
const errorT ERROR_FileMode
Definition: error.h:38
const uint CUSTOM_FLAG_MAX
Definition: index.h:46
const errorT ERROR_FileOpen
Definition: error.h:31
Definition: indexentry.h:54