bool ResTable::collectString()

in libresource/ResourceTypes.cpp [5347:5487]


bool ResTable::collectString(String16* outString,
                             const char16_t* s, size_t len,
                             bool preserveSpaces,
                             const char** outErrorMsg,
                             bool append)
{
    String16 tmp;

    char quoted = 0;
    const char16_t* p = s;
    while (p < (s+len)) {
        while (p < (s+len)) {
            const char16_t c = *p;
            if (c == '\\') {
                break;
            }
            if (!preserveSpaces) {
                if (quoted == 0 && isspace16(c)
                    && (c != ' ' || isspace16(*(p+1)))) {
                    break;
                }
                if (c == '"' && (quoted == 0 || quoted == '"')) {
                    break;
                }
                if (c == '\'' && (quoted == 0 || quoted == '\'')) {
                    /*
                     * In practice, when people write ' instead of \'
                     * in a string, they are doing it by accident
                     * instead of really meaning to use ' as a quoting
                     * character.  Warn them so they don't lose it.
                     */
                    if (outErrorMsg) {
                        *outErrorMsg = "Apostrophe not preceded by \\";
                    }
                    return false;
                }
            }
            p++;
        }
        if (p < (s+len)) {
            if (p > s) {
                tmp.append(String16(s, p-s));
            }
            if (!preserveSpaces && (*p == '"' || *p == '\'')) {
                if (quoted == 0) {
                    quoted = *p;
                } else {
                    quoted = 0;
                }
                p++;
            } else if (!preserveSpaces && isspace16(*p)) {
                // Space outside of a quote -- consume all spaces and
                // leave a single plain space char.
                tmp.append(String16(" "));
                p++;
                while (p < (s+len) && isspace16(*p)) {
                    p++;
                }
            } else if (*p == '\\') {
                p++;
                if (p < (s+len)) {
                    switch (*p) {
                    case 't':
                        tmp.append(String16("\t"));
                        break;
                    case 'n':
                        tmp.append(String16("\n"));
                        break;
                    case '#':
                        tmp.append(String16("#"));
                        break;
                    case '@':
                        tmp.append(String16("@"));
                        break;
                    case '?':
                        tmp.append(String16("?"));
                        break;
                    case '"':
                        tmp.append(String16("\""));
                        break;
                    case '\'':
                        tmp.append(String16("'"));
                        break;
                    case '\\':
                        tmp.append(String16("\\"));
                        break;
                    case 'u':
                    {
                        char16_t chr = 0;
                        int i = 0;
                        while (i < 4 && p[1] != 0) {
                            p++;
                            i++;
                            int c;
                            if (*p >= '0' && *p <= '9') {
                                c = *p - '0';
                            } else if (*p >= 'a' && *p <= 'f') {
                                c = *p - 'a' + 10;
                            } else if (*p >= 'A' && *p <= 'F') {
                                c = *p - 'A' + 10;
                            } else {
                                if (outErrorMsg) {
                                    *outErrorMsg = "Bad character in \\u unicode escape sequence";
                                }
                                return false;
                            }
                            chr = (chr<<4) | c;
                        }
                        tmp.append(String16(&chr, 1));
                    } break;
                    default:
                        // ignore unknown escape chars.
                        break;
                    }
                    p++;
                }
            }
            len -= (p-s);
            s = p;
        }
    }

    if (tmp.size() != 0) {
        if (len > 0) {
            tmp.append(String16(s, len));
        }
        if (append) {
            outString->append(tmp);
        } else {
            outString->setTo(tmp);
        }
    } else {
        if (append) {
            outString->append(String16(s, len));
        } else {
            outString->setTo(s, len);
        }
    }

    return true;
}