TEST(XmlPullParserTest, NextChildNodeTraversesCorrectly) {
    std::stringstream str;
    str << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
            "<a><b><c xmlns:a=\"http://schema.org\"><d/></c><e/></b></a>";
    xml::XmlPullParser parser(str);

    const size_t depthOuter = parser.getDepth();
    ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthOuter));

    EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
    EXPECT_EQ(StringPiece16(u"a"), StringPiece16(parser.getElementName()));

    const size_t depthA = parser.getDepth();
    ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthA));
    EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
    EXPECT_EQ(StringPiece16(u"b"), StringPiece16(parser.getElementName()));

    const size_t depthB = parser.getDepth();
    ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthB));
    EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
    EXPECT_EQ(StringPiece16(u"c"), StringPiece16(parser.getElementName()));

    ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthB));
    EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
    EXPECT_EQ(StringPiece16(u"e"), StringPiece16(parser.getElementName()));

    ASSERT_FALSE(xml::XmlPullParser::nextChildNode(&parser, depthOuter));
    EXPECT_EQ(xml::XmlPullParser::Event::kEndDocument, parser.getEvent());
}
TEST(StringPieceTest, PiecesHaveCorrectSortOrder) {
    std::u16string testing(u"testing");
    std::u16string banana(u"banana");
    std::u16string car(u"car");

    EXPECT_TRUE(StringPiece16(testing) > banana);
    EXPECT_TRUE(StringPiece16(testing) > car);
    EXPECT_TRUE(StringPiece16(banana) < testing);
    EXPECT_TRUE(StringPiece16(banana) < car);
    EXPECT_TRUE(StringPiece16(car) < testing);
    EXPECT_TRUE(StringPiece16(car) > banana);
}
Ejemplo n.º 3
0
StringPiece16 trimWhitespace(const StringPiece16& str) {
    if (str.size() == 0 || str.data() == nullptr) {
        return str;
    }

    const char16_t* start = str.data();
    const char16_t* end = str.data() + str.length();

    while (start != end && util::isspace16(*start)) {
        start++;
    }

    while (end != start && util::isspace16(*(end - 1))) {
        end--;
    }

    return StringPiece16(start, end - start);
}
bool ResourceTable::markPublicImpl(const ResourceNameRef& name, const ResourceId& resId,
                                   const SourceLine& source, const char16_t* validChars) {
    if (!name.package.empty() && name.package != mPackage) {
        Logger::error(source)
                << "resource '"
                << name
                << "' has incompatible package. Must be '"
                << mPackage
                << "'."
            << std::endl;
        return false;
    }

    auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars);
    if (badCharIter != name.entry.end()) {
        Logger::error(source)
                << "resource '"
                << name
                << "' has invalid entry name '"
                << name.entry
                << "'. Invalid character '"
                << StringPiece16(badCharIter, 1)
                << "'."
                << std::endl;
        return false;
    }

    std::unique_ptr<ResourceTableType>& type = findOrCreateType(name.type);
    if (resId.isValid() && type->typeId != ResourceTableType::kUnsetTypeId &&
            type->typeId != resId.typeId()) {
        Logger::error(source)
                << "trying to make resource '"
                << name
                << "' public with ID "
                << resId
                << " but type '"
                << type->type
                << "' already has ID "
                << std::hex << type->typeId << std::dec
                << "."
                << std::endl;
        return false;
    }

    std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, name.entry);
    if (resId.isValid() && entry->entryId != ResourceEntry::kUnsetEntryId &&
            entry->entryId != resId.entryId()) {
        Logger::error(source)
                << "trying to make resource '"
                << name
                << "' public with ID "
                << resId
                << " but resource already has ID "
                << ResourceId(mPackageId, type->typeId, entry->entryId)
                << "."
                << std::endl;
        return false;
    }

    type->publicStatus.isPublic = true;
    entry->publicStatus.isPublic = true;
    entry->publicStatus.source = source;

    if (resId.isValid()) {
        type->typeId = resId.typeId();
        entry->entryId = resId.entryId();
    }
    return true;
}
bool ResourceTable::addResourceImpl(const ResourceNameRef& name, const ResourceId& resId,
                                    const ConfigDescription& config, const SourceLine& source,
                                    std::unique_ptr<Value> value, const char16_t* validChars) {
    if (!name.package.empty() && name.package != mPackage) {
        Logger::error(source)
                << "resource '"
                << name
                << "' has incompatible package. Must be '"
                << mPackage
                << "'."
                << std::endl;
        return false;
    }

    auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars);
    if (badCharIter != name.entry.end()) {
        Logger::error(source)
                << "resource '"
                << name
                << "' has invalid entry name '"
                << name.entry
                << "'. Invalid character '"
                << StringPiece16(badCharIter, 1)
                << "'."
                << std::endl;
        return false;
    }

    std::unique_ptr<ResourceTableType>& type = findOrCreateType(name.type);
    if (resId.isValid() && type->typeId != ResourceTableType::kUnsetTypeId &&
            type->typeId != resId.typeId()) {
        Logger::error(source)
                << "trying to add resource '"
                << name
                << "' with ID "
                << resId
                << " but type '"
                << type->type
                << "' already has ID "
                << std::hex << type->typeId << std::dec
                << "."
                << std::endl;
        return false;
    }

    std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, name.entry);
    if (resId.isValid() && entry->entryId != ResourceEntry::kUnsetEntryId &&
            entry->entryId != resId.entryId()) {
        Logger::error(source)
                << "trying to add resource '"
                << name
                << "' with ID "
                << resId
                << " but resource already has ID "
                << ResourceId(mPackageId, type->typeId, entry->entryId)
                << "."
                << std::endl;
        return false;
    }

    const auto endIter = std::end(entry->values);
    auto iter = std::lower_bound(std::begin(entry->values), endIter, config, compareConfigs);
    if (iter == endIter || iter->config != config) {
        // This resource did not exist before, add it.
        entry->values.insert(iter, ResourceConfigValue{ config, source, {}, std::move(value) });
    } else {
        int collisionResult = defaultCollisionHandler(*iter->value, *value);
        if (collisionResult > 0) {
            // Take the incoming value.
            *iter = ResourceConfigValue{ config, source, {}, std::move(value) };
        } else if (collisionResult == 0) {
            Logger::error(source)
                    << "duplicate value for resource '" << name << "' "
                    << "with config '" << iter->config << "'."
                    << std::endl;

            Logger::error(iter->source)
                    << "resource previously defined here."
                    << std::endl;
            return false;
        }
    }

    if (resId.isValid()) {
        type->typeId = resId.typeId();
        entry->entryId = resId.entryId();
    }
    return true;
}