Transform strings (or substrings) prefixed with introducer (_charset) to ASCII equivalent.
| 129 | |
| 130 | // Transform strings (or substrings) prefixed with introducer (_charset) to ASCII equivalent. |
| 131 | void Parser::transformString(const char* start, unsigned length, string& dest) |
| 132 | { |
| 133 | const static char HEX_DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
| 134 | 'A', 'B', 'C', 'D', 'E', 'F'}; |
| 135 | |
| 136 | const unsigned fromBegin = start - lex.start; |
| 137 | HalfStaticArray<char, 256> buffer; |
| 138 | const char* pos = start; |
| 139 | |
| 140 | // We need only the "introduced" strings, in the bounds of "start" and "length" and in "pos" |
| 141 | // order. Let collect them. |
| 142 | |
| 143 | SortedArray<StrMark> introducedMarks; |
| 144 | |
| 145 | GenericMap<NonPooled<IntlString*, StrMark> >::ConstAccessor accessor(&strMarks); |
| 146 | for (bool found = accessor.getFirst(); found; found = accessor.getNext()) |
| 147 | { |
| 148 | const StrMark& mark = accessor.current()->second; |
| 149 | if (mark.introduced && mark.pos >= fromBegin && mark.pos < fromBegin + length) |
| 150 | introducedMarks.add(mark); |
| 151 | } |
| 152 | |
| 153 | for (FB_SIZE_T i = 0; i < introducedMarks.getCount(); ++i) |
| 154 | { |
| 155 | const StrMark& mark = introducedMarks[i]; |
| 156 | |
| 157 | const char* s = lex.start + mark.pos; |
| 158 | buffer.add(pos, s - pos); |
| 159 | |
| 160 | if (!isspace(UCHAR(pos[s - pos - 1]))) |
| 161 | buffer.add(' '); // fix _charset'' becoming invalid syntax _charsetX'' |
| 162 | |
| 163 | const FB_SIZE_T count = buffer.getCount(); |
| 164 | const FB_SIZE_T newSize = count + 2 + mark.str->getString().length() * 2 + 1; |
| 165 | buffer.grow(newSize); |
| 166 | char* p = buffer.begin() + count; |
| 167 | |
| 168 | *p++ = 'X'; |
| 169 | *p++ = '\''; |
| 170 | |
| 171 | const char* s2 = mark.str->getString().c_str(); |
| 172 | |
| 173 | for (const char* end = s2 + mark.str->getString().length(); s2 < end; ++s2) |
| 174 | { |
| 175 | *p++ = HEX_DIGITS[UCHAR(*s2) >> 4]; |
| 176 | *p++ = HEX_DIGITS[UCHAR(*s2) & 0xF]; |
| 177 | } |
| 178 | |
| 179 | *p = '\''; |
| 180 | fb_assert(p < buffer.begin() + newSize); |
| 181 | |
| 182 | pos = s + mark.length; |
| 183 | } |
| 184 | |
| 185 | fb_assert(start + length - pos >= 0); |
| 186 | buffer.add(pos, start + length - pos); |
| 187 | |
| 188 | dest.assign(buffer.begin(), MIN(string::max_length(), buffer.getCount())); |