str.hpp

Go to the documentation of this file.
00001 /* $Id: str.hpp 21890 2011-01-22 14:52:20Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #ifndef STR_HPP
00013 #define STR_HPP
00014 
00015 #include <errno.h>
00016 #include <stdarg.h>
00017 #include "blob.hpp"
00018 #include "../core/math_func.hpp"
00019 #include "../string_func.h"
00020 
00022 struct CStrA : public CBlobT<char>
00023 {
00024   typedef CBlobT<char> base;                    
00025 
00027   FORCEINLINE CStrA()
00028   {
00029   }
00030 
00032   FORCEINLINE CStrA(const CStrA &src) : base(src)
00033   {
00034     base::FixTail();
00035   }
00036 
00038   FORCEINLINE CStrA(const OnTransfer& ot)
00039     : base(ot)
00040   {
00041   }
00042 
00044   FORCEINLINE char *GrowSizeNC(uint count)
00045   {
00046     char *ret = base::GrowSizeNC(count);
00047     base::FixTail();
00048     return ret;
00049   }
00050 
00052   FORCEINLINE void AppendStr(const char *str)
00053   {
00054     if (!StrEmpty(str)) {
00055       base::AppendRaw(str, strlen(str));
00056       base::FixTail();
00057     }
00058   }
00059 
00061   FORCEINLINE void Append(const CStrA &src)
00062   {
00063     if (src.Length() > 0) {
00064       base::AppendRaw(src);
00065       base::FixTail();
00066     }
00067   }
00068 
00070   FORCEINLINE CStrA &operator = (const char *src)
00071   {
00072     base::Clear();
00073     AppendStr(src);
00074     return *this;
00075   }
00076 
00078   FORCEINLINE CStrA &operator = (const CStrA &src)
00079   {
00080     if (&src != this) {
00081       base::Clear();
00082       base::AppendRaw(src.Data(), src.Size());
00083       base::FixTail();
00084     }
00085     return *this;
00086   }
00087 
00089   FORCEINLINE bool operator < (const CStrA &other) const
00090   {
00091     return strcmp(base::Data(), other.Data()) < 0;
00092   }
00093 
00095   int AddFormatL(const char *format, va_list args)
00096   {
00097     size_t addSize = max<size_t>(strlen(format), 16);
00098     addSize += addSize / 2;
00099     int ret;
00100     int err = 0;
00101     for (;;) {
00102       char *buf = MakeFreeSpace(addSize);
00103       ret = vsnprintf(buf, base::GetReserve(), format, args);
00104       if (ret >= (int)base::GetReserve()) {
00105         /* Greater return than given count means needed buffer size. */
00106         addSize = ret + 1;
00107         continue;
00108       }
00109       if (ret >= 0) {
00110         /* success */
00111         break;
00112       }
00113       err = errno;
00114       if (err != ERANGE && err != ENOENT && err != 0) {
00115         /* some strange failure */
00116         break;
00117       }
00118       /* small buffer (M$ implementation) */
00119       addSize *= 2;
00120     }
00121     if (ret > 0) {
00122       GrowSizeNC(ret);
00123     } else {
00124       base::FixTail();
00125     }
00126     return ret;
00127   }
00128 
00130   int CDECL WARN_FORMAT(2, 3) AddFormat(const char *format, ...)
00131   {
00132     va_list args;
00133     va_start(args, format);
00134     int ret = AddFormatL(format, args);
00135     va_end(args);
00136     return ret;
00137   }
00138 
00140   int CDECL WARN_FORMAT(2, 3) Format(const char *format, ...)
00141   {
00142     base::Free();
00143     va_list args;
00144     va_start(args, format);
00145     int ret = AddFormatL(format, args);
00146     va_end(args);
00147     return ret;
00148   }
00149 };
00150 
00151 #endif /* STR_HPP */