Scid  4.6.5
codec_proxy.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-2017 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 CodecProxy class, which serves as base class for non-native
22  * databases.
23  */
24 
25 #ifndef CODEC_PROXY_H
26 #define CODEC_PROXY_H
27 
28 #include "codec.h"
29 #include "codec_memory.h"
30 #include "common.h"
31 #include "game.h"
32 
33 #if !CPP11_SUPPORT
34 #define override
35 #endif
36 
37 /**
38  * Base class for non-native databases.
39  * Every class derived from ICodecDatabase must keep an @e Index object and the
40  * corresponding @e NameBase object fully updated in memory.
41  * This implies that the virtual function dyn_open() must load in memory the
42  * header's data of all the games; however a dependency between the codecs and
43  * the @e Index class is not desirable.
44  * This class provides an interface that encapsulates the codecs, requiring only
45  * the ability to exchange @e Game objects.
46  */
47 template <typename Derived>
48 class CodecProxy : public CodecMemory {
49 protected:
50  /**
51  * Opens/creates a database encoded in a non-native format.
52  * @param filename: full path of the database to be opened.
53  * @param fMode: valid file access mode.
54  * @returns OK in case of success, an @p errorT code otherwise.
55  */
56  errorT open(const char* filename, fileModeT fMode);
57 
58  /**
59  * Reads the next game.
60  * A derived class implements this function to sequentially read the games
61  * contained into the database.
62  * @param Game*: valid pointer to the Game object where the data will be stored.
63  * @returns
64  * - OK on success.
65  * - ERROR_NotFound if there are no more games to be read.
66  * - ERROR code if the game cannot be read and was skipped.
67  */
69  return ERROR_NotFound;
70  }
71 
72  /**
73  * Returns info about the parsing progress.
74  * @returns a pair<size_t, size_t> where first element is the quantity of
75  * data parsed and second one is the total amount of data of the database.
76  */
77  std::pair<size_t, size_t> parseProgress() {
78  return std::pair<size_t, size_t>(1, 1);
79  }
80 
81  /**
82  * Returns the list of errors produced by parseNext() calls.
83  */
84  const char* parseErrors() {
85  return NULL;
86  }
87 
88  /**
89  * Adds a game into the database.
90  * @param Game*: valid pointer to a Game object with the new data.
91  * @returns OK in case of success, an @p errorT code otherwise.
92  */
94  return ERROR_CodecUnsupFeat;
95  }
96 
97  /**
98  * Replaces a game in the database.
99  * @param Game*: valid pointer to a Game object with the new data.
100  * @param gamenumT: valid gamenumT of the game to be replaced.
101  * @returns OK in case of success, an @p errorT code otherwise.
102  */
104  return ERROR_CodecUnsupFeat;
105  }
106 
107 
108 private:
109  errorT addGame(Game* game) override {
110  errorT err = getDerived()->dyn_addGame(game);
111  if (err != OK) return err;
112 
113  return CodecMemory::addGame(game);
114  }
115 
116  errorT saveGame(Game* game, gamenumT replaced) override {
117  errorT err = getDerived()->dyn_saveGame(game, replaced);
118  if (err != OK) return err;
119 
120  return CodecMemory::saveGame(game, replaced);
121  }
122 
123  errorT addGame(IndexEntry* ie, const byte* src, size_t length) override {
124  Game game;
125  errorT err = decodeGame(ie, src, length, game);
126  if (err != OK) return err;
127 
128  err = getDerived()->dyn_addGame(&game);
129  if (err != OK) return err;
130 
131  return CodecMemory::addGame(ie, src, length);
132  }
133 
134  errorT saveGame(IndexEntry* ie, const byte* src, size_t length,
135  gamenumT replaced) override {
136  Game game;
137  errorT err = decodeGame(ie, src, length, game);
138  if (err != OK) return err;
139 
140  err = getDerived()->dyn_saveGame(&game, replaced);
141  if (err != OK) return err;
142 
143  return CodecMemory::saveGame(ie, src, length, replaced);
144  }
145 
146  /*
147  * Creates a memory database and invokes the function open(), which will
148  * open the non-native database @p filename. Subsequently, the function
149  * parseNext() is repeatedly called until it returns ERROR_NotFound, and
150  * the games are copied into the memory database.
151  */
152  errorT dyn_open(fileModeT fMode, const char* filename,
153  const Progress& progress, Index* idx,
154  NameBase* nb) override {
155  if (filename == 0) return ERROR;
156 
157  errorT err = CodecMemory::dyn_open(FMODE_Memory, filename, progress, idx, nb);
158  if (err != OK) return err;
159 
160  err = getDerived()->open(filename, fMode);
161  if (err != OK) return err;
162 
163  Game g;
164  uint nImported = 0;
165  while ((err = getDerived()->parseNext(&g)) != ERROR_NotFound) {
166  if (err != OK) continue;
167 
168  err = CodecMemory::addGame(&g);
169  if (err != OK) break;
170 
171  if (++nImported % 1024 == 0) {
172  std::pair<size_t, size_t> count = getDerived()->parseProgress();
173  if (!progress.report(count.first, count.second)) {
174  err = ERROR_UserCancel;
175  break;
176  }
177  }
178  }
179  progress(1, 1, getDerived()->parseErrors());
180 
181  return (err == ERROR_NotFound) ? OK : err;
182  }
183 
184  /**
185  * Decodes a Game object from native format.
186  * @param srcIe: valid pointer to the header data.
187  * @param src: valid pointer to a buffer containing the game data
188  * (encoded in native format).
189  * @param length: length of the game data (in bytes).
190  * @param[out] resGame: the Game object where the data will be decoded.
191  * @returns OK in case of success, an @p errorT code otherwise.
192  */
193  errorT decodeGame(const IndexEntry* srcIe, const byte* src, size_t length,
194  Game& resGame) {
195  ByteBuffer buf(0);
196  buf.ProvideExternal(const_cast<byte*>(src), length);
197  errorT err = resGame.Decode(&buf, GAME_DECODE_ALL);
198  if (err == OK) err = resGame.LoadStandardTags(srcIe, nb_);
199  return err;
200  }
201 
202  /**
203  * Return a pointer to the derived class.
204  */
205  Derived* getDerived() { return static_cast<Derived*>(this); }
206 };
207 
208 #if !CPP11_SUPPORT
209 #undef override
210 #endif
211 
212 #endif
unsigned char byte
Definition: common.h:97
const errorT ERROR_CodecUnsupFeat
Definition: error.h:82
Manages memory databases that do not have associated files.
Definition: codec_memory.h:47
bool report(size_t done, size_t total) const
Definition: misc.h:136
errorT dyn_addGame(Game *)
Adds a game into the database.
Definition: codec_proxy.h:93
const errorT OK
Definition: error.h:23
errorT dyn_open(fileModeT fMode, const char *, const Progress &, Index *idx, NameBase *nb) override
Opens/Creates a database.
Definition: codec_memory.h:105
Definition: misc.h:124
Defines the ICodecDatabase interface, which encapsulates the data representation of databases...
const char * parseErrors()
Returns the list of errors produced by parseNext() calls.
Definition: codec_proxy.h:84
errorT addGame(IndexEntry *ie, const byte *src, size_t length) override
Add a game to the database.
Definition: codec_memory.h:75
errorT LoadStandardTags(const IndexEntry *ie, const NameBase *nb)
Definition: game.cpp:2932
const errorT ERROR_UserCancel
Definition: error.h:27
uint32_t uint
Definition: common.h:99
std::pair< size_t, size_t > parseProgress()
Returns info about the parsing progress.
Definition: codec_proxy.h:77
errorT dyn_saveGame(Game *, gamenumT)
Replaces a game in the database.
Definition: codec_proxy.h:103
Definition: index.h:61
errorT parseNext(Game *)
Reads the next game.
Definition: codec_proxy.h:68
#define GAME_DECODE_ALL
Definition: game.h:185
unsigned short errorT
Definition: error.h:20
NameBase * nb_
Definition: codec_memory.h:50
Base class for non-native databases.
Definition: codec_proxy.h:48
Definition: game.h:227
void ProvideExternal(byte *data, uint length)
Definition: bytebuf.cpp:52
errorT open(const char *filename, fileModeT fMode)
Opens/creates a database encoded in a non-native format.
uint gamenumT
Definition: common.h:159
fileModeT
Definition: common.h:144
const errorT ERROR
Definition: error.h:26
const errorT ERROR_NotFound
Definition: error.h:50
errorT saveGame(IndexEntry *ie, const byte *src, size_t length, gamenumT replaced) override
Replaces a game in the database.
Definition: codec_memory.h:79
Definition: indexentry.h:54
errorT Decode(ByteBuffer *buf, byte flags)
Definition: game.cpp:3931
Implements the CodecMemory class, which manages the memory representation of the open databases...