pstring.cxx (4938B)
1 /* 2 * 3 * C++ Portable Types Library (PTypes) 4 * Version 2.1.1 Released 27-Jun-2007 5 * 6 * Copyright (C) 2001-2007 Hovik Melikyan 7 * 8 * http://www.melikyan.com/ptypes/ 9 * 10 */ 11 12 #include <stdlib.h> 13 #include <string.h> 14 #include <time.h> 15 16 #include "ptypes.h" 17 #include "ptime.h" // nowstring() is defined in this module 18 19 20 namespace ptypes { 21 22 23 const int strrecsize = sizeof(_strrec); 24 25 26 static void stringoverflow() 27 { 28 fatal(CRIT_FIRST + 21, "String overflow"); 29 } 30 31 32 void string::idxerror() 33 { 34 fatal(CRIT_FIRST + 20, "String index overflow"); 35 } 36 37 38 int stralloc; 39 40 char emptystrbuf[strrecsize + 4]; 41 char* emptystr = emptystrbuf + strrecsize; 42 43 44 string nullstring; 45 46 47 inline int quantize(int numchars) 48 { 49 return memquantize(numchars + 1 + strrecsize); 50 } 51 52 53 void string::_alloc(int numchars) 54 { 55 if (numchars <= 0) 56 stringoverflow(); 57 size_t a = quantize(numchars); 58 #ifdef DEBUG 59 stralloc += a; 60 #endif 61 data = (char*)(memalloc(a)) + strrecsize; 62 STR_LENGTH(data) = numchars; 63 STR_REFCOUNT(data) = 1; 64 data[numchars] = 0; 65 } 66 67 68 void string::_realloc(int numchars) 69 { 70 if (numchars <= 0 || STR_LENGTH(data) <= 0) 71 stringoverflow(); 72 int a = quantize(numchars); 73 int b = quantize(STR_LENGTH(data)); 74 if (a != b) 75 { 76 #ifdef DEBUG 77 stralloc += a - b; 78 #endif 79 data = (char*)(memrealloc(data - strrecsize, a)) + strrecsize; 80 } 81 STR_LENGTH(data) = numchars; 82 data[numchars] = 0; 83 } 84 85 86 inline void _freestrbuf(char* data) 87 { 88 #ifdef DEBUG 89 stralloc -= quantize(STR_LENGTH(data)); 90 #endif 91 memfree((char*)(STR_BASE(data))); 92 } 93 94 95 void string::_free() 96 { 97 _freestrbuf(data); 98 data = emptystr; 99 } 100 101 102 void string::initialize(const char* sc, int initlen) 103 { 104 if (initlen <= 0 || sc == nil) 105 data = emptystr; 106 else 107 { 108 _alloc(initlen); 109 memmove(data, sc, initlen); 110 } 111 } 112 113 114 void string::initialize(const char* sc) 115 { 116 initialize(sc, hstrlen(sc)); 117 } 118 119 120 void string::initialize(char c) 121 { 122 _alloc(1); 123 data[0] = c; 124 } 125 126 127 void string::initialize(const string& s) 128 { 129 data = s.data; 130 #ifdef PTYPES_ST 131 STR_REFCOUNT(data)++; 132 #else 133 pincrement(&STR_REFCOUNT(data)); 134 #endif 135 } 136 137 138 void string::finalize() 139 { 140 if (STR_LENGTH(data) != 0) 141 { 142 143 #ifdef PTYPES_ST 144 if (--STR_REFCOUNT(data) == 0) 145 #else 146 if (pdecrement(&STR_REFCOUNT(data)) == 0) 147 #endif 148 _freestrbuf(data); 149 150 data = emptystr; 151 } 152 } 153 154 155 char* ptdecl unique(string& s) 156 { 157 if (STR_LENGTH(s.data) > 0 && STR_REFCOUNT(s.data) > 1) 158 { 159 char* odata = s.data; 160 s._alloc(STR_LENGTH(s.data)); 161 memcpy(s.data, odata, STR_LENGTH(s.data)); 162 #ifdef PTYPES_ST 163 STR_REFCOUNT(odata)--; 164 #else 165 if (pdecrement(&STR_REFCOUNT(odata)) == 0) 166 _freestrbuf(odata); 167 #endif 168 } 169 return s.data; 170 } 171 172 173 char* ptdecl setlength(string& s, int newlen) 174 { 175 if (newlen < 0) 176 return nil; 177 178 int curlen = STR_LENGTH(s.data); 179 180 // if becoming empty 181 if (newlen == 0) 182 s.finalize(); 183 184 // if otherwise s was empty before 185 else if (curlen == 0) 186 s._alloc(newlen); 187 188 // if length is not changing, return a unique string 189 else if (newlen == curlen) 190 unique(s); 191 192 // non-unique reallocation 193 else if (STR_REFCOUNT(s.data) > 1) 194 { 195 char* odata = s.data; 196 s._alloc(newlen); 197 memcpy(s.data, odata, imin(curlen, newlen)); 198 #ifdef PTYPES_ST 199 STR_REFCOUNT(odata)--; 200 #else 201 if (pdecrement(&STR_REFCOUNT(odata)) == 0) 202 _freestrbuf(odata); 203 #endif 204 } 205 206 // unique reallocation 207 else 208 s._realloc(newlen); 209 210 return s.data; 211 } 212 213 214 void string::assign(const char* sc, int initlen) 215 { 216 if (STR_LENGTH(data) > 0 && initlen > 0 && STR_REFCOUNT(data) == 1) 217 { 218 // reuse data buffer if unique 219 _realloc(initlen); 220 memmove(data, sc, initlen); 221 } 222 else 223 { 224 finalize(); 225 if (initlen == 1) 226 initialize(sc[0]); 227 else if (initlen > 1) 228 initialize(sc, initlen); 229 } 230 } 231 232 233 void string::assign(const char* sc) 234 { 235 assign(sc, hstrlen(sc)); 236 } 237 238 239 void string::assign(char c) 240 { 241 assign(&c, 1); 242 } 243 244 245 void string::assign(const string& s) 246 { 247 if (data != s.data) 248 { 249 finalize(); 250 initialize(s); 251 } 252 } 253 254 255 string ptdecl dup(const string& s) 256 { 257 // dup() only reads the data pointer so it is thread-safe 258 return string(s.data); 259 } 260 261 262 string ptdecl nowstring(const char* fmt, bool utc) 263 { 264 char buf[128]; 265 time_t longtime; 266 time(&longtime); 267 268 #if defined(PTYPES_ST) || defined(WIN32) 269 tm* t; 270 if (utc) 271 t = gmtime(&longtime); 272 else 273 t = localtime(&longtime); 274 int r = strftime(buf, sizeof(buf), fmt, t); 275 #else 276 tm t; 277 if (utc) 278 gmtime_r(&longtime, &t); 279 else 280 localtime_r(&longtime, &t); 281 int r = strftime(buf, sizeof(buf), fmt, &t); 282 #endif 283 284 buf[r] = 0; 285 return string(buf); 286 } 287 288 289 }