Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
namebase.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014-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 #ifndef SCID_NAMEBASE_H
20 #define SCID_NAMEBASE_H
21 
22 #include "common.h"
23 #include "misc.h"
24 #include <algorithm>
25 #include <map>
26 #include <memory>
27 #include <vector>
28 
29 /**
30  * This class stores the database's names (players, events, sites and rounds).
31  * Assigns a idNumberT (which will be used as reference) to each name.
32  */
33 class NameBase {
34  std::vector<std::unique_ptr<const char[]> > names_[NUM_NAME_TYPES];
35  std::vector<eloT> eloV_;
36  struct idxCmp {
37  bool operator()(const char* str1, const char* str2) const {
38  // *** Compatibility ***
39  // Older code used a custom StrTree class with a peculiar sorting:
40  // - the first char was interpreted as an unsigned char;
41  // - the remaining part was compared with the function
42  // strComapare(),
43  // which converts the chars to ints, and is not consistent with
44  // the standard function strcmp().
45  // The old StrTree class did also have unpredictable behaviors when
46  // fed with names not sorted according to that criteria, for example
47  // it could create Namebase objects with duplicate entries.
48  // ***
49  if (*str1 == *str2)
50  return strCompare(str1, str2) < 0;
51 
52  return static_cast<uint>(*str1) < static_cast<uint>(*str2);
53  }
54  };
55  std::map<const char*, idNumberT, idxCmp> idx_[NUM_NAME_TYPES];
56 
57 public:
58  /**
59  * A NameBase stores the max ELO for each player. This functions updates
60  * the max ELO of a player if it's greater than the previous one.
61  * @param id: a valid idNumberT corresponding to a NAME_PLAYER name.
62  * @param elo: the ELO.
63  */
64  void AddElo(idNumberT id, eloT elo) {
66  if (elo > eloV_[id])
67  eloV_[id] = elo;
68  }
69 
70  /**
71  * Add a name (string) to the NameBase.
72  * If the name already exists the corresponding ID is returned.
73  * @param nt: @e nameT type of the name to add.
74  * @param name: the name to add.
75  * @param MAX_LEN: the max length for names of type @e nt
76  * @param MAX_ID: the max ID allowed for names of type @e nt
77  * @returns
78  * - on success, a @e std::pair containing OK and the ID.
79  * - on failure, a @e std::pair containing an error code and 0.
80  */
81  std::pair<errorT, idNumberT> addName(nameT nt, const char* name,
82  size_t MAX_LEN, idNumberT MAX_ID) {
83  ASSERT(IsValidNameType(nt) && name != NULL);
84 
85  auto exists = idx_[nt].lower_bound(name);
86  if (exists != idx_[nt].end() &&
87  !idx_[nt].key_comp()(name, exists->first))
88  return std::make_pair(OK, exists->second);
89 
90  const size_t nameLen = strlen(name);
91  if (nameLen > MAX_LEN)
92  return std::make_pair(ERROR_NameTooLong, 0);
93 
94  if (names_[nt].size() >= MAX_ID)
95  return std::make_pair(ERROR_NameLimit, 0);
96 
97  char* buf = new char[nameLen + 1];
98  std::copy_n(name, nameLen + 1, buf);
99  idNumberT newID = static_cast<idNumberT>(names_[nt].size());
100  names_[nt].emplace_back(buf);
101  idx_[nt].emplace_hint(exists, buf, newID);
102 
103  if (nt == NAME_PLAYER)
104  eloV_.push_back(0);
105 
106  return std::make_pair(OK, newID);
107  }
108 
109  /**
110  * Frees memory, leaving the object empty.
111  */
112  void Clear() { *this = NameBase(); }
113 
114  /**
115  * @returns references to the NameBase's containers.
116  * (must be used only to read names from files)
117  */
118  std::tuple<decltype(idx_) &, decltype(names_) &, decltype(eloV_) &>
120  return std::tuple<decltype(idx_)&, decltype(names_)&, decltype(eloV_)&>(
121  idx_, names_, eloV_);
122  }
123 
124  /**
125  * @param id: a valid idNumberT corresponding to a NAME_PLAYER name.
126  * @returns the max ELO of a player.
127  */
128  eloT GetElo(idNumberT id) const {
130  return eloV_[id];
131  }
132 
133  /**
134  * Get the first few matches of a name prefix.
135  * @param nt: @e nameT type of the name to be searched.
136  * @param str: name prefix be searched.
137  * @param maxMatches: the max number of ID to return
138  * @returns a vector containing the ID of the matching names.
139  */
140  std::vector<idNumberT> getFirstMatches(nameT nt, const char* str,
141  size_t maxMatches) const {
142  ASSERT(IsValidNameType(nt) && str != NULL);
143 
144  std::vector<idNumberT> res;
145  size_t len = strlen(str);
146  for (auto it = idx_[nt].lower_bound(str);
147  it != idx_[nt].end() && res.size() < maxMatches; ++it) {
148  const char* s = it->first;
149  if (strlen(s) < len || !std::equal(str, str + len, s))
150  break;
151  res.emplace_back(it->second);
152  }
153  return res;
154  }
155 
156  /**
157  * Retrieve a name.
158  * @param nt: the valid @e nameT type of the name to retrieve.
159  * @param id: the valid ID of the name to retrieve.
160  * @returns the name corresponding to @e id.
161  */
162  const char* GetName(nameT nt, idNumberT id) const {
163  ASSERT(IsValidNameType(nt) && id < GetNumNames(nt));
164  return names_[nt][id].get();
165  }
166 
167  /**
168  * @returns a reference to a container with all the names and IDs (given as
169  * std::pair<const char*, idNumberT>).
170  */
171  const decltype(idx_) & getNames() const { return idx_; }
172 
173  /**
174  * @param nt: a valid @e nameT type.
175  * @returns the first invalid idNumberT (which is equal to the number of
176  * names stored).
177  */
179  ASSERT(IsValidNameType(nt));
180  return static_cast<idNumberT>(names_[nt].size());
181  }
182 
183  /**
184  * Finds an exact full, case-sensitive name.
185  * @param nt: @e nameT type of the name to be searched.
186  * @param str: name to be be searched.
187  * @param[out] idPtr: pointer which will receive the ID of the name.
188  * @returns OK or ERROR_NameNotFound if the name does not exists.
189  */
190  errorT FindExactName(nameT nt, const char* str, idNumberT* idPtr) const {
191  ASSERT(IsValidNameType(nt) && str != NULL && idPtr != NULL);
192 
193  auto it = idx_[nt].find(str);
194  if (it != idx_[nt].end()) {
195  *idPtr = (*it).second;
196  return OK;
197  }
198  return ERROR_NameNotFound;
199  }
200 
201  /**
202  * For every name generates a 32bit hash with the first 4 chars.
203  * @param nt: @e nameT type of the names.
204  * @returns a vector containing the hashes.
205  */
206  std::vector<uint32_t> generateHashMap(nameT nt) const {
207  std::vector<uint32_t> res(names_[nt].size());
208  std::transform(names_[nt].begin(), names_[nt].end(), res.begin(),
209  [](const std::unique_ptr<const char[]>& name) {
210  return strStartHash(name.get());
211  });
212  return res;
213  }
214 
215  /**
216  * Validate a @e nameT type.
217  * @param nt: @e nameT type to be validated.
218  * @returns true if @e nt is valid.
219  */
220  static bool IsValidNameType(nameT nt) { return (nt < NUM_NAME_TYPES); }
221 
222  /**
223  * Match a string to a nameT.
224  * To match, the string should be a prefix of "player", "event", "site" or
225  * "round", or be a superstring of it, e.g. "player ...."
226  * @param str: the string to be matched.
227  * @returns a valid nameT, or NAME_INVALID.
228  */
229  static nameT NameTypeFromString(const char* str) {
230  if (*str == '\0')
231  return NAME_INVALID;
232  if (strIsAlphaPrefix(str, "player"))
233  return NAME_PLAYER;
234  if (strIsAlphaPrefix(str, "event"))
235  return NAME_EVENT;
236  if (strIsAlphaPrefix(str, "site"))
237  return NAME_SITE;
238  if (strIsAlphaPrefix(str, "round"))
239  return NAME_ROUND;
240  if (strIsAlphaPrefix("player", str))
241  return NAME_PLAYER;
242  if (strIsAlphaPrefix("event", str))
243  return NAME_EVENT;
244  if (strIsAlphaPrefix("site", str))
245  return NAME_SITE;
246  if (strIsAlphaPrefix("round", str))
247  return NAME_ROUND;
248  return NAME_INVALID;
249  }
250 };
251 
252 #endif // SCID_NAMEBASE_H
void Clear()
Frees memory, leaving the object empty.
Definition: namebase.h:112
std::pair< errorT, idNumberT > addName(nameT nt, const char *name, size_t MAX_LEN, idNumberT MAX_ID)
Add a name (string) to the NameBase.
Definition: namebase.h:81
uint32_t strStartHash(const char *str)
Definition: misc.h:127
errorT FindExactName(nameT nt, const char *str, idNumberT *idPtr) const
Finds an exact full, case-sensitive name.
Definition: namebase.h:190
const errorT OK
Definition: error.h:23
#define ASSERT(f)
Definition: common.h:59
void AddElo(idNumberT id, eloT elo)
A NameBase stores the max ELO for each player.
Definition: namebase.h:64
const errorT ERROR_NameTooLong
Definition: error.h:55
names
Definition: tablebase.tcl:257
const errorT ERROR_NameNotFound
Definition: error.h:50
std::vector< uint32_t > generateHashMap(nameT nt) const
For every name generates a 32bit hash with the first 4 chars.
Definition: namebase.h:206
const char * GetName(nameT nt, idNumberT id) const
Retrieve a name.
Definition: namebase.h:162
uint32_t idNumberT
Definition: common.h:152
This class stores the database&#39;s names (players, events, sites and rounds).
Definition: namebase.h:33
sizew
Definition: board.tcl:574
static bool IsValidNameType(nameT nt)
Validate a nameT type.
Definition: namebase.h:220
uint32_t uint
Definition: common.h:91
ushort eloT
Definition: common.h:164
std::vector< idNumberT > getFirstMatches(nameT nt, const char *str, size_t maxMatches) const
Get the first few matches of a name prefix.
Definition: namebase.h:140
unsigned short errorT
Definition: error.h:20
std::tuple< decltype(idx_) &, decltype(names_) &, decltype(eloV_) & > getData()
Definition: namebase.h:119
eloT GetElo(idNumberT id) const
Definition: namebase.h:128
idNumberT GetNumNames(nameT nt) const
Definition: namebase.h:178
unsigned nameT
Definition: common.h:153
decltype(idx_) const & getNames() const
Definition: namebase.h:171
const errorT ERROR_NameLimit
Definition: error.h:56
int strCompare(const char *s1, const char *s2)
Definition: misc.h:280
static nameT NameTypeFromString(const char *str)
Match a string to a nameT.
Definition: namebase.h:229
bool strIsAlphaPrefix(const char *prefix, const char *longStr)
Definition: misc.h:366