Line data Source code
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 CodecMemory class, which represent a memory database.
22 : */
23 :
24 : #ifndef CODEC_MEMORY_H
25 : #define CODEC_MEMORY_H
26 :
27 : #include "codec_native.h"
28 :
29 : /**
30 : * Manages memory databases that do not have associated files.
31 : * Every open database should have a native representation in memory: to satisfy
32 : * this requirement non-native codecs should be derived from this class.
33 : */
34 83 : class CodecMemory : public CodecNative<CodecMemory> {
35 : VectorChunked<byte, 24> v_;
36 :
37 : enum : uint64_t {
38 : LIMIT_GAMEOFFSET = 1ULL << 46,
39 : LIMIT_GAMELEN = 1ULL << 18,
40 : LIMIT_NUMGAMES = (1ULL << 32) - 2,
41 : LIMIT_UNIQUENAMES = 1ULL << 28,
42 : LIMIT_NAMELEN = 255
43 : };
44 :
45 : public: // ICodecDatabase interface
46 1 : Codec getType() const override { return ICodecDatabase::MEMORY; }
47 :
48 4 : std::vector<std::string> getFilenames() const override {
49 4 : return std::vector<std::string>();
50 : }
51 :
52 : std::vector<std::pair<const char*, std::string>>
53 0 : getExtraInfo() const override {
54 0 : std::vector<std::pair<const char*, std::string>> res;
55 0 : res.emplace_back("type", std::to_string(idx_->GetType()));
56 0 : return res;
57 : }
58 :
59 7021 : const byte* getGameData(uint64_t offset, uint32_t length) override {
60 7021 : ASSERT(offset < v_.size());
61 7021 : ASSERT(length <= v_.size() - offset);
62 7021 : ASSERT(v_.contiguous(static_cast<size_t>(offset)) >= length);
63 7021 : return &v_[offset];
64 : }
65 :
66 19 : errorT flush() override { return OK; }
67 :
68 34 : errorT dyn_open(fileModeT fMode, const char*, const Progress&, Index* idx,
69 : NameBase* nb) override {
70 34 : if (idx == 0 || nb == 0)
71 0 : return ERROR;
72 34 : if (fMode != FMODE_Memory)
73 4 : return ERROR;
74 30 : idx_ = idx;
75 30 : nb_ = nb;
76 30 : return OK;
77 : }
78 :
79 : public: // CodecNative CRTP
80 : /**
81 : * Stores the data of a game into memory.
82 : * @param src: valid pointer to a buffer that contains the game data
83 : * (encoded in native format).
84 : * @param length: the length of the buffer @p src (in bytes).
85 : * @returns
86 : * - on success, a @e std::pair containing OK and the offset of the stored
87 : * data (usable to retrieve the data with getGameData()).
88 : * - on failure, a @e std::pair containing an error code and 0.
89 : */
90 8018 : std::pair<errorT, uint64_t> dyn_addGameData(const byte* src,
91 : size_t length) {
92 8018 : ASSERT(src != 0);
93 :
94 8018 : if (length >= LIMIT_GAMELEN)
95 0 : return std::make_pair(ERROR_GameLengthLimit, 0);
96 :
97 8018 : auto offset = v_.size();
98 8018 : auto capacity = v_.capacity();
99 8018 : if (capacity - offset < length) // Do not fit in the current chunk
100 28 : offset = capacity;
101 8018 : if (offset >= LIMIT_GAMEOFFSET)
102 0 : return std::make_pair(ERROR_OffsetLimit, 0);
103 :
104 8018 : v_.resize(offset + length);
105 8018 : ASSERT(v_.contiguous(offset) >= length);
106 8018 : std::copy_n(src, length, &v_[offset]);
107 8018 : return {OK, offset};
108 : }
109 :
110 : /**
111 : * Given a name (string), retrieve the corresponding ID.
112 : * The name is added to @e nb_ if do not already exists in the NameBase.
113 : * @param nt: nameT type of the name to retrieve.
114 : * @param name: the name to retrieve.
115 : * @returns
116 : * - on success, a @e std::pair containing OK and the ID.
117 : * - on failure, a @e std::pair containing an error code and 0.
118 : */
119 40090 : std::pair<errorT, idNumberT> dyn_addName(nameT nt, const char* name) {
120 40090 : return nb_->addName(nt, name, LIMIT_NAMELEN, LIMIT_UNIQUENAMES);
121 : }
122 :
123 : /**
124 : * Add an IndexEntry to @e idx_.
125 : * @param ie: the IndexEntry object to add.
126 : * @returns OK if successful or an error code.
127 : */
128 7017 : errorT dyn_addIndexEntry(const IndexEntry& ie) {
129 7017 : auto nGames = idx_->GetNumGames();
130 7017 : if (nGames >= LIMIT_NUMGAMES)
131 0 : return ERROR_NumGamesLimit;
132 :
133 7017 : return idx_->WriteEntry(&ie, nGames);
134 : }
135 :
136 : /**
137 : * Replace an IndexEntry.
138 : * @param ie: the IndexEntry with the new data.
139 : * @param replaced: valid gamenumT of the game to be replaced.
140 : * @returns OK if successful or an error code.
141 : */
142 1001 : errorT dyn_saveIndexEntry(const IndexEntry& ie, gamenumT replaced) {
143 1001 : return idx_->WriteEntry(&ie, replaced);
144 : }
145 : };
146 :
147 : #endif
|