ScummVM API documentation
string.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 //=============================================================================
23 //
24 // String class with simple memory management and copy-on-write behavior.
25 //
26 // String objects do reference counting and share data buffer on assignment.
27 // The reallocation and copying is done only when the string is modified.
28 //
29 // The copying of memory inside buffer is reduced to minimum. If the string is
30 // truncated, it is not aligned to buffer head each time, instead the c-str
31 // pointer is advanced, or null-terminator is put on the new place. Similarly,
32 // when string is enlarged and new characters are prepended or appended, only
33 // c-str pointer and null-terminator's position are changed, if there's enough
34 // space before and after meaningful string data.
35 //
36 // The class provides means to reserve large amount of buffer space before
37 // making modifications, as well as compacting buffer to minimal size.
38 //
39 // For all methods that expect C-string as parameter - if the null pointer is
40 // passed in place of C-string it is treated in all aspects as a valid empty
41 // string.
42 //
43 //=============================================================================
44 
45 #ifndef AGS_SHARED_UTIL_STRING_H
46 #define AGS_SHARED_UTIL_STRING_H
47 
48 //include <stdarg.h>
49 
50 #include "common/str.h"
51 
52 #include "ags/lib/std/vector.h"
53 #include "ags/shared/core/platform.h"
54 #include "ags/shared/core/types.h"
55 
56 namespace AGS3 {
57 namespace AGS {
58 namespace Shared {
59 
60 class Stream;
61 
62 class String {
63 public:
64  static const size_t NoIndex = (size_t)-1;
65 
66  // Standard constructor: intialize empty string
67  String();
68  // Copy constructor
69  String(const String &);
70  // Move constructor
71  String(String &&);
72  // Initialize with C-string
73  String(const char *cstr);
74  // Initialize by copying up to N chars from C-string
75  String(const char *cstr, size_t length);
76  // Initialize by filling N chars with certain value
77  String(char c, size_t count);
78  // Initialize from a ScummVM string
79  String(const Common::String &s);
80  ~String();
81 
82  // Get underlying C-string for reading; this method guarantees valid C-string
83  inline const char *GetCStr() const {
84  return _cstr;
85  }
86  // Get character count
87  inline size_t GetLength() const {
88  return _len;
89  }
90  // Know if the string is empty (has no meaningful characters)
91  inline bool IsEmpty() const {
92  return _len == 0;
93  }
94  // Tells if the string is either empty or has only whitespace characters
95  bool IsNullOrSpace() const;
96 
97  // Those getters are for tests only, hence if AGS_PLATFORM_DEBUG
98 #if defined(AGS_PLATFORM_TEST) && AGS_PLATFORM_TEST
99  inline const char *GetBuffer() const {
100  return _buf;
101  }
102 
103  inline size_t GetCapacity() const {
104  return _bufHead ? _bufHead->Capacity : 0;
105  }
106 
107  inline size_t GetRefCount() const {
108  return _bufHead ? _bufHead->RefCount : 0;
109  }
110 #endif
111 
112  // Read() method implies that string length is initially unknown.
113  // max_chars parameter determine the buffer size limit.
114  // If stop_at_limit flag is set, it will read only up to the max_chars.
115  // Otherwise (by default) hitting the limit won't stop stream reading;
116  // the data will be read until null-terminator or EOS is met, and buffer
117  // will contain only leftmost part of the longer string that fits in.
118  // This method is better fit for reading from binary streams.
119  void Read(Stream *in, size_t max_chars = 5 * 1024 * 1024, bool stop_at_limit = false);
120  // ReadCount() reads up to N characters from stream, ignoring null-
121  // terminator. This method is better fit for reading from text
122  // streams, or when the length of string is known beforehand.
123  void ReadCount(Stream *in, size_t count);
124  // Write() puts the null-terminated string into the stream.
125  void Write(Stream *out) const;
126  // WriteCount() writes N characters to stream, filling the remaining
127  // space with null-terminators when needed.
128  void WriteCount(Stream *out, size_t count) const;
129 
130  //-------------------------------------------------------------------------
131  // String analysis methods
132  //-------------------------------------------------------------------------
133 
134  // Compares with given string
135  int Compare(const String &str) const {
136  return Compare(str._cstr);
137  }
138  int Compare(const char *cstr) const;
139  int CompareNoCase(const String &str) const {
140  return CompareNoCase(str._cstr);
141  }
142  int CompareNoCase(const char *cstr) const;
143  // Compares the leftmost part of this string with given string
144  int CompareLeft(const String &str, size_t count = -1) const {
145  return CompareLeft(str._cstr, count != NoIndex ? count : str._len);
146  }
147  int CompareLeft(const char *cstr, size_t count = -1) const;
148  int CompareLeftNoCase(const String &str, size_t count = -1) const {
149  return CompareLeftNoCase(str._cstr, count != NoIndex ? count : str._len);
150  }
151  int CompareLeftNoCase(const char *cstr, size_t count = -1) const;
152  // Compares any part of this string with given string
153  int CompareMid(const String &str, size_t from, size_t count = -1) const {
154  return CompareMid(str._cstr, from, count != NoIndex ? count : str._len);
155  }
156  int CompareMid(const char *cstr, size_t from, size_t count = -1) const;
157  int CompareMidNoCase(const String &str, size_t from, size_t count = -1) const {
158  return CompareMidNoCase(str._cstr, from, count != NoIndex ? count : str._len);
159  }
160  int CompareMidNoCase(const char *cstr, size_t from, size_t count = -1) const;
161  // Compares the rightmost part of this string with given C-string
162  int CompareRight(const String &str, size_t count = -1) const {
163  return CompareRight(str._cstr, count != NoIndex ? count : str._len);
164  }
165  int CompareRight(const char *cstr, size_t count = -1) const;
166  int CompareRightNoCase(const String &str, size_t count = -1) const {
167  return CompareRightNoCase(str._cstr, count != NoIndex ? count : str._len);
168  }
169  int CompareRightNoCase(const char *cstr, size_t count = -1) const;
170  // Convenience aliases for Compare functions
171  inline bool Equals(const String &str) const {
172  return Compare(str) == 0;
173  }
174  inline bool Equals(const char *cstr) const {
175  return Compare(cstr) == 0;
176  }
177  inline bool StartsWith(const String &str) const {
178  return CompareLeft(str) == 0;
179  }
180  inline bool StartsWith(const char *cstr) const {
181  return CompareLeft(cstr) == 0;
182  }
183  inline bool EndsWidth(const String &str) const {
184  return CompareRight(str) == 0;
185  }
186  inline bool EndsWidth(const char *cstr) const {
187  return CompareRight(cstr) == 0;
188  }
189 
190  // These functions search for character or substring inside this string
191  // and return the index of the (first) character, or -1 if nothing found.
192  size_t FindChar(char c, size_t from = 0) const;
193  size_t FindCharReverse(char c, size_t from = -1) const;
194  size_t FindString(const String &str, size_t from = 0) const {
195  return FindString(str._cstr, from);
196  }
197  size_t FindString(const char *cstr, size_t from = 0) const;
198 
199  // Section methods treat string as a sequence of 'fields', separated by
200  // special character. They search for a substring consisting of all such
201  // 'fields' from the 'first' to the 'last', inclusive; the bounding
202  // separators are optionally included too.
203  // Section indexes are zero-based. The first (0th) section is always
204  // located before the first separator and the last section is always
205  // located after the last separator, meaning that if the outermost
206  // character in string is separator char, there's still an empty trailing
207  // field beyond that.
208  // This also means that there's always at least one section in any string,
209  // even if there are no separating chars.
210  bool FindSection(char separator, size_t first, size_t last, bool exclude_first_sep, bool exclude_last_sep,
211  size_t &from, size_t &to) const;
212 
213  // Get Nth character with bounds check (as opposed to subscript operator)
214  inline char GetAt(size_t index) const {
215  return (index < _len) ? _cstr[index] : 0;
216  }
217  inline char GetLast() const {
218  return (_len > 0) ? _cstr[_len - 1] : 0;
219  }
220 
221  //-------------------------------------------------------------------------
222  // Value cast methods
223  //-------------------------------------------------------------------------
224 
225  int ToInt() const;
226 
227  //-------------------------------------------------------------------------
228  // Factory methods
229  //-------------------------------------------------------------------------
230 
231  // Wraps the given string buffer without owning it, won't count references,
232  // won't delete it at destruction. Can be used with string literals.
233  static String Wrapper(const char *cstr);
234 
235  // TODO: investigate C++11 solution for variadic templates (would that be more convenient here?)
236 
237  static String FromFormat(const char *fcstr, ...);
238  static String FromFormatV(const char *fcstr, va_list argptr);
239  // Reads stream until null-terminator or EOS
240  static String FromStream(Stream *in, size_t max_chars = 5 * 1024 * 1024, bool stop_at_limit = false);
241  // Reads up to N chars from stream
242  static String FromStreamCount(Stream *in, size_t count);
243 
244  // Creates a lowercased copy of the string
245  String Lower() const;
246  // Creates an uppercased copy of the string
247  String Upper() const;
248 
249  // Extract N leftmost characters as a new string
250  String Left(size_t count) const;
251  // Extract up to N characters starting from given index
252  String Mid(size_t from, size_t count = -1) const;
253  // Extract N rightmost characters
254  String Right(size_t count) const;
255 
256  // Extract leftmost part, separated by the given char; if no separator was
257  // found returns the whole string
258  String LeftSection(char separator, bool exclude_separator = true) const;
259  // Extract rightmost part, separated by the given char; if no separator was
260  // found returns the whole string
261  String RightSection(char separator, bool exclude_separator = true) const;
262  // Extract the range of Xth to Yth fields, separated by the given character
263  String Section(char separator, size_t first, size_t last,
264  bool exclude_first_sep = true, bool exclude_last_sep = true) const;
265  // Splits the string into segments divided by the instances of a given character,
266  // including empty segments e.g. if separators follow each other;
267  // returns at least one segment (equal to full string if no separator was found)
268  std::vector<String> Split(char separator) const;
269 
270  //-------------------------------------------------------------------------
271  // String modification methods
272  //-------------------------------------------------------------------------
273 
274  // Ensure string has at least space to store N chars;
275  // this does not change string contents, nor length
276  void Reserve(size_t max_length);
277  // Ensure string has at least space to store N additional chars
278  void ReserveMore(size_t more_length);
279  // Make string's buffer as small as possible to hold current data
280  void Compact();
281 
282  // Append* methods add content at the string's end, increasing its length
283  // Appends another string to this string
284  void Append(const String &str);
285  void Append(const char *cstr) {
286  String str = String::Wrapper(cstr);
287  Append(str);
288  }
289  void Append(const char *cstr, size_t len);
290  // Appends a single character
291  void AppendChar(char c);
292  // Appends a formatted string
293  void AppendFmt(MSVC_PRINTF const char *fcstr, ...) GCC_PRINTF(2, 3);
294  void AppendFmtv(const char *fcstr, va_list argptr);
295  // Clip* methods decrease the string, removing defined part
296  // Cuts off leftmost N characters
297  void ClipLeft(size_t count);
298  // Cuts out N characters starting from given index
299  void ClipMid(size_t from, size_t count = -1);
300  // Cuts off rightmost N characters
301  void ClipRight(size_t count);
302  // Cuts off leftmost part, separated by the given char; if no separator was
303  // found cuts whole string, leaving empty string
304  void ClipLeftSection(char separator, bool include_separator = true);
305  // Cuts off rightmost part, separated by the given char; if no separator
306  // was found cuts whole string, leaving empty string
307  void ClipRightSection(char separator, bool include_separator = true);
308  // Cuts out the range of Xth to Yth fields separated by the given character
309  void ClipSection(char separator, size_t first, size_t last,
310  bool include_first_sep = true, bool include_last_sep = true);
311  // Sets string length to zero
312  void Empty();
313  // Makes a new string by filling N chars with certain value
314  void FillString(char c, size_t count);
315  // Makes a new string by putting in parameters according to format string
316  void Format(const char *fcstr, ...);
317  void FormatV(const char *fcstr, va_list argptr);
318  // Decrement ref counter and deallocate data if must.
319  // Free() should be called only when buffer is not needed anymore;
320  // if string must be truncated to zero length, but retain the allocated
321  // memory, call Empty() instead.
322  void Free();
323  // Convert string to lowercase equivalent
324  void MakeLower();
325  // Convert string to uppercase equivalent
326  void MakeUpper();
327  // Merges sequences of same characters into one
328  void MergeSequences(char c = 0);
329  // Prepend* methods add content before the string's head, increasing its length
330  // Prepends another string to this string
331  void Prepend(const String &str);
332  void Prepend(const char *cstr) {
333  String str = String::Wrapper(cstr); Prepend(str);
334  }
335  // Prepends a single character
336  void PrependChar(char c);
337  // Replaces all occurrences of one character with another character
338  void Replace(char what, char with);
339  // Replaces all occurrences of one substring with another substring
340  void Replace(const String &what, const String &with);
341  void Replace(const char *what, const char *with) {
342  String whats = String::Wrapper(what), withs = String::Wrapper(with); Replace(whats, withs);
343  }
344  // Replaces particular substring with another substring; new substring
345  // may have different length
346  void ReplaceMid(size_t from, size_t count, const String &str);
347  void ReplaceMid(size_t from, size_t count, const char *cstr) {
348  String str = String::Wrapper(cstr); ReplaceMid(from, count, str);
349  }
350  // Reverses the string
351  void Reverse();
352  // Reverse the multibyte unicode string
353  // FIXME: name? invent some consistent naming for necessary multibyte funcs,
354  // proper utf8 support where necessary
355  void ReverseUTF8();
356  // Overwrite the Nth character of the string; does not change string's length
357  void SetAt(size_t index, char c);
358  // Makes a new string by copying up to N chars from C-string
359  void SetString(const char *cstr, size_t length = -1);
360  // For all Trim functions, if given character value is 0, all whitespace
361  // characters (space, tabs, CRLF) are removed.
362  // Remove heading and trailing characters from the string
363  void Trim(char c = 0);
364  // Remove heading characters from the string;
365  void TrimLeft(char c = 0);
366  // Remove trailing characters from the string
367  void TrimRight(char c = 0);
368  // Truncate* methods decrease the string to the part of itself
369  // Truncate the string to the leftmost N characters
370  void TruncateToLeft(size_t count);
371  // Truncate the string to the middle N characters
372  void TruncateToMid(size_t from, size_t count = -1);
373  // Truncate the string to the rightmost N characters
374  void TruncateToRight(size_t count);
375  // Truncate the string to the leftmost part, separated by the given char;
376  // if no separator was found leaves string unchanged
377  void TruncateToLeftSection(char separator, bool exclude_separator = true);
378  // Truncate the string to the rightmost part, separated by the given char;
379  // if no separator was found leaves string unchanged
380  void TruncateToRightSection(char separator, bool exclude_separator = true);
381  // Truncate the string to range of Xth to Yth fields separated by the
382  // given character
383  void TruncateToSection(char separator, size_t first, size_t last,
384  bool exclude_first_sep = true, bool exclude_last_sep = true);
385  // Wraps the given string buffer without owning it, won't count references,
386  // won't delete it at destruction. Can be used with string literals.
387  void Wrap(const char *cstr);
388 
389  //-------------------------------------------------------------------------
390  // Operators
391  //-------------------------------------------------------------------------
392 
393  // Assign String by sharing data reference
394  String &operator=(const String &str);
395  // Move operator
396  String &operator=(String &&str);
397  // Assign C-string by copying contents
398  String &operator=(const char *cstr);
399  inline char operator[](size_t index) const {
400  assert(index < _len);
401  return _cstr[index];
402  }
403  inline bool operator ==(const String &str) const {
404  return Compare(str) == 0;
405  }
406  inline bool operator ==(const char *cstr) const {
407  return Compare(cstr) == 0;
408  }
409  inline bool operator !=(const String &str) const {
410  return Compare(str) != 0;
411  }
412  inline bool operator !=(const char *cstr) const {
413  return Compare(cstr) != 0;
414  }
415  inline bool operator <(const String &str) const {
416  return Compare(str) < 0;
417  }
418  inline bool operator <(const char *cstr) const {
419  return Compare(cstr) < 0;
420  }
421  // Converts an AGS string to a ScummVM one
422  operator Common::String() const {
423  return Common::String(_cstr);
424  }
425  // Fixes compilation error in script_set
426  operator bool() const {
427  return !IsEmpty();
428  }
429  operator const char *() const {
430  return GetCStr();
431  }
432 
433 private:
434  // Creates new empty string with buffer enough to fit given length
435  void Create(size_t buffer_length);
436  // Release string and copy data to the new buffer
437  void Copy(size_t buffer_length, size_t offset = 0);
438  // Aligns data at given offset
439  void Align(size_t offset);
440 
441  // Tells if this object shares its string buffer with others
442  bool IsShared() const;
443  // Ensure this string is a writeable independent copy, with ref counter = 1
444  void BecomeUnique();
445  // Ensure this string is independent, and there's enough space before
446  // or after the current string data
447  void ReserveAndShift(bool left, size_t more_length);
448 
449  // Internal String data
450  char *_cstr; // pointer to actual string data; always valid, never null
451  size_t _len; // valid string length, in characters, excluding null-term
452 
453  // Header of a reference-counted buffer
454  struct BufHeader {
455  size_t RefCount = 0; // reference count
456  size_t Capacity = 0; // available space, in characters
457  };
458 
459  // Union that groups mutually exclusive data (currently only ref counted buffer)
460  union {
461  char *_buf; // reference-counted data (raw ptr)
462  BufHeader *_bufHead; // the header of a reference-counted data
463  };
464 };
465 
466 } // namespace Shared
467 } // namespace AGS
468 } // namespace AGS3
469 
470 #endif
Definition: achievements_tables.h:27
Definition: str.h:59
int FORCEINLINE GCC_PRINTF(2, 0) int vsprintf_s(T(&dst)[N]
Definition: string.h:62
Definition: stream.h:52
Definition: ags.h:40