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

Last change on this file since 875 was 786, checked in by Maciej Komosinski, 7 years ago

Improved shortening of long stringified values in error messages

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