jvar
JS inspired Variant and Json
str.h
00001 // Copyright (c) 2014 Yasser Asmi
00002 // Released under the MIT License (http://opensource.org/licenses/MIT)
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             // Cannot fit in fixed
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             // Can fit in fixed
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         // Stores an external pointer and doesn't try to free it.
00309         // Can only be called once.  Can call set() after this, however.
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         //TODO: Should this call charPunc?
00559 
00560         return PuncTok;
00561     }
00562 
00563 };
00564 
00565 } // jvar
00566 
00567 
00568 #endif // _STR_H
00569 
 All Classes Functions Variables Enumerator