00001
00002
00003
00004 #ifndef _STR_H
00005 #define _STR_H
00006
00007 #include "util.h"
00008
00012 #define PUNC_CHARS "&!|/:;=+*-.$@^%?`,\\"
00013
00017 #define BRAC_CHARS "<([{}])>"
00018
00022 #define ESCAPE_CODES "nrtbf\\\"/"
00023
00027 #define ESCAPE_CHARS "\n\r\t\b\f\\\"/"
00028
00029 namespace jvar
00030 {
00031
00039 std::string format(const char* fmt, ...);
00040
00047 void format(std::string& outstr, const char* fmt, ...);
00048
00058 bool vformat(std::string& outstr, const char* fmt, va_list varg);
00059
00065 void upperCase(std::string& str);
00066
00072 void lowerCase(std::string& str);
00073
00083 uint makeUnicode(const char* s, int maxlen, int* lenused = NULL);
00084
00092 std::string makeUTF8(uint charcode);
00093
00103 bool equal(const char* s1, const char* s2, bool ignorecase = false);
00104 inline bool strfind(const char* s, char c, int* pos = NULL)
00105 {
00106 const char* foundp = strchr(s, c);
00107 if (foundp)
00108 {
00109 if (pos)
00110 {
00111 *pos = (foundp - s);
00112 }
00113 return true;
00114 }
00115 return false;
00116 }
00117
00125 std::string int2str(longint n);
00126
00133 inline void int2str(std::string& s, longint n)
00134 {
00135 format(s, "%ld", n);
00136 }
00137
00145 std::string dbl2str(double d);
00146
00153 inline void dbl2str(std::string& s, double d)
00154 {
00155 format(s, "%lf", d);
00156 }
00157
00167 longint str2baseint(const std::string& str, int base, bool* valid = NULL);
00168
00177 inline longint str2int(const std::string& str, bool* valid = NULL)
00178 {
00179 return str2baseint(str, 10, valid);
00180 }
00181
00190 double str2dbl(const std::string& str, bool* valid = NULL);
00191
00201 inline std::string pathParent(const std::string p, const char* delim)
00202 {
00203 return p.substr(0, p.find_last_of(delim));
00204 }
00205
00215 inline std::string pathChild(const std::string p, const char* delim)
00216 {
00217 return p.substr(p.find_last_of(delim) + 1);
00218 }
00219
00225 template <int MAXFIXED>
00226 class FixedStr
00227 {
00228 public:
00229 inline FixedStr()
00230 {
00231 mFixed[0] = '\0';
00232 }
00233 ~FixedStr()
00234 {
00235 if (mFixed[0] == '\1')
00236 {
00237 if (mDyn.ptr)
00238 {
00239 free(mDyn.ptr);
00240 }
00241 }
00242 }
00243 inline FixedStr(const FixedStr& src)
00244 {
00245 mFixed[0] = '\0';
00246 set(src.get());
00247 }
00248 inline FixedStr(FixedStr& src)
00249 {
00250 mFixed[0] = '\0';
00251 set(src.get());
00252 }
00253 inline FixedStr& operator=(const FixedStr& src)
00254 {
00255 set(src.get());
00256 return *this;
00257 }
00258 inline FixedStr& operator=(const FixedStr* src)
00259 {
00260 set(src.get());
00261 return *this;
00262 }
00263
00264 void set(const char* val)
00265 {
00266 int len = strlen(val);
00267 char* dest;
00268
00269 if (mFixed[0] == '\2')
00270 {
00271 mFixed[0] = '\0';
00272 }
00273
00274 if (len > (MAXFIXED - 2))
00275 {
00276
00277
00278 if (isFixed())
00279 {
00280 mFixed[0] = '\1';
00281
00282 mDyn.ptr = NULL;
00283 mDyn.size = 0;
00284 }
00285 ensureDyn(len + 1);
00286 dest = mDyn.ptr;
00287 }
00288 else
00289 {
00290
00291
00292 if (isFixed())
00293 {
00294 dest = &(mFixed[1]);
00295 }
00296 else
00297 {
00298 ensureDyn(len + 1);
00299 dest = mDyn.ptr;
00300 }
00301 }
00302
00303 memcpy(dest, val, len + 1);
00304 }
00305
00306 void setExt(const char* val)
00307 {
00308
00309
00310
00311 mFixed[0] = '\2';
00312
00313 mDyn.ptr = (char*)val;
00314 mDyn.size = 0;
00315 }
00316
00317 const char* get() const
00318 {
00319 if (isFixed())
00320 {
00321 return &(mFixed[1]);
00322 }
00323 else
00324 {
00325 return mDyn.ptr;
00326 }
00327 }
00328
00329 void clear()
00330 {
00331 if (mFixed[0] == '\1')
00332 {
00333 if (mDyn.ptr)
00334 {
00335 free(mDyn.ptr);
00336 }
00337 }
00338 mFixed[0] = '\0';
00339 }
00340
00341 private:
00342 union
00343 {
00344 struct
00345 {
00346 int tag;
00347 char* ptr;
00348 int size;
00349 } mDyn;
00350 char mFixed[MAXFIXED];
00351 };
00352
00353 inline bool isFixed() const
00354 {
00355 return mFixed[0] == '\0';
00356 }
00357
00358 void ensureDyn(int size)
00359 {
00360 if (mDyn.ptr != NULL && mDyn.size >= size)
00361 {
00362 return;
00363 }
00364
00365 void* p = ::realloc(mDyn.ptr, size);
00366 if (p == NULL)
00367 {
00368 dbgerr("FixedStr failed to allocate %d bytes\n", size);
00369 return;
00370 }
00371 mDyn.ptr = (char*)p;
00372 mDyn.size = size;
00373 }
00374 };
00375
00384 class Parser
00385 {
00386 public:
00392 Parser(const char* txt);
00393
00399 inline bool eof()
00400 {
00401 return (mPos >= mTxtLen) || mErr;
00402 }
00403
00409 inline bool failed()
00410 {
00411 return mErr;
00412 }
00413
00419 inline const std::string& errMsg()
00420 {
00421 return mErrMsg;
00422 }
00423
00429 inline const char* c_str()
00430 {
00431 return token().c_str();
00432 }
00433
00439 inline const std::string& token()
00440 {
00441 parseToken();
00442 return mToken;
00443 }
00444
00452 inline bool tokenEquals(const char* val)
00453 {
00454 return token().compare(val) == 0;
00455 }
00456
00460 inline void advance()
00461 {
00462 mTokParsed = false;
00463 }
00464
00470 void advance(const char* match);
00471
00477 void setError(const char* msg);
00478
00484 void stripQuotes(bool allowsingle);
00485
00486 void captureDelim(const char* delim);
00487
00488 private:
00489 enum TokenStateEnum
00490 {
00491 NullTok, WordTok, PuncTok, BracTok, QuoteTok
00492 };
00493
00494 const char* mTxt;
00495 std::string mToken;
00496 bool mTokParsed;
00497 int mPos;
00498 int mLineNum;
00499 bool mErr;
00500 int mTxtLen;
00501 std::string mErrMsg;
00502
00503 protected:
00504 inline bool charWord(char c)
00505 {
00506 return (isalnum(c) || (c == '_') || (c == '\''));
00507 }
00508 inline bool charPunc(char c)
00509 {
00510 return (strchr(PUNC_CHARS, c) != NULL);
00511 }
00512 inline bool charBrac(char c)
00513 {
00514 return (strchr(BRAC_CHARS, c) != NULL);
00515 }
00516
00517 private:
00518 void parseToken();
00519
00520 inline void append(char c)
00521 {
00522 mToken += c;
00523 }
00524 inline void append(const std::string& s)
00525 {
00526 mToken += s;
00527 }
00528 inline void replaceLast(char c)
00529 {
00530 int l = mToken.length();
00531 if (l > 0)
00532 {
00533 mToken[l - 1] = c;
00534 }
00535 }
00536 inline void eraseLast()
00537 {
00538 int l = mToken.length();
00539 if (l >= 1)
00540 {
00541 mToken.erase(l - 1, 1);
00542 }
00543 }
00544 inline TokenStateEnum detState(char c)
00545 {
00546 if (c == '"' || c == '\'')
00547 {
00548 return QuoteTok;
00549 }
00550 if (charWord(c))
00551 {
00552 return WordTok;
00553 }
00554 if (charBrac(c))
00555 {
00556 return BracTok;
00557 }
00558
00559
00560 return PuncTok;
00561 }
00562
00563 };
00564
00565 }
00566
00567
00568 #endif // _STR_H
00569