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

Last change on this file since 520 was 512, checked in by Maciej Komosinski, 9 years ago

No trailing space in full name when last name is empty

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