source: cpp/frams/util/sstringutils.cpp @ 547

Last change on this file since 547 was 529, checked in by Maciej Komosinski, 8 years ago

\r can be optionally removed while loading

  • Property svn:eol-style set to native
File size: 6.4 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
[109]4
5#include "sstringutils.h"
[382]6#include <common/virtfile/virtfile.h>
[375]7#include <common/log.h>
[109]8#include <common/nonstd.h>
9
[529]10int loadSString(const char* filename, SString& s, const char* framsgmodule, const char* error, bool remove_cr)
[109]11{
[257]12        VirtFILE *f;
13        int ret = 0;
14        if (f = Vfopen(filename, FOPEN_READ_BINARY))
[109]15        {
[529]16                loadSString(f, s, remove_cr);
[257]17                ret = 1;
[523]18                delete f;
[109]19        }
[257]20        else if (framsgmodule)
[375]21                logPrintf(framsgmodule, "loadSString", LOG_WARN, error ? error : "can't open file \"%s\"", filename);
[257]22        return ret;
[109]23}
24
[529]25void loadSString(VirtFILE *f, SString& s, bool remove_cr)
[109]26{
[257]27        char buf[1024];
28        int len;
29        while (!f->Veof())
[109]30        {
[523]31                len = f->Vread(buf, 1, sizeof(buf));
[257]32                s.append(buf, len);
[109]33        }
[529]34        if (remove_cr)
35                removeCR(s);
[109]36}
37
38//load single line, discarding any \r or \n found at the end, return false if nothing could be loaded (error or eof)
[257]39bool loadSStringLine(VirtFILE* f, SString& s)
[109]40{
[257]41        char buf[100];
42        bool eolfound = false;
43        bool ret = false;
44        s = SString::empty();
45        while (!eolfound)
[109]46        {
[523]47                char *r = f->Vgets(buf, sizeof(buf));
[257]48                if (r == NULL) break;
49                ret = true;
50                int d = strlen(r);
51                if (d > 0)
[109]52                {
[257]53                        if (r[d - 1] == '\n') { d--; eolfound = true; }
54                        if (d > 0) if (r[d - 1] == '\r') d--;
55                        s += SString(r, d);
[109]56                }
57        }
[257]58        return ret;
[109]59}
60
61//////////////////////////
62
63/** "x~xx~xxx" -> "x\~xx\~xxx"  */
64int quoteTilde(SString &target)
65{
[348]66        const char* x = target.c_str();
[257]67        SString tmp;
68        char *f;
69        while (1)
[109]70        {
[257]71                f = strchr((char*)x, '~');
72                if (f)
[109]73                {
[257]74                        tmp.append(x, f - x);
75                        tmp += "\\~";
76                        x = f + 1;
[109]77                }
[257]78                else
[109]79                {
[257]80                        if (tmp.len() == 0) return 0; // nothing was changed!
81                        tmp += x;
82                        target = tmp;
83                        return 1;
[109]84                }
85        }
86}
87
88/** "x\~xx\~xxx" -> "x~xx~xxx"  */
89int unquoteTilde(SString &target)
90{
[348]91        const char* x = target.c_str();
[257]92        SString tmp;
93        char *f;
94        while (1)
[109]95        {
[257]96                f = strchr((char*)x, '\\');
97                if (f)
[109]98                {
[257]99                        tmp.append(x, f - x);
100                        if (f[1] == '~')
[109]101                        {
[257]102                                tmp += '~';
103                                x = f + 2;
[109]104                        }
[257]105                        else
[109]106                        {
[257]107                                tmp += "\\";
108                                x = f + 1;
[109]109                        }
110                }
[257]111                else
[109]112                {
[257]113                        if (tmp.len() == 0) return 0; // nothing was changed!
114                        tmp += x;
115                        target = tmp;
116                        return 1;
[109]117                }
118        }
119}
120
121/////////////////
122
[257]123bool strContainsOneOf(const char* str, const char* chars)
[109]124{
[257]125        while (*str)
[109]126        {
[257]127                if (strchr(chars, *str)) return 1;
128                str++;
[109]129        }
[257]130        return 0;
[109]131}
132
133//////////////
134
135bool sstringQuote(SString& target)
136{
[348]137        const char* x = target.c_str();
[257]138        bool changed = 0;
139        SString tmp;
140        tmp.memoryHint(target.len());
141        while (*x)
[109]142        {
[257]143                switch (*x)
[109]144                {
[257]145                case '\n': tmp += "\\n"; changed = 1; break;
146                case '\r': tmp += "\\r"; changed = 1; break;
147                case '\t': tmp += "\\t"; changed = 1; break;
148                case '\"': tmp += "\\\""; changed = 1; break;
149                case '\\': tmp += "\\\\"; changed = 1; break;
150                default: tmp += *x;
[109]151                }
[257]152                x++;
[109]153        }
[257]154        if (changed) target = tmp;
155        return changed;
[109]156}
157
158const char* skipQuoteString(const char* txt, const char* limit)
159{
[257]160        while (*txt)
[109]161        {
[257]162                if (*txt == '\"') return txt;
163                if (*txt == '\\') txt++;
164                txt++;
165                if (txt == limit) break;
[109]166        }
[257]167        return txt;
[109]168}
169
170int sstringUnquote(SString &target)
171{
[348]172        const char* x = target.c_str();
[257]173        SString tmp;
174        char *f;
175        while (1)
[109]176        {
[257]177                f = strchr((char*)x, '\\');
178                if (f)
[109]179                {
[257]180                        tmp.append(x, f - x);
181                        switch (f[1])
[109]182                        {
[257]183                        case 'n': tmp += '\n'; break;
184                        case 'r': tmp += '\r'; break;
185                        case 't': tmp += '\t'; break;
186                        case '\"': tmp += '\"'; break;
187                        default: tmp += f[1];
[109]188                        }
[257]189                        x = f + 2;
[109]190                }
[257]191                else
[109]192                {
[257]193                        if (tmp.len() == 0) return 0; // nothing was changed!
194                        tmp += x;
195                        target = tmp;
196                        return 1;
[109]197                }
198        }
199}
200
[257]201int strFindField(const SString& txt, const SString& name, int &end)
[109]202{
[348]203        const char* t = txt.c_str(), *n;
[257]204        int pos = 0;
205        while (1)
[109]206        {
[257]207                n = strchr(t + pos, ',');
[348]208                if ((!strncmp(t + pos, name.c_str(), name.len())) && (t[pos + name.len()] == '='))
[109]209                {
[257]210                        if (n) end = n - t; else end = txt.len();
211                        return pos;
[109]212                }
[257]213                if (n) pos = n - t + 1; else break;
[109]214        }
[257]215        return -1;
[109]216}
217
[257]218SString strGetField(const SString& txt, const SString& name)
[109]219{
[257]220        int p, e;
221        p = strFindField(txt, name, e);
222        if (p < 0) return SString();
223        p += name.len() + 1;
224        return SString(txt.substr(p, e - p));
[109]225}
226
[257]227void strSetField(SString& txt, const SString& name, const SString& value)
[109]228{
[257]229        int p, e;
230        p = strFindField(txt, name, e);
231        if (p < 0)
[109]232        {
[257]233                if (!value.len()) return;
234                char *t = txt.directAppend(1 + name.len() + value.len());
235                char *b = t;
236                if (txt.len()) *(t++) = ',';
[348]237                strcpy(t, name.c_str()); t += name.len();
[257]238                *(t++) = '=';
[348]239                strcpy(t, value.c_str()); t += value.len();
[257]240                txt.endAppend(t - b);
[109]241        }
[257]242        else
[109]243        {
[257]244                if (!value.len())
[109]245                {
[257]246                        if (p > 0) p--; else if (e < txt.len()) e++;
247                        char *t = txt.directWrite(0);
248                        memmove(t + p, t + e, txt.len() - e);
249                        txt.endWrite(txt.len() + value.len() - (e - p));
[109]250                }
[257]251                else
[109]252                {
[257]253                        p += name.len() + 1;
254                        char *t = txt.directWrite(txt.len() + value.len() - (e - p));
255                        memmove(t + p + value.len(), t + e, txt.len() - e);
[348]256                        memmove(t + p, value.c_str(), value.len());
[257]257                        txt.endWrite(txt.len() + value.len() - (e - p));
[109]258                }
259        }
260}
261
[512]262SString trim(const SString& s)
[109]263{
[348]264        const unsigned char*b = (const unsigned char*)s.c_str();
[257]265        const unsigned char*e = b + s.len();
266        while ((b < e) && (*b <= ' ')) b++;
267        while ((b < e) && (e[-1] <= ' ')) e--;
268        if ((e - b) == s.len()) return s;
269        SString newstring;
270        char* t = newstring.directWrite(e - b);
271        memmove(t, b, e - b);
272        newstring.endWrite(e - b);
273        return newstring;
[109]274}
275
276bool removeCR(SString& s)
277{
[348]278        const char* p = s.c_str();
[257]279        const char* cr = strchr(p, '\r');
280        if (!cr) return false;
281        char* begin = s.directWrite();
282        char* src = begin + (cr - p), *dst = src;
283        while (*src)
284                if (*src == '\r')
285                        src++;
286                else
287                        *(dst++) = *(src++);
288        s.endWrite(dst - begin);
289        return true;
[109]290}
[210]291
[257]292bool matchWildcard(const SString& word, const SString& pattern)
[210]293{
[257]294        if (pattern.len() == 0)
295                return word.len() == 0;
296        int aster = pattern.indexOf('*');
297        if (aster >= 0)
[210]298        {
[257]299                SString before = pattern.substr(0, aster);
300                SString after = pattern.substr(aster + 1);
301                if (!word.len()) return false;
[348]302                if (before.len()) if (!word.startsWith(before.c_str())) return false;
[257]303                if (after.len())
304                        if ((word.len() < after.len())
[348]305                                || (strcmp(after.c_str(), word.c_str() + word.len() - after.len())))
[257]306                                return false;
307                return true;
[210]308        }
[257]309        else
310                return word == pattern;
[210]311}
312
[257]313bool matchWildcardList(const SString& word, const SString& patterns)
[210]314{
[257]315        if (patterns.len() == 0)
316                return word.len() == 0;
317        int pos = 0;
318        SString pattern;
319        while (patterns.getNextToken(pos, pattern, ','))
320                if (matchWildcard(word, pattern))
321                        return true;
322        return false;
[210]323}
324
Note: See TracBrowser for help on using the repository browser.