~linaro-graphics-wg/libmatrix/misc-changes-glmark2

« back to all changes in this revision

Viewing changes to util.cc

  • Committer: Jesse Barker
  • Date: 2012-08-09 21:11:02 UTC
  • mfrom: (38.1.4 split-refactor)
  • Revision ID: jesse.barker@linaro.org-20120809211102-o675afh0jnttz9ne
Merge of lp:~linaro-graphics-wg/libmatrix/split-refactor

Adds bash-style escaping for Util::split and cleans up the API to handle all of
the modes we now support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
using std::string;
26
26
using std::vector;
27
27
 
28
 
void
29
 
Util::split(const string& src, char delim, vector<string>& elementVec, bool fuzzy)
30
 
{
31
 
    // Trivial rejection
32
 
    if (src.empty())
33
 
    {
34
 
        return;
35
 
    }
36
 
 
37
 
    // Simple case: we want to enforce the value of 'delim' strictly 
38
 
    if (!fuzzy)
39
 
    {
40
 
        std::stringstream ss(src);
41
 
        string item;
42
 
        while(std::getline(ss, item, delim))
43
 
            elementVec.push_back(item);
44
 
        return;
45
 
    }
46
 
 
 
28
/*
 
29
 * State machine for bash-like quoted string escaping:
 
30
 *
 
31
 *         \
 
32
 *    -----------> +---------+
 
33
 *    | ---------- | Escaped |
 
34
 *    | |  *,ESC   +---------+
 
35
 *    | |
 
36
 *    | v      '
 
37
 * +--------+ ---> +--------------+ -----
 
38
 * | Normal | <--- | SingleQuoted |     | *, ESC
 
39
 * +--------+  '   +--------------+ <----
 
40
 *    | ^
 
41
 *    | |
 
42
 *    | |  "       +--------------+ ----
 
43
 *    | ---------- | DoubleQuoted |    | *, ESC
 
44
 *    -----------> +--------------+ <---
 
45
 *         "             | ^
 
46
 *                     \ | | *, ESC
 
47
 *                       v |
 
48
 *             +---------------------+
 
49
 *             | DoubleQuotedEscaped |
 
50
 *             +---------------------+
 
51
 *
 
52
 * ESC: Mark character as Escaped
 
53
 */
 
54
static void
 
55
fill_escape_vector(const string &str, vector<bool> &esc_vec)
 
56
{
 
57
    enum State {
 
58
        StateNormal,
 
59
        StateEscaped,
 
60
        StateDoubleQuoted,
 
61
        StateDoubleQuotedEscaped,
 
62
        StateSingleQuoted
 
63
    };
 
64
 
 
65
    State state = StateNormal;
 
66
 
 
67
    for (string::const_iterator iter = str.begin();
 
68
         iter != str.end();
 
69
         iter++)
 
70
    {
 
71
        const char c(*iter);
 
72
        bool esc = false;
 
73
 
 
74
        switch (state) {
 
75
            case StateNormal:
 
76
                if (c == '"')
 
77
                    state = StateDoubleQuoted;
 
78
                else if (c == '\\')
 
79
                    state = StateEscaped;
 
80
                else if (c == '\'')
 
81
                    state = StateSingleQuoted;
 
82
                break;
 
83
            case StateEscaped:
 
84
                esc = true;
 
85
                state = StateNormal;
 
86
                break;
 
87
            case StateDoubleQuoted:
 
88
                if (c == '"')
 
89
                    state = StateNormal;
 
90
                else if (c == '\\')
 
91
                    state = StateDoubleQuotedEscaped;
 
92
                else
 
93
                    esc = true;
 
94
                break;
 
95
            case StateDoubleQuotedEscaped:
 
96
                esc = true;
 
97
                state = StateDoubleQuoted;
 
98
                break;
 
99
            case StateSingleQuoted:
 
100
                if (c == '\'')
 
101
                    state = StateNormal;
 
102
                else
 
103
                    esc = true;
 
104
            default:
 
105
                break;
 
106
        }
 
107
 
 
108
        esc_vec.push_back(esc);
 
109
    }
 
110
}
 
111
 
 
112
static void
 
113
split_normal(const string& src, char delim, vector<string>& elementVec)
 
114
{
 
115
    std::stringstream ss(src);
 
116
    string item;
 
117
    while(std::getline(ss, item, delim))
 
118
        elementVec.push_back(item);
 
119
}
 
120
 
 
121
static void
 
122
split_fuzzy(const string& src, char delim, vector<string>& elementVec)
 
123
{
47
124
    // Fuzzy case: Initialize our delimiter string based upon the caller's plus
48
125
    // a space to allow for more flexibility.
49
126
    string delimiter(" ");
76
153
    elementVec.push_back(str);
77
154
}
78
155
 
 
156
static void
 
157
split_quoted(const string& src, char delim, vector<string>& elementVec)
 
158
{
 
159
    std::stringstream ss;
 
160
    vector<bool> escVec;
 
161
 
 
162
    /* Mark characters in the string as escaped or not */
 
163
    fill_escape_vector(src, escVec);
 
164
 
 
165
    /* Sanity check... */
 
166
    if (src.length() != escVec.size())
 
167
        return;
 
168
 
 
169
    for (vector<bool>::const_iterator iter = escVec.begin();
 
170
         iter != escVec.end();
 
171
         iter++)
 
172
    {
 
173
        bool escaped = static_cast<bool>(*iter);
 
174
        char c = src[iter - escVec.begin()];
 
175
 
 
176
        /* Output all characters, except unescaped ",\,' */
 
177
        if ((c != '"' && c != '\\' && c != '\'') || escaped) {
 
178
            /* If we reach an unescaped delimiter character, do a split */
 
179
            if (c == delim && !escaped) {
 
180
                elementVec.push_back(ss.str());
 
181
                ss.str("");
 
182
                ss.clear();
 
183
            }
 
184
            else {
 
185
                ss << c;
 
186
            }
 
187
        }
 
188
 
 
189
    }
 
190
 
 
191
    /* Handle final element, delimited by end of string */
 
192
    const string &finalElement(ss.str());
 
193
    if (!finalElement.empty())
 
194
        elementVec.push_back(finalElement);
 
195
}
 
196
 
 
197
void
 
198
Util::split(const string& src, char delim, vector<string>& elementVec,
 
199
            Util::SplitMode mode)
 
200
{
 
201
    // Trivial rejection
 
202
    if (src.empty())
 
203
    {
 
204
        return;
 
205
    }
 
206
 
 
207
    switch (mode)
 
208
    {
 
209
        case Util::SplitModeNormal:
 
210
            return split_normal(src, delim, elementVec);
 
211
        case Util::SplitModeFuzzy:
 
212
            return split_fuzzy(src, delim, elementVec);
 
213
        case Util::SplitModeQuoted:
 
214
            return split_quoted(src, delim, elementVec);
 
215
        default:
 
216
            break;
 
217
    }
 
218
}
 
219
 
79
220
uint64_t
80
221
Util::get_timestamp_us()
81
222
{