src/misc/str.hpp
branchNewGRF_ports
changeset 6720 35756db7e577
child 6725 23339968083f
equal deleted inserted replaced
6719:4cc327ad39d5 6720:35756db7e577
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file str.hpp */
       
     4 
       
     5 #ifndef  STR_HPP
       
     6 #define  STR_HPP
       
     7 
       
     8 #include <errno.h>
       
     9 #include <stdarg.h>
       
    10 #include "strapi.hpp"
       
    11 
       
    12 /** Blob based string. */
       
    13 template <typename Tchar, bool TcaseInsensitive>
       
    14 struct CStrT : public CBlobT<Tchar>
       
    15 {
       
    16 	typedef CBlobT<Tchar> base;                    ///< base class
       
    17 	typedef CStrApiT<Tchar, TcaseInsensitive> Api; ///< string API abstraction layer
       
    18 	typedef typename base::bsize_t bsize_t;        ///< size type inherited from blob
       
    19 	typedef typename base::OnTransfer OnTransfer;  ///< temporary 'transfer ownership' object type
       
    20 
       
    21 	/** Construction from C zero ended string. */
       
    22 	FORCEINLINE CStrT(const Tchar* str = NULL)
       
    23 	{
       
    24 		AppendStr(str);
       
    25 	}
       
    26 
       
    27 	/** Construction from C string and given number of characters. */
       
    28 	FORCEINLINE CStrT(const Tchar* str, bsize_t num_chars) : base(str, num_chars)
       
    29 	{
       
    30 		base::FixTail();
       
    31 	}
       
    32 
       
    33 	/** Construction from C string determined by 'begin' and 'end' pointers. */
       
    34 	FORCEINLINE CStrT(const Tchar* str, const Tchar* end)
       
    35 		: base(str, end - str)
       
    36 	{
       
    37 		base::FixTail();
       
    38 	}
       
    39 
       
    40 	/** Construction from blob contents. */
       
    41 	FORCEINLINE CStrT(const CBlobBaseSimple& src)
       
    42 		: base(src)
       
    43 	{
       
    44 		base::FixTail();
       
    45 	}
       
    46 
       
    47 	/** Copy constructor. */
       
    48 	FORCEINLINE CStrT(const CStrT& src)
       
    49 		: base(src)
       
    50 	{
       
    51 		base::FixTail();
       
    52 	}
       
    53 
       
    54 	/** Take over ownership constructor */
       
    55 	FORCEINLINE CStrT(const OnTransfer& ot)
       
    56 		: base(ot)
       
    57 	{
       
    58 	}
       
    59 
       
    60 	/** Grow the actual buffer and fix the trailing zero at the end. */
       
    61 	FORCEINLINE Tchar* GrowSizeNC(bsize_t count)
       
    62 	{
       
    63 		Tchar* ret = base::GrowSizeNC(count);
       
    64 		base::FixTail();
       
    65 		return ret;
       
    66 	}
       
    67 
       
    68 	/** Append zero-ended C string. */
       
    69 	FORCEINLINE void AppendStr(const Tchar* str)
       
    70 	{
       
    71 		if (str != NULL && str[0] != '\0') {
       
    72 			base::Append(str, (bsize_t)Api::StrLen(str));
       
    73 			base::FixTail();
       
    74 		}
       
    75 	}
       
    76 
       
    77 	/** Append another CStrT or blob. */
       
    78 	FORCEINLINE void Append(const CBlobBaseSimple& src)
       
    79 	{
       
    80 		if (src.RawSize() > 0) {
       
    81 			base::AppendRaw(src);
       
    82 			base::FixTail();
       
    83 		}
       
    84 	}
       
    85 
       
    86 	/** Assignment from C string. */
       
    87 	FORCEINLINE CStrT& operator = (const Tchar* src)
       
    88 	{
       
    89 		base::Clear();
       
    90 		AppendStr(src);
       
    91 		return *this;
       
    92 	}
       
    93 
       
    94 	/** Assignment from another CStrT or blob. */
       
    95 	FORCEINLINE CStrT& operator = (const CBlobBaseSimple& src)
       
    96 	{
       
    97 		base::Clear();
       
    98 		base::AppendRaw(src);
       
    99 		base::FixTail();
       
   100 		return *this;
       
   101 	}
       
   102 
       
   103 	/** Assignment from another CStrT or blob. */
       
   104 	FORCEINLINE CStrT& operator = (const CStrT& src)
       
   105 	{
       
   106 		base::Clear();
       
   107 		base::AppendRaw(src);
       
   108 		base::FixTail();
       
   109 		return *this;
       
   110 	}
       
   111 
       
   112 	/** Lower-than operator (to support stl collections) */
       
   113 	FORCEINLINE bool operator < (const CStrT &other) const
       
   114 	{
       
   115 		return (Api::StrCmp(base::Data(), other.Data()) < 0);
       
   116 	}
       
   117 
       
   118 	/** Add formated string (like vsprintf) at the end of existing contents. */
       
   119 	int AddFormatL(const Tchar *format, va_list args)
       
   120 	{
       
   121 		bsize_t addSize = Api::StrLen(format);
       
   122 		if (addSize < 16) addSize = 16;
       
   123 		addSize += addSize / 2;
       
   124 		int ret;
       
   125 		int err = 0;
       
   126 		for (;;) {
       
   127 			Tchar *buf = MakeFreeSpace(addSize);
       
   128 			ret = Api::SPrintFL(buf, base::GetReserve(), format, args);
       
   129 			if (ret >= base::GetReserve()) {
       
   130 				/* Greater return than given count means needed buffer size. */
       
   131 				addSize = ret + 1;
       
   132 				continue;
       
   133 			}
       
   134 			if (ret >= 0) {
       
   135 				/* success */
       
   136 				break;
       
   137 			}
       
   138 			err = errno;
       
   139 			if (err != ERANGE && err != ENOENT && err != 0) {
       
   140 				/* some strange failure */
       
   141 				break;
       
   142 			}
       
   143 			/* small buffer (M$ implementation) */
       
   144 			addSize *= 2;
       
   145 		}
       
   146 		if (ret > 0) {
       
   147 			GrowSizeNC(ret);
       
   148 		} else {
       
   149 			base::FixTail();
       
   150 		}
       
   151 		return ret;
       
   152 	}
       
   153 
       
   154 	/** Add formated string (like sprintf) at the end of existing contents. */
       
   155 	int AddFormat(const Tchar *format, ...)
       
   156 	{
       
   157 		va_list args;
       
   158 		va_start(args, format);
       
   159 		int ret = AddFormatL(format, args);
       
   160 		va_end(args);
       
   161 		return ret;
       
   162 	}
       
   163 
       
   164 	/** Assign formated string (like vsprintf). */
       
   165 	int FormatL(const Tchar *format, va_list args)
       
   166 	{
       
   167 		base::Free();
       
   168 		int ret = AddFormatL(format, args);
       
   169 		return ret;
       
   170 	}
       
   171 
       
   172 	/** Assign formated string (like sprintf). */
       
   173 	int Format(const Tchar *format, ...)
       
   174 	{
       
   175 		base::Free();
       
   176 		va_list args;
       
   177 		va_start(args, format);
       
   178 		int ret = AddFormatL(format, args);
       
   179 		va_end(args);
       
   180 		return ret;
       
   181 	}
       
   182 };
       
   183 
       
   184 typedef CStrT<char   , false> CStrA;   ///< Case sensitive ANSI/UTF-8 string
       
   185 typedef CStrT<char   , true > CStrCiA; ///< Case insensitive ANSI/UTF-8 string
       
   186 typedef CStrT<wchar_t, false> CStrW;   ///< Case sensitive unicode string
       
   187 typedef CStrT<wchar_t, true > CStrCiW; ///< Case insensitive unicode string
       
   188 
       
   189 #endif /* STR_HPP */