OpenTTD
str.hpp
Go to the documentation of this file.
1 /* $Id: str.hpp 27362 2015-08-08 10:06:24Z alberth $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #ifndef STR_HPP
13 #define STR_HPP
14 
15 #include <errno.h>
16 #include <stdarg.h>
17 #include "blob.hpp"
18 #include "../core/math_func.hpp"
19 #include "../string_func.h"
20 
22 struct CStrA : public CBlobT<char>
23 {
24  typedef CBlobT<char> base;
25 
27  inline CStrA()
28  {
29  }
30 
32  inline CStrA(const CStrA &src) : base(src)
33  {
34  base::FixTail();
35  }
36 
38  inline CStrA(const OnTransfer &ot)
39  : base(ot)
40  {
41  }
42 
44  inline char *GrowSizeNC(uint count)
45  {
46  char *ret = base::GrowSizeNC(count);
47  base::FixTail();
48  return ret;
49  }
50 
52  inline void AppendStr(const char *str)
53  {
54  if (!StrEmpty(str)) {
55  base::AppendRaw(str, strlen(str));
56  base::FixTail();
57  }
58  }
59 
61  inline void Append(const CStrA &src)
62  {
63  if (src.Length() > 0) {
64  base::AppendRaw(src);
65  base::FixTail();
66  }
67  }
68 
70  inline CStrA &operator=(const char *src)
71  {
72  base::Clear();
73  AppendStr(src);
74  return *this;
75  }
76 
78  inline CStrA &operator=(const CStrA &src)
79  {
80  if (&src != this) {
81  base::Clear();
82  base::AppendRaw(src.Data(), src.Size());
83  base::FixTail();
84  }
85  return *this;
86  }
87 
89  inline bool operator<(const CStrA &other) const
90  {
91  return strcmp(base::Data(), other.Data()) < 0;
92  }
93 
95  int AddFormatL(const char *format, va_list args)
96  {
97  size_t addSize = max<size_t>(strlen(format), 16);
98  addSize += addSize / 2;
99  int ret;
100  int err = 0;
101  for (;;) {
102  char *buf = MakeFreeSpace(addSize);
103  ret = vseprintf(buf, buf + base::GetReserve() - 1, format, args);
104  if (ret >= (int)base::GetReserve()) {
105  /* Greater return than given count means needed buffer size. */
106  addSize = ret + 1;
107  continue;
108  }
109  if (ret >= 0) {
110  /* success */
111  break;
112  }
113  err = errno;
114  if (err != ERANGE && err != ENOENT && err != 0) {
115  /* some strange failure */
116  break;
117  }
118  /* small buffer (M$ implementation) */
119  addSize *= 2;
120  }
121  if (ret > 0) {
122  GrowSizeNC(ret);
123  } else {
124  base::FixTail();
125  }
126  return ret;
127  }
128 
130  int CDECL WARN_FORMAT(2, 3) AddFormat(const char *format, ...)
131  {
132  va_list args;
133  va_start(args, format);
134  int ret = AddFormatL(format, args);
135  va_end(args);
136  return ret;
137  }
138 
140  int CDECL WARN_FORMAT(2, 3) Format(const char *format, ...)
141  {
142  base::Free();
143  va_list args;
144  va_start(args, format);
145  int ret = AddFormatL(format, args);
146  va_end(args);
147  return ret;
148  }
149 };
150 
151 #endif /* STR_HPP */