Merge branch 'development' into feature/no_multiplayer_grf_limit
[openttd-joker.git] / src / misc / str.hpp
blobbacfba9a73ca9afc22bc9755a4f7a204a99490db
1 /* $Id: str.hpp 23640 2011-12-20 17:57:56Z truebrain $ */
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 */
10 /** @file str.hpp String formating? */
12 #ifndef STR_HPP
13 #define STR_HPP
15 #include <errno.h>
16 #include <stdarg.h>
17 #include "blob.hpp"
18 #include "../core/math_func.hpp"
19 #include "../string_func.h"
21 /** Blob based case sensitive ANSI/UTF-8 string */
22 struct CStrA : public CBlobT<char>
24 typedef CBlobT<char> base; ///< base class
26 /** Create an empty CStrT */
27 inline CStrA()
31 /** Copy constructor */
32 inline CStrA(const CStrA &src) : base(src)
34 base::FixTail();
37 /** Take over ownership constructor */
38 inline CStrA(const OnTransfer &ot)
39 : base(ot)
43 /** Grow the actual buffer and fix the trailing zero at the end. */
44 inline char *GrowSizeNC(uint count)
46 char *ret = base::GrowSizeNC(count);
47 base::FixTail();
48 return ret;
51 /** Append zero-ended C string. */
52 inline void AppendStr(const char *str)
54 if (!StrEmpty(str)) {
55 base::AppendRaw(str, strlen(str));
56 base::FixTail();
60 /** Append another CStrA. */
61 inline void Append(const CStrA &src)
63 if (src.Length() > 0) {
64 base::AppendRaw(src);
65 base::FixTail();
69 /** Assignment from C string. */
70 inline CStrA &operator=(const char *src)
72 base::Clear();
73 AppendStr(src);
74 return *this;
77 /** Assignment from another CStrA. */
78 inline CStrA &operator=(const CStrA &src)
80 if (&src != this) {
81 base::Clear();
82 base::AppendRaw(src.Data(), src.Size());
83 base::FixTail();
85 return *this;
88 /** Lower-than operator (to support stl collections) */
89 inline bool operator<(const CStrA &other) const
91 return strcmp(base::Data(), other.Data()) < 0;
94 /** Add formated string (like vsprintf) at the end of existing contents. */
95 int AddFormatL(const char *format, va_list args)
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;
109 if (ret >= 0) {
110 /* success */
111 break;
113 err = errno;
114 if (err != ERANGE && err != ENOENT && err != 0) {
115 /* some strange failure */
116 break;
118 /* small buffer (M$ implementation) */
119 addSize *= 2;
121 if (ret > 0) {
122 GrowSizeNC(ret);
123 } else {
124 base::FixTail();
126 return ret;
129 /** Add formated string (like sprintf) at the end of existing contents. */
130 int CDECL WARN_FORMAT(2, 3) AddFormat(const char *format, ...)
132 va_list args;
133 va_start(args, format);
134 int ret = AddFormatL(format, args);
135 va_end(args);
136 return ret;
139 /** Assign formated string (like sprintf). */
140 int CDECL WARN_FORMAT(2, 3) Format(const char *format, ...)
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;
151 #endif /* STR_HPP */