libscid 0.1.0
Chess applications made easy.
Loading...
Searching...
No Matches
misc.h
1
3//
4// FILE: misc.h
5// Miscellaneous routines (File I/O, etc)
6//
7// Part of: Scid (Shane's Chess Information Database)
8// Version: 3.5
9//
10// Notice: Copyright (c) 2001-2003 Shane Hudson. All rights reserved.
11// Copyright (C) 2015 Fulvio Benini
12//
13// Author: Shane Hudson (sgh@users.sourceforge.net)
14//
16
17
18#ifndef SCID_MISC_H
19#define SCID_MISC_H
20
21#include "scid/core/game_result.h"
22#include "scid/database/common.h"
23#include <algorithm>
24#include <string>
25#include <cstring>
26#include <stdio.h>
27#include <ctype.h> // For isspace(), etc
28#include <cstdlib>
29#include <vector>
30
37namespace scid::database {
38
39class StrRange {
40protected:
41 long min_;
42 long max_;
43
44protected:
45 StrRange()
46 : min_(0), max_(0) {}
47
48public:
49 explicit StrRange(const char* range) {
50 char* next;
51 min_ = std::strtol(range, &next, 10);
52 char* end;
53 max_ = std::strtol(next, &end, 10);
54 if (next == end) max_ = min_;
55 if (min_ > max_) std::swap(min_, max_);
56 }
57
59 bool inRange(long val) const {
60 if (val < min_ || val > max_) return false;
61 return true;
62 }
63};
64
65
66class Progress {
67public:
68 struct Impl {
69 virtual ~Impl() {}
70 virtual bool report(size_t done, size_t total, const char* msg) = 0;
71 };
72
73 Progress(Impl* f = NULL) : f_(f) {}
74 Progress(const Progress&) = delete;
75 ~Progress() { delete f_; }
76
77 bool report(size_t done, size_t total) const {
78 return operator()(done, total);
79 }
80 bool operator()(size_t done, size_t total, const char* msg = NULL) const {
81 if (f_) return f_->report(done, total, msg);
82 return true;
83 }
84
85private:
86 Impl* f_;
87};
88
89
90//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91// strGetFilterOp:
92// Converts a string value to a filter operation value.
93enum filterOpT { FILTEROP_AND, FILTEROP_OR, FILTEROP_RESET };
94
95inline filterOpT strGetFilterOp (const char * str)
96{
97 switch (*str) {
98 // AND:
99 case 'A': case 'a': case '0': return FILTEROP_AND;
100 // OR:
101 case 'O': case 'o': case '1': return FILTEROP_OR;
102 // RESET:
103 case 'R': case 'r': case '2': return FILTEROP_RESET;
104 }
105 // Default is RESET.
106 return FILTEROP_RESET;
107}
108
109// String routines. Some are identical to ANSI standard functions, but
110// I have included them:
111// (a) to keep nice consistent naming conventions, e.g. strCopy.
112// (b) so stats can easily be kept by modifying the functions.
113// (c) so some can be made inline for speed if necessary.
114
115inline uint32_t strStartHash(const char* str) {
116 ASSERT(str != 0);
117 const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
118
119 uint32_t tmp = static_cast<unsigned char>(tolower(*s));
120 uint32_t result = tmp << 24;
121 if (*s == '\0') return result;
122 tmp = static_cast<unsigned char>(tolower(*++s));
123 result += tmp << 16;
124 if (*s == '\0') return result;
125 tmp = static_cast<unsigned char>(tolower(*++s));
126 result += tmp << 8;
127 if (*s == '\0') return result;
128 result += static_cast<unsigned char>(tolower(*++s));
129 return result;
130}
131
132char * strDuplicate (const char * str);
133
134char * strAppend (char * target, const char * extra);
135scid::core::uint strPad (char * target, const char * orig, int length, char pad);
136const char * strFirstChar (const char * target, char matchChar);
137const char * strLastChar (const char * target, char matchChar);
138void strStrip (char * str, char ch);
139
140const char * strTrimLeft (const char * target, const char * trimChars);
141inline const char * strTrimLeft (const char * target) {
142 return strTrimLeft (target, " \t\r\n");
143}
144scid::core::uint strTrimSuffix (char * target, char suffixChar);
145void strTrimDate (char * str);
146void strTrimMarkCodes (char * str);
147void strTrimMarkup (char * str);
148const char * strFirstWord (const char * str);
149const char * strNextWord (const char * str);
150
151// strPlural:
152// Returns the empty string if its parameter is 1, or "s" otherwise.
153inline const char *
154strPlural (scid::core::uint x) {
155 return (x == 1 ? "" : "s");
156}
157
158bool strIsUnknownName (const char * str);
159
160// strIsSurnameOnly: returns true if a string appears to only
161// contain a surname.
162bool strIsSurnameOnly (const char * name);
163
164bool strGetBoolean (const char * str);
165
166//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167// strGetInteger():
168// Extracts a signed base-10 value from a string.
169// Defaults to zero (as strtol does) for non-numeric strings.
170inline int
171strGetInteger(const char * str)
172{
173 return std::strtol(str, NULL, 10);
174}
175
176//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177// strGetUnsigned():
178// Extracts an unsigned base-10 value from a string.
179// Defaults to zero (as strtoul does) for non-numeric strings.
180//
181inline uint32_t strGetUnsigned(const char* str) {
182 ASSERT(str != NULL);
183 return static_cast<uint32_t>(std::strtoul(str, NULL, 10));
184}
185
186inline int strCaseCompare(const char* str1, const char* str2) {
187 ASSERT(str1 != NULL && str2 != NULL);
188 const unsigned char* s1 = reinterpret_cast<const unsigned char*>(str1);
189 const unsigned char* s2 = reinterpret_cast<const unsigned char*>(str2);
190 int c1, c2;
191 do {
192 c1 = tolower(*s1++);
193 c2 = tolower(*s2++);
194 if (c1 == '\0')
195 break;
196 } while (c1 == c2);
197
198 return c1 - c2;
199}
200
201inline int strCompareRound(const char* str1, const char* str2) {
202 ASSERT(str1 != NULL && str2 != NULL);
203 uint32_t a = strGetUnsigned(str1);
204 uint32_t b = strGetUnsigned(str2);
205 if (a == b)
206 return strCaseCompare(str1, str2);
207 return (a < b) ? -1 : 1;
208}
209
210inline bool strEqual(const char* str1, const char* str2) {
211 ASSERT(str1 != NULL && str2 != NULL);
212 return (std::strcmp(str1, str2) == 0);
213}
214
215void strGetIntegers (const char * str, int * results, scid::core::uint nResults);
216void strGetUnsigneds (const char * str, scid::core::uint * results, scid::core::uint nResults);
217scid::core::resultT strGetResult (const char * str);
218
219typedef scid::core::uint flagT;
220const flagT FLAG_EMPTY = 0;
221const flagT FLAG_YES = 1;
222const flagT FLAG_NO = 2;
223const flagT FLAG_BOTH = 3;
224inline bool flag_Yes (flagT t) { return (t & FLAG_YES); }
225inline bool flag_No (flagT t) { return (t & FLAG_NO); }
226flagT strGetFlag (const char * str);
227
228scid::core::squareT strGetSquare (const char * str);
229
230inline scid::core::uint
231strTrimFileSuffix (char * target) { return strTrimSuffix (target, '.'); }
232
233inline const char *
234strFileSuffix (const char * target) { return strLastChar (target, '.'); }
235
236
237
238int strUniqueExactMatch (const char * keyStr, const char ** strTable,
239 bool exact);
240
241inline int strUniqueMatch (const char * keyStr, const char ** strTable) {
242 return strUniqueExactMatch (keyStr, strTable, false);
243}
244inline int strExactMatch (const char * keyStr, const char ** strTable) {
245 return strUniqueExactMatch (keyStr, strTable, true);
246}
247
248inline bool
249strContainsChar (const char * str, char ch)
250{
251 while (*str) {
252 if (*str == ch) { return true; }
253 str++;
254 }
255 return false;
256}
257
258// WARNING: Avoid this function!
259// Considering that the sign of a char is implementation-defined [3.9.1], the
260// int conversion ("[4.7.3] If the destination type is signed, the value is
261// unchanged if it can be represented in the destination type") can yield
262// different results on different architectures or compilers.
263// A better alternative is the standard function strcmp() that returns the
264// difference between the values of the first pair of characters (both
265// interpreted as unsigned char) that differ in the strings being compared.
266inline int strCompare(const char* s1, const char* s2)
267{
268 ASSERT (s1 != NULL && s2 != NULL);
269 while (1) {
270 if (*s1 != *s2) {
271 return ((int) *s1) - ((int) *s2);
272 }
273 if (*s1 == 0)
274 break;
275 s1++; s2++;
276 }
277 return 0;
278}
279
280//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
281// strCopy(): same as strcpy().
282//
283inline void
284strCopy (char * target, const char * original)
285{
286 ASSERT (target != NULL && original != NULL);
287 while (*original != 0) {
288 *target = *original;
289 target++;
290 original++;
291 }
292 *target = 0;
293}
294
295//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
296// strPrefix():
297// Returns the length of the common prefix of two strings.
298//
299inline scid::core::uint
300strPrefix (const char * s1, const char * s2)
301{
302 ASSERT (s1 != NULL && s2 != NULL);
303 scid::core::uint count = 0;
304 while (*s1 == *s2) {
305 if (*s1 == 0) { // seen end of string, strings are identical
306 return count;
307 }
308 count++; s1++; s2++;
309 }
310 return count;
311}
312
313//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314// strIsPrefix():
315// Returns true if the prefix string is a prefix of longStr.
316inline bool
317strIsPrefix (const char * prefix, const char * longStr)
318{
319 while (*prefix) {
320 if (*longStr == 0) { return false; }
321 if (*prefix != *longStr) { return false; }
322 prefix++;
323 longStr++;
324 }
325 return true;
326}
327
328//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
329// strIsCasePrefix():
330// Returns true if the prefix string is a case-insensitive
331// prefix of longStr.
332inline bool
333strIsCasePrefix (const char * prefix, const char * longStr)
334{
335 typedef unsigned char U;
336 while (*prefix) {
337 if (*longStr == 0) { return false; }
338 if (tolower(U(*prefix)) != tolower(U(*longStr))) { return false; }
339 prefix++;
340 longStr++;
341 }
342 return true;
343}
344
345//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
346// strIsAlphaPrefix():
347// Returns true if the prefix string is a prefix of longStr.
348// Unlike strIsPrexix(), this version is case-insensitive and
349// spaces are ignored.
350// Example: strIsAlphaPrefix ("smith,j", "Smith, John") == true.
351inline bool
352strIsAlphaPrefix (const char * prefix, const char * longStr)
353{
354 typedef unsigned char U;
355 while (*prefix) {
356 while (*prefix == ' ') { prefix++; }
357 while (*longStr == ' ') { longStr++; }
358 if (*longStr == 0) { return false; }
359 if (tolower(U(*prefix)) != tolower(U(*longStr))) { return false; }
360 prefix++;
361 longStr++;
362 }
363 return true;
364}
365
366//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
367// strContains():
368// Returns true if longStr contains an occurrence of keyStr,
369// case-sensitive and NOT ignoring any characters such as spaces.
370inline bool
371strContains (const char * longStr, const char * keyStr)
372{
373 while (*longStr) {
374 if (strIsPrefix (keyStr, longStr)) { return true; }
375 longStr++;
376 }
377 return false;
378}
379
380//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
381// strAlphaContains():
382// Returns true if longStr contains an occurrence of keyStr,
383// case-insensitive and ignoring spaces.
384// Example: strAlphaContains ("Smith, John", "th,j") == true.
385//
386inline bool
387strAlphaContains (const char * longStr, const char * keyStr)
388{
389 while (*longStr) {
390 if (strIsAlphaPrefix (keyStr, longStr)) { return true; }
391 longStr++;
392 }
393 return false;
394}
395
396inline scid::core::uint
397strLength (const char * str)
398{
399 ASSERT(str != NULL);
400 scid::core::uint len = 0;
401 while (*str != 0) { len++; str++; }
402 return len;
403}
404
405
406//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
407// strTrimRight():
408// Trims the provided string in-place, removing the
409// end characters that match the trimChars.
410// Returns the number of characters trimmed.
411// E.g., strTrimRight("abcyzyz", "yz") would leave the string
412// as "abc".
413inline void strTrimRight(char* target, const char* trimChars, size_t nTrimCh) {
414 const char* endTrim = trimChars + nTrimCh;
415 size_t iCh = strlen(target);
416 for (; iCh > 0; --iCh) {
417 if (std::find(trimChars, endTrim, target[iCh - 1]) == endTrim)
418 break;
419 }
420 target[iCh] = '\0';
421}
422inline void strTrimRight(char* target) {
423 return strTrimRight(target, " \t\r\n", 4);
424}
425
426
427} // namespace scid::database
428#endif // #ifdef SCID_MISC_H
429
431// EOF: misc.h
Definition misc.h:66
Definition misc.h:39
bool inRange(long val) const
Definition misc.h:59
class StrRange - parse a string interpreting its content as 1 or 2 integers separated by whitespace.
Definition common.h:30
Definition misc.h:68