diff options
author | sobols <sobols@yandex-team.ru> | 2022-02-10 16:47:08 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:08 +0300 |
commit | 09961b69c61f471ddd594e0fd877df62a8021562 (patch) | |
tree | 54a7b60a9526a7104557a033eb0a8d70d64b604c /library | |
parent | 4ce8835206f981afa4a61915a49a21fb750416ec (diff) | |
download | ydb-09961b69c61f471ddd594e0fd877df62a8021562.tar.gz |
Restoring authorship annotation for <sobols@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'library')
28 files changed, 1280 insertions, 1280 deletions
diff --git a/library/cpp/blockcodecs/core/common.h b/library/cpp/blockcodecs/core/common.h index f05df4d334..5944a08890 100644 --- a/library/cpp/blockcodecs/core/common.h +++ b/library/cpp/blockcodecs/core/common.h @@ -91,11 +91,11 @@ namespace NBlockCodecs { const auto len = ReadUnaligned<ui64>(in.data()); - if (!len) + if (!len) return 0; - Base()->DoDecompress(TData(in).Skip(sizeof(len)), out, len); - return len; + Base()->DoDecompress(TData(in).Skip(sizeof(len)), out, len); + return len; } inline const T* Base() const noexcept { diff --git a/library/cpp/charset/codepage_ut.cpp b/library/cpp/charset/codepage_ut.cpp index c3ac3ac478..350f886335 100644 --- a/library/cpp/charset/codepage_ut.cpp +++ b/library/cpp/charset/codepage_ut.cpp @@ -365,58 +365,58 @@ static void TestCanEncodeEach(const TWtringBuf& text, ECharset encoding, bool ex void TCodepageTest::TestCanEncode() { TestCanEncodeEmpty(); - const TUtf16String lat = u"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; + const TUtf16String lat = u"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; TestCanEncodeEach(lat, CODES_WIN, true); TestCanEncodeEach(lat, CODES_YANDEX, true); TestCanEncodeEach(lat, CODES_UTF8, true); - const TUtf16String rus = u"АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя"; + const TUtf16String rus = u"АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя"; TestCanEncodeEach(rus, CODES_WIN, true); TestCanEncodeEach(rus, CODES_YANDEX, true); TestCanEncodeEach(rus, CODES_UTF8, true); - const TUtf16String ukr = u"ҐґЄєІіЇї"; + const TUtf16String ukr = u"ҐґЄєІіЇї"; TestCanEncodeEach(ukr, CODES_WIN, true); TestCanEncodeEach(ukr, CODES_YANDEX, true); TestCanEncodeEach(ukr, CODES_UTF8, true); - const TUtf16String pol = u"ĄĆĘŁŃÓŚŹŻąćęłńóśźż"; + const TUtf16String pol = u"ĄĆĘŁŃÓŚŹŻąćęłńóśźż"; TestCanEncodeEach(pol, CODES_WIN, false); TestCanEncodeEach(pol, CODES_YANDEX, true); TestCanEncodeEach(pol, CODES_UTF_16BE, true); - const TUtf16String ger = u"ÄäÖöÜüß"; + const TUtf16String ger = u"ÄäÖöÜüß"; TestCanEncodeEach(ger, CODES_WIN, false); TestCanEncodeEach(ger, CODES_YANDEX, true); TestCanEncodeEach(ger, CODES_UTF_16LE, true); - const TUtf16String fra1 = u"éàèùâêîôûëïç"; // supported in yandex cp - const TUtf16String fra2 = u"ÉÀÈÙÂÊÎÔÛËÏŸÿÇ"; - const TUtf16String fra3 = u"Æ挜"; + const TUtf16String fra1 = u"éàèùâêîôûëïç"; // supported in yandex cp + const TUtf16String fra2 = u"ÉÀÈÙÂÊÎÔÛËÏŸÿÇ"; + const TUtf16String fra3 = u"Æ挜"; TestCanEncodeEach(fra1 + fra2 + fra3, CODES_WIN, false); TestCanEncodeEach(fra1, CODES_YANDEX, true); TestCanEncodeEach(fra2 + fra3, CODES_YANDEX, false); TestCanEncodeEach(fra1 + fra2 + fra3, CODES_UTF8, true); - const TUtf16String kaz = u"ӘәҒғҚқҢңӨөҰұҮүҺһ"; + const TUtf16String kaz = u"ӘәҒғҚқҢңӨөҰұҮүҺһ"; TestCanEncodeEach(kaz, CODES_WIN, false); TestCanEncodeEach(kaz, CODES_YANDEX, false); TestCanEncodeEach(kaz, CODES_UTF8, true); TestCanEncodeEach(kaz, CODES_KAZWIN, true); - const TUtf16String tur1 = u"ĞİŞğş"; - const TUtf16String tur = tur1 + u"ı"; + const TUtf16String tur1 = u"ĞİŞğş"; + const TUtf16String tur = tur1 + u"ı"; TestCanEncodeEach(tur, CODES_WIN, false); TestCanEncodeEach(tur, CODES_YANDEX, false); TestCanEncodeEach(tur, CODES_UTF8, true); - const TUtf16String chi = u"新隶体新隸體"; + const TUtf16String chi = u"新隶体新隸體"; TestCanEncodeEach(chi, CODES_WIN, false); TestCanEncodeEach(chi, CODES_YANDEX, false); TestCanEncodeEach(chi, CODES_UTF8, true); TestCanEncodeEach(chi, CODES_UTF_16LE, true); - const TUtf16String jap = u"漢字仮字交じり文"; + const TUtf16String jap = u"漢字仮字交じり文"; TestCanEncodeEach(jap, CODES_WIN, false); TestCanEncodeEach(jap, CODES_YANDEX, false); TestCanEncodeEach(jap, CODES_UTF8, true); diff --git a/library/cpp/containers/comptrie/comptrie_ut.cpp b/library/cpp/containers/comptrie/comptrie_ut.cpp index 74bee09b5d..efd9154b76 100644 --- a/library/cpp/containers/comptrie/comptrie_ut.cpp +++ b/library/cpp/containers/comptrie/comptrie_ut.cpp @@ -1249,7 +1249,7 @@ void TCompactTrieTest::TestTrieForPairWtrokaVectorInt64() { TVector<TVector<i64>> values = GetSampleVectorData<TVector<i64>>(10); TVector<std::pair<TUtf16String, TVector<i64>>> data; for (size_t i = 0; i < 10; i++) - data.push_back(std::pair<TUtf16String, TVector<i64>>(keys[i] + u"_v", values[i])); + data.push_back(std::pair<TUtf16String, TVector<i64>>(keys[i] + u"_v", values[i])); TestTrieWithContainers<std::pair<TUtf16String, TVector<i64>>>(keys, data, "pair-str-v-i64"); } @@ -1273,9 +1273,9 @@ void TCompactTrieTest::TestFindLongestPrefixWithEmptyValue() { TBufferOutput buffer; { TCompactTrieBuilder<wchar16, ui32> builder; - builder.Add(u"", 42); - builder.Add(u"yandex", 271828); - builder.Add(u"ya", 31415); + builder.Add(u"", 42); + builder.Add(u"yandex", 271828); + builder.Add(u"ya", 31415); builder.Save(buffer); } { @@ -1283,11 +1283,11 @@ void TCompactTrieTest::TestFindLongestPrefixWithEmptyValue() { size_t prefixLen = 123; ui32 value = 0; - UNIT_ASSERT(trie.FindLongestPrefix(u"google", &prefixLen, &value)); + UNIT_ASSERT(trie.FindLongestPrefix(u"google", &prefixLen, &value)); UNIT_ASSERT(prefixLen == 0); UNIT_ASSERT(value == 42); - UNIT_ASSERT(trie.FindLongestPrefix(u"yahoo", &prefixLen, &value)); + UNIT_ASSERT(trie.FindLongestPrefix(u"yahoo", &prefixLen, &value)); UNIT_ASSERT(prefixLen == 2); UNIT_ASSERT(value == 31415); } @@ -1562,18 +1562,18 @@ void TCompactTrieTest::TestBuilderFindLongestPrefix(size_t keysCount, double bra void TCompactTrieTest::TestBuilderFindLongestPrefixWithEmptyValue() { TCompactTrieBuilder<wchar16, ui32> builder; - builder.Add(u"", 42); - builder.Add(u"yandex", 271828); - builder.Add(u"ya", 31415); + builder.Add(u"", 42); + builder.Add(u"yandex", 271828); + builder.Add(u"ya", 31415); size_t prefixLen = 123; ui32 value = 0; - UNIT_ASSERT(builder.FindLongestPrefix(u"google", &prefixLen, &value)); + UNIT_ASSERT(builder.FindLongestPrefix(u"google", &prefixLen, &value)); UNIT_ASSERT_VALUES_EQUAL(prefixLen, 0); UNIT_ASSERT_VALUES_EQUAL(value, 42); - UNIT_ASSERT(builder.FindLongestPrefix(u"yahoo", &prefixLen, &value)); + UNIT_ASSERT(builder.FindLongestPrefix(u"yahoo", &prefixLen, &value)); UNIT_ASSERT_VALUES_EQUAL(prefixLen, 2); UNIT_ASSERT_VALUES_EQUAL(value, 31415); diff --git a/library/cpp/digest/crc32c/crc32c_ut.cpp b/library/cpp/digest/crc32c/crc32c_ut.cpp index aa31b83422..02d4c12fec 100644 --- a/library/cpp/digest/crc32c/crc32c_ut.cpp +++ b/library/cpp/digest/crc32c/crc32c_ut.cpp @@ -8,15 +8,15 @@ Y_UNIT_TEST_SUITE(TestCrc32c) { } Y_UNIT_TEST(TestUnaligned) { - const TString str(1000, 'a'); - for (size_t substrLen = 0; substrLen <= str.length(); ++substrLen) { - const ui32 crc = Crc32c(str.data(), substrLen); - for (size_t offset = 1; offset + substrLen <= str.length(); ++offset) { - UNIT_ASSERT_VALUES_EQUAL(Crc32c(str.data() + offset, substrLen), crc); - } - } - } - + const TString str(1000, 'a'); + for (size_t substrLen = 0; substrLen <= str.length(); ++substrLen) { + const ui32 crc = Crc32c(str.data(), substrLen); + for (size_t offset = 1; offset + substrLen <= str.length(); ++offset) { + UNIT_ASSERT_VALUES_EQUAL(Crc32c(str.data() + offset, substrLen), crc); + } + } + } + Y_UNIT_TEST(TestExtend) { UNIT_ASSERT_VALUES_EQUAL(Crc32cExtend(1, "abc", 3), ui32(2466950601)); } diff --git a/library/cpp/protobuf/json/json2proto.cpp b/library/cpp/protobuf/json/json2proto.cpp index 640c10f5a5..ba6f2859f3 100644 --- a/library/cpp/protobuf/json/json2proto.cpp +++ b/library/cpp/protobuf/json/json2proto.cpp @@ -110,18 +110,18 @@ JsonString2Field(const NJson::TJsonValue& json, reflection->SetString(&proto, &field, value); } -static const NProtoBuf::EnumValueDescriptor* -FindEnumValue(const NProtoBuf::EnumDescriptor* enumField, - TStringBuf target, bool (*equals)(TStringBuf, TStringBuf)) { - for (int i = 0; i < enumField->value_count(); i++) { - auto* valueDescriptor = enumField->value(i); - if (equals(valueDescriptor->name(), target)) { - return valueDescriptor; - } - } - return nullptr; -} - +static const NProtoBuf::EnumValueDescriptor* +FindEnumValue(const NProtoBuf::EnumDescriptor* enumField, + TStringBuf target, bool (*equals)(TStringBuf, TStringBuf)) { + for (int i = 0; i < enumField->value_count(); i++) { + auto* valueDescriptor = enumField->value(i); + if (equals(valueDescriptor->name(), target)) { + return valueDescriptor; + } + } + return nullptr; +} + static void JsonEnum2Field(const NJson::TJsonValue& json, google::protobuf::Message& proto, @@ -148,7 +148,7 @@ JsonEnum2Field(const NJson::TJsonValue& json, const auto& value = json.GetString(); if (config.EnumValueMode == NProtobufJson::TJson2ProtoConfig::EnumCaseInsensetive) { enumFieldValue = FindEnumValue(enumField, value, AsciiEqualsIgnoreCase); - } else if (config.EnumValueMode == NProtobufJson::TJson2ProtoConfig::EnumSnakeCaseInsensitive) { + } else if (config.EnumValueMode == NProtobufJson::TJson2ProtoConfig::EnumSnakeCaseInsensitive) { enumFieldValue = FindEnumValue(enumField, value, NProtobufJson::EqualsIgnoringCaseAndUnderscores); } else { enumFieldValue = enumField->FindValueByName(value); diff --git a/library/cpp/protobuf/json/json2proto.h b/library/cpp/protobuf/json/json2proto.h index 4c33498dfa..5e7cff44b4 100644 --- a/library/cpp/protobuf/json/json2proto.h +++ b/library/cpp/protobuf/json/json2proto.h @@ -32,8 +32,8 @@ namespace NProtobufJson { enum EnumValueMode { EnumCaseSensetive = 0, // default - EnumCaseInsensetive, - EnumSnakeCaseInsensitive + EnumCaseInsensetive, + EnumSnakeCaseInsensitive }; TSelf& SetFieldNameMode(FldNameMode mode) { diff --git a/library/cpp/protobuf/json/ut/json2proto_ut.cpp b/library/cpp/protobuf/json/ut/json2proto_ut.cpp index 0dfe57bc7a..377b1d7836 100644 --- a/library/cpp/protobuf/json/ut/json2proto_ut.cpp +++ b/library/cpp/protobuf/json/ut/json2proto_ut.cpp @@ -928,21 +928,21 @@ Y_UNIT_TEST(TestComplexMapAsObject_EnumStringCaseInsensetive) { ); } // TestComplexMapAsObject_EnumStringCaseInsensetive -Y_UNIT_TEST(TestComplexMapAsObject_EnumStringSnakeCaseInsensitive) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableEnum(); - items["key1"] = EEnum::E_1; - items["key2"] = EEnum::E_2; - items["key3"] = EEnum::E_3; - }, - R"_({"Enum":{"key1":"e1","key2":"_E_2_","key3":"e_3"}})_", - TJson2ProtoConfig() - .SetMapAsObject(true) - .SetEnumValueMode(NProtobufJson::TJson2ProtoConfig::EnumSnakeCaseInsensitive) - ); -} // TestComplexMapAsObject_EnumStringCaseInsensetive - +Y_UNIT_TEST(TestComplexMapAsObject_EnumStringSnakeCaseInsensitive) { + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableEnum(); + items["key1"] = EEnum::E_1; + items["key2"] = EEnum::E_2; + items["key3"] = EEnum::E_3; + }, + R"_({"Enum":{"key1":"e1","key2":"_E_2_","key3":"e_3"}})_", + TJson2ProtoConfig() + .SetMapAsObject(true) + .SetEnumValueMode(NProtobufJson::TJson2ProtoConfig::EnumSnakeCaseInsensitive) + ); +} // TestComplexMapAsObject_EnumStringCaseInsensetive + Y_UNIT_TEST(TestComplexMapAsObject_Float) { TestComplexMapAsObject( [](TComplexMapType& proto) { diff --git a/library/cpp/protobuf/json/ut/util_ut.cpp b/library/cpp/protobuf/json/ut/util_ut.cpp index 05101dca28..0d22ce86d4 100644 --- a/library/cpp/protobuf/json/ut/util_ut.cpp +++ b/library/cpp/protobuf/json/ut/util_ut.cpp @@ -1,42 +1,42 @@ -#include <library/cpp/protobuf/json/util.h> - -#include <library/cpp/testing/unittest/registar.h> - -using namespace NProtobufJson; - -Y_UNIT_TEST_SUITE(TEqualsTest) { - Y_UNIT_TEST(TestEmpty) { - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("", "")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("", "_")); - UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("f", "")); - } - - Y_UNIT_TEST(TestTrivial) { - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("f", "f")); - UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("f", "o")); - UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("fo", "f")); - UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("f", "fo")); - UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("bar", "baz")); - } - - Y_UNIT_TEST(TestUnderscores) { - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo_bar", "foobar")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo_bar_", "foobar")); - UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("foo_bar_z", "foobar")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo__bar__", "foobar")); - UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("foo__bar__z", "foobar")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("_foo_bar", "foobar")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("_foo_bar_", "foobar")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("_foo_bar_", "foo___bar")); - } - - Y_UNIT_TEST(TestCase) { - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo_bar", "FOO_BAR")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foobar", "fooBar")); - } - - Y_UNIT_TEST(TestCaseAndUnderscores) { - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("fooBar", "FOO_BAR")); - UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("FOO_BAR_BAZ", "fooBar_BAZ")); - } -} +#include <library/cpp/protobuf/json/util.h> + +#include <library/cpp/testing/unittest/registar.h> + +using namespace NProtobufJson; + +Y_UNIT_TEST_SUITE(TEqualsTest) { + Y_UNIT_TEST(TestEmpty) { + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("", "")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("", "_")); + UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("f", "")); + } + + Y_UNIT_TEST(TestTrivial) { + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("f", "f")); + UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("f", "o")); + UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("fo", "f")); + UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("f", "fo")); + UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("bar", "baz")); + } + + Y_UNIT_TEST(TestUnderscores) { + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo_bar", "foobar")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo_bar_", "foobar")); + UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("foo_bar_z", "foobar")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo__bar__", "foobar")); + UNIT_ASSERT(!EqualsIgnoringCaseAndUnderscores("foo__bar__z", "foobar")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("_foo_bar", "foobar")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("_foo_bar_", "foobar")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("_foo_bar_", "foo___bar")); + } + + Y_UNIT_TEST(TestCase) { + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foo_bar", "FOO_BAR")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("foobar", "fooBar")); + } + + Y_UNIT_TEST(TestCaseAndUnderscores) { + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("fooBar", "FOO_BAR")); + UNIT_ASSERT(EqualsIgnoringCaseAndUnderscores("FOO_BAR_BAZ", "fooBar_BAZ")); + } +} diff --git a/library/cpp/protobuf/json/ut/ya.make b/library/cpp/protobuf/json/ut/ya.make index b60a6d3c17..966d481639 100644 --- a/library/cpp/protobuf/json/ut/ya.make +++ b/library/cpp/protobuf/json/ut/ya.make @@ -11,7 +11,7 @@ SRCS( string_transform_ut.cpp filter_ut.proto test.proto - util_ut.cpp + util_ut.cpp ) GENERATE_ENUM_SERIALIZATION(test.pb.h) diff --git a/library/cpp/protobuf/json/util.cpp b/library/cpp/protobuf/json/util.cpp index 53a065eee2..c0c90c0e5c 100644 --- a/library/cpp/protobuf/json/util.cpp +++ b/library/cpp/protobuf/json/util.cpp @@ -39,7 +39,7 @@ namespace { } } } - + namespace NProtobufJson { void ToSnakeCase(TString* const name) { ToSnakeCaseImpl(name, [](const char prev) { return prev != '_'; }); @@ -49,28 +49,28 @@ namespace NProtobufJson { ToSnakeCaseImpl(name, [](const char prev) { return prev != '_' && !IsAsciiUpper(prev); }); } - bool EqualsIgnoringCaseAndUnderscores(TStringBuf s1, TStringBuf s2) { - size_t i1 = 0, i2 = 0; - - while (i1 < s1.size() && i2 < s2.size()) { - if (s1[i1] == '_') { - ++i1; - } else if (s2[i2] == '_') { - ++i2; - } else if (AsciiToUpper(s1[i1]) != AsciiToUpper(s2[i2])) { - return false; - } else { - ++i1, ++i2; - } - } - - while (i1 < s1.size() && s1[i1] == '_') { - ++i1; - } - while (i2 < s2.size() && s2[i2] == '_') { - ++i2; - } - - return (i1 == s1.size() && i2 == s2.size()); - } + bool EqualsIgnoringCaseAndUnderscores(TStringBuf s1, TStringBuf s2) { + size_t i1 = 0, i2 = 0; + + while (i1 < s1.size() && i2 < s2.size()) { + if (s1[i1] == '_') { + ++i1; + } else if (s2[i2] == '_') { + ++i2; + } else if (AsciiToUpper(s1[i1]) != AsciiToUpper(s2[i2])) { + return false; + } else { + ++i1, ++i2; + } + } + + while (i1 < s1.size() && s1[i1] == '_') { + ++i1; + } + while (i2 < s2.size() && s2[i2] == '_') { + ++i2; + } + + return (i1 == s1.size() && i2 == s2.size()); + } } diff --git a/library/cpp/protobuf/json/util.h b/library/cpp/protobuf/json/util.h index d93342d3f8..7ee2405afd 100644 --- a/library/cpp/protobuf/json/util.h +++ b/library/cpp/protobuf/json/util.h @@ -4,11 +4,11 @@ namespace NProtobufJson { void ToSnakeCase(TString* const name); - + void ToSnakeCaseDense(TString* const name); - /** - * "FOO_BAR" ~ "foo_bar" ~ "fooBar" - */ - bool EqualsIgnoringCaseAndUnderscores(TStringBuf s1, TStringBuf s2); + /** + * "FOO_BAR" ~ "foo_bar" ~ "fooBar" + */ + bool EqualsIgnoringCaseAndUnderscores(TStringBuf s1, TStringBuf s2); } diff --git a/library/cpp/unicode/punycode/punycode.cpp b/library/cpp/unicode/punycode/punycode.cpp index 800d1f19fe..adbb80ad53 100644 --- a/library/cpp/unicode/punycode/punycode.cpp +++ b/library/cpp/unicode/punycode/punycode.cpp @@ -19,7 +19,7 @@ static inline void CheckIdnaResult(int rc) { // UTF-32 helpers -static inline void AppendWideToUtf32(const TWtringBuf& in, TVector<ui32>& out) { +static inline void AppendWideToUtf32(const TWtringBuf& in, TVector<ui32>& out) { out.reserve(out.size() + in.size() + 1); const wchar16* b = in.begin(); @@ -29,18 +29,18 @@ static inline void AppendWideToUtf32(const TWtringBuf& in, TVector<ui32>& out) { } } -static inline void AppendUtf32ToWide(const ui32* in, size_t len, TUtf16String& out) { +static inline void AppendUtf32ToWide(const ui32* in, size_t len, TUtf16String& out) { out.reserve(out.size() + len); - const ui32* b = in; - const ui32* e = in + len; + const ui32* b = in; + const ui32* e = in + len; for (; b != e; ++b) { - WriteSymbol(wchar32(*b), out); + WriteSymbol(wchar32(*b), out); } } TStringBuf WideToPunycode(const TWtringBuf& in16, TString& out) { - TVector<ui32> in32; + TVector<ui32> in32; AppendWideToUtf32(in16, in32); size_t outlen = in32.size(); @@ -59,7 +59,7 @@ TStringBuf WideToPunycode(const TWtringBuf& in16, TString& out) { TWtringBuf PunycodeToWide(const TStringBuf& in, TUtf16String& out16) { size_t outlen = in.size(); - TVector<ui32> out32(outlen); + TVector<ui32> out32(outlen); int rc = punycode_decode(in.size(), in.data(), &outlen, out32.begin(), nullptr); CheckPunycodeResult(rc); @@ -80,7 +80,7 @@ namespace { } TString HostNameToPunycode(const TWtringBuf& unicodeHost) { - TVector<ui32> in32; + TVector<ui32> in32; AppendWideToUtf32(unicodeHost, in32); in32.push_back(0); @@ -96,12 +96,12 @@ TUtf16String PunycodeToHostName(const TStringBuf& punycodeHost) { ythrow TPunycodeError() << "Non-ASCII punycode input"; size_t len = punycodeHost.size(); - TVector<ui32> in32(len + 1, 0); + TVector<ui32> in32(len + 1, 0); for (size_t i = 0; i < len; ++i) in32[i] = static_cast<ui8>(punycodeHost[i]); in32[len] = 0; - TIdnaResult<ui32> out; + TIdnaResult<ui32> out; int rc = idna_to_unicode_4z4z(in32.begin(), &out.Data, 0); CheckIdnaResult(rc); diff --git a/library/cpp/uri/uri-ru_ut.cpp b/library/cpp/uri/uri-ru_ut.cpp index ec35a164d2..3fca250dcf 100644 --- a/library/cpp/uri/uri-ru_ut.cpp +++ b/library/cpp/uri/uri-ru_ut.cpp @@ -4,15 +4,15 @@ #include <util/system/maxlen.h> namespace NUri { - namespace { - TString AsWin1251(const TString& s) { - return Recode(CODES_UTF8, CODES_WIN, s); - } - TString AsKoi8(const TString& s) { - return Recode(CODES_UTF8, CODES_KOI8, s); - } - } - + namespace { + TString AsWin1251(const TString& s) { + return Recode(CODES_UTF8, CODES_WIN, s); + } + TString AsKoi8(const TString& s) { + return Recode(CODES_UTF8, CODES_KOI8, s); + } + } + Y_UNIT_TEST_SUITE(URLTestRU) { Y_UNIT_TEST(test_httpURL2) { TUri url; @@ -37,19 +37,19 @@ namespace NUri { UNIT_ASSERT(!url.IsNull(TField::FlagPath)); UNIT_ASSERT_VALUES_EQUAL(url.PrintS(TField::FlagPath), "www.ya.ru/index.html"); - UNIT_ASSERT_VALUES_EQUAL(url.Parse(AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10")), TState::ParsedOK); - UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10")); + UNIT_ASSERT_VALUES_EQUAL(url.Parse(AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10")), TState::ParsedOK); + UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10")); - UNIT_ASSERT_VALUES_EQUAL(url.Parse(AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10"), + UNIT_ASSERT_VALUES_EQUAL(url.Parse(AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10"), TFeature::FeaturesDefault | TFeature::FeatureEncodeExtendedASCII), TState::ParsedOK); UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), - AsWin1251("www.TEST.Ru/%D4%C5%D3%D4\\'\".html?%D4%C5%D3%D4\\'\"=%D4%C5%D3%D4+\\'\"%10")); + AsWin1251("www.TEST.Ru/%D4%C5%D3%D4\\'\".html?%D4%C5%D3%D4\\'\"=%D4%C5%D3%D4+\\'\"%10")); - UNIT_ASSERT_VALUES_EQUAL(url.Parse(AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10"), + UNIT_ASSERT_VALUES_EQUAL(url.Parse(AsWin1251("www.TEST.Ru/ФЕУФ\\'\".html?ФЕУФ\\'\"=ФЕУФ+\\'\"%10"), TFeature::FeaturesDefault | TFeature::FeatureEncodeForSQL), TState::ParsedOK); - UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), AsWin1251("www.TEST.Ru/ФЕУФ%5C%27%22.html?ФЕУФ%5C%27%22=ФЕУФ+%5C%27%22%10")); + UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), AsWin1251("www.TEST.Ru/ФЕУФ%5C%27%22.html?ФЕУФ%5C%27%22=ФЕУФ+%5C%27%22%10")); UNIT_ASSERT_VALUES_EQUAL(url.Parse("q/%33%26%13%2f%2b%30%20", TFeature::FeaturesDefault | TFeature::FeatureDecodeStandard), @@ -62,7 +62,7 @@ namespace NUri { UNIT_ASSERT_VALUES_EQUAL(url.Parse("//server/path", TFeature::FeaturesRobot), TState::ParsedOK); } - const TString links[] = { + const TString links[] = { "viewforum.php?f=1&sid=b4568481b67b1d7683bea78634b2e240", "viewforum.php?f=1&sid=b4568481b67b1d7683bea78634b2e240", "./viewtopic.php?p=74&sid=6#p74", "./viewtopic.php?p=74&sid=6#p74", "viewtopic.php?p=9313&sid=8#9313", "viewtopic.php?p=9313&sid=8#9313", @@ -71,12 +71,12 @@ namespace NUri { "images\nil.jpg", "images%0Ail.jpg", "http://caedebaturque.termez.su\r\n/?article=218", "http://caedebaturque.termez.su%0D%0A/?article=218", - AsKoi8("javascript:window.external.AddFavorite(\'http://www.humor.look.ru/\',\'Злобные Деды Морозы!!!\')"), "javascript:window.external.AddFavorite(\'http://www.humor.look.ru/\',\'%FA%CC%CF%C2%CE%D9%C5%20%E4%C5%C4%D9%20%ED%CF%D2%CF%DA%D9!!!\')", + AsKoi8("javascript:window.external.AddFavorite(\'http://www.humor.look.ru/\',\'Злобные Деды Морозы!!!\')"), "javascript:window.external.AddFavorite(\'http://www.humor.look.ru/\',\'%FA%CC%CF%C2%CE%D9%C5%20%E4%C5%C4%D9%20%ED%CF%D2%CF%DA%D9!!!\')", "search.php?search_author=%CB%FE%E4%EC%E8%EB%E0+%C3%F3%F1%E5%E2%E0&showresults=posts&sid=8", "search.php?search_author=%CB%FE%E4%EC%E8%EB%E0+%C3%F3%F1%E5%E2%E0&showresults=posts&sid=8", - AsWin1251("/Search/author/?q=Штрибель Х.В."), "/Search/author/?q=%D8%F2%F0%E8%E1%E5%EB%FC%20%D5.%C2.", - AsWin1251("javascript:ins(\'ГОРШОК\')"), "javascript:ins(\'%C3%CE%D0%D8%CE%CA\')", - AsWin1251("?l=я"), "?l=%FF", - AsWin1251("content.php?id=3392&theme=Цена"), "content.php?id=3392&theme=%D6%E5%ED%E0", + AsWin1251("/Search/author/?q=Штрибель Х.В."), "/Search/author/?q=%D8%F2%F0%E8%E1%E5%EB%FC%20%D5.%C2.", + AsWin1251("javascript:ins(\'ГОРШОК\')"), "javascript:ins(\'%C3%CE%D0%D8%CE%CA\')", + AsWin1251("?l=я"), "?l=%FF", + AsWin1251("content.php?id=3392&theme=Цена"), "content.php?id=3392&theme=%D6%E5%ED%E0", "/a-mp3/stype-1/?search=А", "/a-mp3/stype-1/?search=%D0%90", "/a-mp3/stype-1/?search=Б", "/a-mp3/stype-1/?search=%D0%91", "/a-mp3/stype-1/?search=В", "/a-mp3/stype-1/?search=%D0%92", @@ -86,7 +86,7 @@ namespace NUri { "/a-mp3/stype-1/?search=Ж", "/a-mp3/stype-1/?search=%D0%96", "/a-mp3/stype-1/?search=З", "/a-mp3/stype-1/?search=%D0%97", // %98 is not defined in CP1251 so don't put it here explicitly - "/a-mp3/stype-1/?search=\xD0\x98", "/a-mp3/stype-1/?search=%D0%98", + "/a-mp3/stype-1/?search=\xD0\x98", "/a-mp3/stype-1/?search=%D0%98", "/a-mp3/stype-1/?search=Й", "/a-mp3/stype-1/?search=%D0%99", "/a-mp3/stype-1/?search=К", "/a-mp3/stype-1/?search=%D0%9A", "/a-mp3/stype-1/?search=Л", "/a-mp3/stype-1/?search=%D0%9B", @@ -94,7 +94,7 @@ namespace NUri { "/a-mp3/stype-1/?search=Н", "/a-mp3/stype-1/?search=%D0%9D", "/a-mp3/stype-1/?search=О", "/a-mp3/stype-1/?search=%D0%9E", "/a-mp3/stype-1/?search=П", "/a-mp3/stype-1/?search=%D0%9F", - "/a-mp3/stype-1/?search=\xD0", "/a-mp3/stype-1/?search=%D0", + "/a-mp3/stype-1/?search=\xD0", "/a-mp3/stype-1/?search=%D0", "/a-mp3/stype-1/?search=С", "/a-mp3/stype-1/?search=%D0%A1", "/a-mp3/stype-1/?search=Т", "/a-mp3/stype-1/?search=%D0%A2", "/a-mp3/stype-1/?search=У", "/a-mp3/stype-1/?search=%D0%A3", @@ -117,20 +117,20 @@ namespace NUri { "http://www.is-ufa.ru/price2/price_IS.rar", "http://www.is-ufa.ru/price2/price_IS.rar", "mailto:info@etem.de", "mailto:info@etem.de", ""http://www.fubix.ru"", "\"http://www.fubix.ru\"", - AsWin1251("mailto:kampa@ukr.net?subject=Арабский язык"), "mailto:kampa@ukr.net?subject=%C0%F0%E0%E1%F1%EA%E8%E9%20%FF%E7%FB%EA", - {}}; + AsWin1251("mailto:kampa@ukr.net?subject=Арабский язык"), "mailto:kampa@ukr.net?subject=%C0%F0%E0%E1%F1%EA%E8%E9%20%FF%E7%FB%EA", + {}}; Y_UNIT_TEST(testHtLinkDecode) { char decodedlink[URL_MAXLEN + 10]; for (int i = 0; links[i]; i += 2) { - UNIT_ASSERT(HtLinkDecode(links[i].c_str(), decodedlink, sizeof(decodedlink))); - UNIT_ASSERT_VALUES_EQUAL(decodedlink, links[i + 1]); + UNIT_ASSERT(HtLinkDecode(links[i].c_str(), decodedlink, sizeof(decodedlink))); + UNIT_ASSERT_VALUES_EQUAL(decodedlink, links[i + 1]); } } Y_UNIT_TEST(testRuIDNA) { { -#define DEC "\xD7\xE5\xF0\xE5\xEf\xEE\xE2\xE5\xF6.\xF0\xF4" /* "Череповец.рф" in Windows-1251 */ +#define DEC "\xD7\xE5\xF0\xE5\xEf\xEE\xE2\xE5\xF6.\xF0\xF4" /* "Череповец.рф" in Windows-1251 */ #define ENC "%D7%E5%F0%E5%EF%EE%E2%E5%F6.%F0%F4" // punycode corresponds to lowercase #define PNC "xn--b1afab7bff7cb.xn--p1ai" diff --git a/library/cpp/xml/document/libxml-guards.h b/library/cpp/xml/document/libxml-guards.h index 4188cecff1..479ce285e5 100644 --- a/library/cpp/xml/document/libxml-guards.h +++ b/library/cpp/xml/document/libxml-guards.h @@ -40,7 +40,7 @@ namespace NXml { typedef TxmlXPathObjectPtr TXPathObjectPtr; typedef TAutoPtr<char, NDetail::TSignedCharPtrTraits> TSignedCharPtr; typedef TAutoPtr<xmlChar, NDetail::TCharPtrTraits> TCharPtr; - typedef TxmlDocHolder TDocHolder; + typedef TxmlDocHolder TDocHolder; typedef TxmlURIPtr TURIPtr; typedef TxmlNodePtr TNodePtr; typedef TAutoPtr<xmlOutputBuffer, NDetail::TOutputBufferPtrTraits> TOutputBufferPtr; diff --git a/library/cpp/xml/document/ut/ya.make b/library/cpp/xml/document/ut/ya.make index e955448c66..9a7213baa0 100644 --- a/library/cpp/xml/document/ut/ya.make +++ b/library/cpp/xml/document/ut/ya.make @@ -4,7 +4,7 @@ OWNER(finder) SRCS( xml-document_ut.cpp - xml-textreader_ut.cpp + xml-textreader_ut.cpp xml-options_ut.cpp ) diff --git a/library/cpp/xml/document/xml-document-decl.h b/library/cpp/xml/document/xml-document-decl.h index bfda1fb7e6..cde87a311b 100644 --- a/library/cpp/xml/document/xml-document-decl.h +++ b/library/cpp/xml/document/xml-document-decl.h @@ -15,8 +15,8 @@ namespace NXml { class TConstNodes; class TConstNode; - using TXPathContext = xmlXPathContext; - + using TXPathContext = xmlXPathContext; + class TDocument { public: enum Source { @@ -35,11 +35,11 @@ namespace NXml { TDocument(const TString& source, Source type = File); public: - TDocument(const TDocument& that) = delete; - TDocument& operator=(const TDocument& that) = delete; + TDocument(const TDocument& that) = delete; + TDocument& operator=(const TDocument& that) = delete; - TDocument(TDocument&& that); - TDocument& operator=(TDocument&& that); + TDocument(TDocument&& that); + TDocument& operator=(TDocument&& that); /** * get root element @@ -74,12 +74,12 @@ namespace NXml { void ParseFile(const TString& file); void ParseString(TZtStringBuf xml); - TDocument(TDocHolder doc) - : Doc(std::move(doc)) + TDocument(TDocHolder doc) + : Doc(std::move(doc)) { } - TDocHolder Doc; + TDocHolder Doc; }; struct TNamespaceForXPath { @@ -150,7 +150,7 @@ namespace NXml { friend class TConstNode; friend class TNode; - TConstNodes(xmlDoc* doc, TXPathObjectPtr obj); + TConstNodes(xmlDoc* doc, TXPathObjectPtr obj); size_t SizeValue; xmlDoc* Doc; @@ -161,7 +161,7 @@ namespace NXml { public: friend class TDocument; friend class TConstNode; - friend class TTextReader; + friend class TTextReader; /** * check if node is null @@ -174,18 +174,18 @@ namespace NXml { bool IsElementNode() const; /** - * Create xpath context to be used later for fast xpath evaluation. - * @param nss: explicitly specify XML namespaces to use and their prefixes - * - * For better performance, when you need to evaluate several xpath expressions, - * it makes sense to create a context, load namespace prefixes once - * and use the context several times in Node(), Nodes(), XPath() function calls for several nodes. - * The context may be used with any node of the current document, but - * cannot be shared between different XML documents. - */ - TXPathContextPtr CreateXPathContext(const TNamespacesForXPath& nss = TNamespacesForXPath()) const; - - /** + * Create xpath context to be used later for fast xpath evaluation. + * @param nss: explicitly specify XML namespaces to use and their prefixes + * + * For better performance, when you need to evaluate several xpath expressions, + * it makes sense to create a context, load namespace prefixes once + * and use the context several times in Node(), Nodes(), XPath() function calls for several nodes. + * The context may be used with any node of the current document, but + * cannot be shared between different XML documents. + */ + TXPathContextPtr CreateXPathContext(const TNamespacesForXPath& nss = TNamespacesForXPath()) const; + + /** * get all element nodes matching given xpath expression * @param xpath: xpath expression * @param quiet: don't throw exception if zero nodes found @@ -197,17 +197,17 @@ namespace NXml { TConstNodes Nodes(TZtStringBuf xpath, bool quiet = false, const TNamespacesForXPath& ns = TNamespacesForXPath()) const; /** - * get all element nodes matching given xpath expression - * @param xpath: xpath expression - * @param quiet: don't throw exception if zero nodes found - * @param ctxt: reusable xpath context - * - * For historical reasons, this only works for *element* nodes. - * Use the XPath function if you need other kinds of nodes. - */ + * get all element nodes matching given xpath expression + * @param xpath: xpath expression + * @param quiet: don't throw exception if zero nodes found + * @param ctxt: reusable xpath context + * + * For historical reasons, this only works for *element* nodes. + * Use the XPath function if you need other kinds of nodes. + */ TConstNodes Nodes(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const; - - /** + + /** * get all nodes matching given xpath expression * @param xpath: xpath expression * @param quiet: don't throw exception if zero nodes found @@ -216,18 +216,18 @@ namespace NXml { TConstNodes XPath(TZtStringBuf xpath, bool quiet = false, const TNamespacesForXPath& ns = TNamespacesForXPath()) const; /** - * get all nodes matching given xpath expression - * @param xpath: xpath expression - * @param quiet: don't throw exception if zero nodes found - * @param ctxt: reusable xpath context - */ + * get all nodes matching given xpath expression + * @param xpath: xpath expression + * @param quiet: don't throw exception if zero nodes found + * @param ctxt: reusable xpath context + */ TConstNodes XPath(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const; - - /** + + /** * get the first element node matching given xpath expression * @param xpath: path to node (from current node) * @param quiet: don't throw exception if node not found, - * return null node (@see IsNull()) + * return null node (@see IsNull()) * @param ns: explicitly specify XML namespaces to use and their prefixes * * For historical reasons, this only works for *element* nodes. @@ -238,23 +238,23 @@ namespace NXml { TConstNode Node(TZtStringBuf xpath, bool quiet = false, const TNamespacesForXPath& ns = TNamespacesForXPath()) const; /** - * get the first element node matching given xpath expression - * @param xpath: path to node (from current node) - * @param quiet: don't throw exception if node not found, - * return null node (@see IsNull()) - * @param ctxt: reusable xpath context - * - * For historical reasons, this only works for *element* nodes. - * Use the XPath function if you need other kinds of nodes. - */ + * get the first element node matching given xpath expression + * @param xpath: path to node (from current node) + * @param quiet: don't throw exception if node not found, + * return null node (@see IsNull()) + * @param ctxt: reusable xpath context + * + * For historical reasons, this only works for *element* nodes. + * Use the XPath function if you need other kinds of nodes. + */ TNode Node(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt); TConstNode Node(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const; - - /** + + /** * get node first child * @param name: child name - * @note if name is empty, returns the first child node of type "element" - * @note returns null node if no child found + * @note if name is empty, returns the first child node of type "element" + * @note returns null node if no child found */ TNode FirstChild(TZtStringBuf name); TConstNode FirstChild(TZtStringBuf name) const; @@ -272,8 +272,8 @@ namespace NXml { /** * get node neighbour * @param name: neighbour name - * @note if name is empty, returns the next sibling node of type "element" - * @node returns null node if no neighbour found + * @note if name is empty, returns the next sibling node of type "element" + * @node returns null node if no neighbour found */ TNode NextSibling(TZtStringBuf name); TConstNode NextSibling(TZtStringBuf name) const; @@ -495,18 +495,18 @@ namespace NXml { } /** - * Create xpath context to be used later for fast xpath evaluation. - * @param nss: explicitly specify XML namespaces to use and their prefixes - */ + * Create xpath context to be used later for fast xpath evaluation. + * @param nss: explicitly specify XML namespaces to use and their prefixes + */ TXPathContextPtr CreateXPathContext(const TNamespacesForXPath& nss = TNamespacesForXPath()) const { - return ActualNode.CreateXPathContext(nss); - } - - /** + return ActualNode.CreateXPathContext(nss); + } + + /** * get all element nodes matching given xpath expression * @param xpath: xpath expression * @param quiet: don't throw exception if zero nodes found - * @param ns: explicitly specify XML namespaces to use and their prefixes + * @param ns: explicitly specify XML namespaces to use and their prefixes * * For historical reasons, this only works for *element* nodes. * Use the XPath function if you need other kinds of nodes. @@ -516,44 +516,44 @@ namespace NXml { } /** - * get all element nodes matching given xpath expression - * @param xpath: xpath expression - * @param quiet: don't throw exception if zero nodes found - * @param ctxt: reusable xpath context - * - * For historical reasons, this only works for *element* nodes. - * Use the XPath function if you need other kinds of nodes. - */ + * get all element nodes matching given xpath expression + * @param xpath: xpath expression + * @param quiet: don't throw exception if zero nodes found + * @param ctxt: reusable xpath context + * + * For historical reasons, this only works for *element* nodes. + * Use the XPath function if you need other kinds of nodes. + */ TConstNodes Nodes(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const { - return ActualNode.Nodes(xpath, quiet, ctxt); - } - - /** + return ActualNode.Nodes(xpath, quiet, ctxt); + } + + /** * get all nodes matching given xpath expression * @param xpath: xpath expression * @param quiet: don't throw exception if zero nodes found - * @param ns: explicitly specify XML namespaces to use and their prefixes + * @param ns: explicitly specify XML namespaces to use and their prefixes */ TConstNodes XPath(TZtStringBuf xpath, bool quiet = false, const TNamespacesForXPath& ns = TNamespacesForXPath()) const { return ActualNode.XPath(xpath, quiet, ns); } /** - * get all nodes matching given xpath expression - * @param xpath: xpath expression - * @param quiet: don't throw exception if zero nodes found - * @param ctxt: reusable xpath context - */ + * get all nodes matching given xpath expression + * @param xpath: xpath expression + * @param quiet: don't throw exception if zero nodes found + * @param ctxt: reusable xpath context + */ TConstNodes XPath(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const { - return ActualNode.XPath(xpath, quiet, ctxt); - } - - /** + return ActualNode.XPath(xpath, quiet, ctxt); + } + + /** * get the first element node matching given xpath expression * @param xpath: path to node (from current node) * @param quiet: don't throw exception if node not found, - * return null node (@see IsNull()) - * @param ns: explicitly specify XML namespaces to use and their prefixes + * return null node (@see IsNull()) + * @param ns: explicitly specify XML namespaces to use and their prefixes * * For historical reasons, this only works for *element* nodes. * Use the XPath function if you need other kinds of nodes. @@ -562,20 +562,20 @@ namespace NXml { return ActualNode.Node(xpath, quiet, ns); } - /** - * get the first element node matching given xpath expression - * @param xpath: path to node (from current node) - * @param quiet: don't throw exception if node not found, - * return null node (@see IsNull()) - * @param ctxt: reusable xpath context - * - * For historical reasons, this only works for *element* nodes. - * Use the XPath function if you need other kinds of nodes. - */ + /** + * get the first element node matching given xpath expression + * @param xpath: path to node (from current node) + * @param quiet: don't throw exception if node not found, + * return null node (@see IsNull()) + * @param ctxt: reusable xpath context + * + * For historical reasons, this only works for *element* nodes. + * Use the XPath function if you need other kinds of nodes. + */ TConstNode Node(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const { - return ActualNode.Node(xpath, quiet, ctxt); - } - + return ActualNode.Node(xpath, quiet, ctxt); + } + TConstNode FirstChild(TZtStringBuf name) const { return ActualNode.FirstChild(name); } diff --git a/library/cpp/xml/document/xml-document.cpp b/library/cpp/xml/document/xml-document.cpp index 18a554d732..6907217a14 100644 --- a/library/cpp/xml/document/xml-document.cpp +++ b/library/cpp/xml/document/xml-document.cpp @@ -26,7 +26,7 @@ namespace NXml { ParseString(xml); break; case RootName: { - TDocHolder doc(xmlNewDoc(XMLCHAR("1.0"))); + TDocHolder doc(xmlNewDoc(XMLCHAR("1.0"))); if (!doc) THROW(XmlException, "Can't create xml document."); doc->encoding = xmlStrdup(XMLCHAR("utf-8")); @@ -36,21 +36,21 @@ namespace NXml { THROW(XmlException, "Can't create root node."); xmlDocSetRootElement(doc.Get(), node.Get()); Y_UNUSED(node.Release()); - Doc = std::move(doc); + Doc = std::move(doc); } break; default: THROW(InvalidArgument, "Wrong source type"); } } - TDocument::TDocument(TDocument&& doc) - : Doc(std::move(doc.Doc)) + TDocument::TDocument(TDocument&& doc) + : Doc(std::move(doc.Doc)) { } - TDocument& TDocument::operator=(TDocument&& doc) { + TDocument& TDocument::operator=(TDocument&& doc) { if (this != &doc) - doc.Swap(*this); + doc.Swap(*this); return *this; } @@ -63,7 +63,7 @@ namespace NXml { if (!pctx) THROW(XmlException, "Can't create parser context"); - TDocHolder doc(xmlCtxtReadFile(pctx.Get(), file.c_str(), nullptr, XML_PARSE_NOCDATA)); + TDocHolder doc(xmlCtxtReadFile(pctx.Get(), file.c_str(), nullptr, XML_PARSE_NOCDATA)); if (!doc) THROW(XmlException, "Can't parse file " << file); @@ -72,7 +72,7 @@ namespace NXml { if (res == -1) THROW(XmlException, "XIncludes processing failed"); - Doc = std::move(doc); + Doc = std::move(doc); } void TDocument::ParseString(TZtStringBuf xml) { @@ -80,12 +80,12 @@ namespace NXml { if (pctx.Get() == nullptr) THROW(XmlException, "Can't create parser context"); - TDocHolder doc(xmlCtxtReadMemory(pctx.Get(), xml.c_str(), (int)xml.size(), nullptr, nullptr, XML_PARSE_NOCDATA)); + TDocHolder doc(xmlCtxtReadMemory(pctx.Get(), xml.c_str(), (int)xml.size(), nullptr, nullptr, XML_PARSE_NOCDATA)); if (!doc) THROW(XmlException, "Can't parse string"); - Doc = std::move(doc); + Doc = std::move(doc); } TNode TDocument::Root() { @@ -113,34 +113,34 @@ namespace NXml { } TXPathContextPtr TNode::CreateXPathContext(const TNamespacesForXPath& nss) const { - TXPathContextPtr ctx = xmlXPathNewContext(DocPointer); - if (!ctx) - THROW(XmlException, "Can't create empty xpath context"); - - for (const auto& ns : nss) { - const int r = xmlXPathRegisterNs(ctx.Get(), XMLCHAR(ns.Prefix.c_str()), XMLCHAR(ns.Url.c_str())); - if (r != 0) - THROW(XmlException, "Can't register namespace " << ns.Url << " with prefix " << ns.Prefix); - } - - return ctx; - } - + TXPathContextPtr ctx = xmlXPathNewContext(DocPointer); + if (!ctx) + THROW(XmlException, "Can't create empty xpath context"); + + for (const auto& ns : nss) { + const int r = xmlXPathRegisterNs(ctx.Get(), XMLCHAR(ns.Prefix.c_str()), XMLCHAR(ns.Url.c_str())); + if (r != 0) + THROW(XmlException, "Can't register namespace " << ns.Url << " with prefix " << ns.Prefix); + } + + return ctx; + } + TConstNodes TNode::XPath(TZtStringBuf xpath, bool quiet, const TNamespacesForXPath& ns) const { - TXPathContextPtr ctxt = CreateXPathContext(ns); - return XPath(xpath, quiet, *ctxt); - } + TXPathContextPtr ctxt = CreateXPathContext(ns); + return XPath(xpath, quiet, *ctxt); + } TConstNodes TNode::XPath(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const { - if (xmlXPathSetContextNode(NodePointer, &ctxt) != 0) - THROW(XmlException, "Can't set xpath context node, probably the context is associated with another document"); - - TXPathObjectPtr obj = xmlXPathEvalExpression(XMLCHAR(xpath.c_str()), &ctxt); - if (!obj) - THROW(XmlException, "Can't evaluate xpath expression " << xpath); - - TConstNodes nodes(DocPointer, obj); - + if (xmlXPathSetContextNode(NodePointer, &ctxt) != 0) + THROW(XmlException, "Can't set xpath context node, probably the context is associated with another document"); + + TXPathObjectPtr obj = xmlXPathEvalExpression(XMLCHAR(xpath.c_str()), &ctxt); + if (!obj) + THROW(XmlException, "Can't evaluate xpath expression " << xpath); + + TConstNodes nodes(DocPointer, obj); + if (nodes.Size() == 0 && !quiet) THROW(NodeNotFound, xpath); @@ -148,30 +148,30 @@ namespace NXml { } TConstNodes TNode::Nodes(TZtStringBuf xpath, bool quiet, const TNamespacesForXPath& ns) const { - TXPathContextPtr ctxt = CreateXPathContext(ns); - return Nodes(xpath, quiet, *ctxt); - } - + TXPathContextPtr ctxt = CreateXPathContext(ns); + return Nodes(xpath, quiet, *ctxt); + } + TConstNodes TNode::Nodes(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const { - TConstNodes nodes = XPath(xpath, quiet, ctxt); + TConstNodes nodes = XPath(xpath, quiet, ctxt); if (nodes.Size() != 0 && !nodes[0].IsElementNode()) THROW(XmlException, "xpath points to non-element nodes: " << xpath); return nodes; } TNode TNode::Node(TZtStringBuf xpath, bool quiet, const TNamespacesForXPath& ns) { - TXPathContextPtr ctxt = CreateXPathContext(ns); - return Node(xpath, quiet, *ctxt); - } + TXPathContextPtr ctxt = CreateXPathContext(ns); + return Node(xpath, quiet, *ctxt); + } TConstNode TNode::Node(TZtStringBuf xpath, bool quiet, const TNamespacesForXPath& ns) const { - TXPathContextPtr ctxt = CreateXPathContext(ns); - return Node(xpath, quiet, *ctxt); - } - + TXPathContextPtr ctxt = CreateXPathContext(ns); + return Node(xpath, quiet, *ctxt); + } + TNode TNode::Node(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) { - TConstNodes n = Nodes(xpath, quiet, ctxt); - + TConstNodes n = Nodes(xpath, quiet, ctxt); + if (n.Size() == 0 && !quiet) THROW(NodeNotFound, xpath); @@ -182,7 +182,7 @@ namespace NXml { } TConstNode TNode::Node(TZtStringBuf xpath, bool quiet, TXPathContext& ctxt) const { - return const_cast<TNode*>(this)->Node(xpath, quiet, ctxt); + return const_cast<TNode*>(this)->Node(xpath, quiet, ctxt); } TNode TNode::FirstChild(TZtStringBuf name) { @@ -271,9 +271,9 @@ namespace NXml { } TString TNode::Name() const { - if (IsNull()) - THROW(XmlException, "Node is null"); - + if (IsNull()) + THROW(XmlException, "Node is null"); + return CAST2CHAR(NodePointer->name); } @@ -294,9 +294,9 @@ namespace NXml { } bool TNode::IsText() const { - if (IsNull()) - THROW(XmlException, "Node is null"); - + if (IsNull()) + THROW(XmlException, "Node is null"); + return NodePointer->type == XML_TEXT_NODE; } @@ -368,10 +368,10 @@ namespace NXml { return TConstNodesRef(*this); } - TConstNodes::TConstNodes(xmlDoc* doc, TXPathObjectPtr obj) - : SizeValue(obj && obj->nodesetval ? obj->nodesetval->nodeNr : 0) - , Doc(doc) - , Obj(obj) + TConstNodes::TConstNodes(xmlDoc* doc, TXPathObjectPtr obj) + : SizeValue(obj && obj->nodesetval ? obj->nodesetval->nodeNr : 0) + , Doc(doc) + , Obj(obj) { } diff --git a/library/cpp/xml/document/xml-document_ut.cpp b/library/cpp/xml/document/xml-document_ut.cpp index 9f537b75c4..8361e3c503 100644 --- a/library/cpp/xml/document/xml-document_ut.cpp +++ b/library/cpp/xml/document/xml-document_ut.cpp @@ -84,11 +84,11 @@ Y_UNIT_TEST_SUITE(TestXmlDocument) { TConstNode text = root.Node("h:text", false, nss); UNIT_ASSERT_EQUAL(text.Value<TString>(), "Некоторый текст"); - - // For performance you can create xpath context once using nss and pass it. - TXPathContextPtr ctxt = root.CreateXPathContext(nss); - UNIT_ASSERT(root.Node("text", true, *ctxt).IsNull()); - UNIT_ASSERT_EXCEPTION(root.Node("text", false, *ctxt), yexception); + + // For performance you can create xpath context once using nss and pass it. + TXPathContextPtr ctxt = root.CreateXPathContext(nss); + UNIT_ASSERT(root.Node("text", true, *ctxt).IsNull()); + UNIT_ASSERT_EXCEPTION(root.Node("text", false, *ctxt), yexception); UNIT_ASSERT_EQUAL(root.Node("h:text", false, *ctxt).Value<TString>(), "Некоторый текст"); } Y_UNIT_TEST(XmlNodes) { @@ -119,37 +119,37 @@ Y_UNIT_TEST_SUITE(TestXmlDocument) { iterLog << node2.Name() << ';'; } UNIT_ASSERT_STRINGS_EQUAL(iterLog.Str(), "a;c;"); - - // get only element nodes, ignore text nodes with empty "name" param + + // get only element nodes, ignore text nodes with empty "name" param node = root.FirstChild(TString()); - UNIT_ASSERT_EQUAL(node.IsText(), false); - UNIT_ASSERT_EQUAL(node.Name(), "a"); + UNIT_ASSERT_EQUAL(node.IsText(), false); + UNIT_ASSERT_EQUAL(node.Name(), "a"); node = node.NextSibling(TString()); - UNIT_ASSERT_EQUAL(node.IsText(), false); - UNIT_ASSERT_EQUAL(node.Name(), "c"); - - // use exact "name" to retrieve children and siblings - node = root.FirstChild("a"); - UNIT_ASSERT_EQUAL(node.IsNull(), false); - UNIT_ASSERT_EQUAL(node.Name(), "a"); - node = node.NextSibling("c"); - UNIT_ASSERT_EQUAL(node.IsNull(), false); - UNIT_ASSERT_EQUAL(node.Name(), "c"); - node = root.FirstChild("c"); // skip "a" - UNIT_ASSERT_EQUAL(node.IsNull(), false); - UNIT_ASSERT_EQUAL(node.Name(), "c"); - - // node not found: no exceptions, null nodes are returned - node = root.FirstChild("b"); // b is not direct child of root - UNIT_ASSERT_EQUAL(node.IsNull(), true); - node = root.FirstChild("nosuchnode"); - UNIT_ASSERT_EQUAL(node.IsNull(), true); - node = root.FirstChild(); - node = root.NextSibling("unknownnode"); - UNIT_ASSERT_EQUAL(node.IsNull(), true); - UNIT_ASSERT_EXCEPTION(node.Name(), yexception); + UNIT_ASSERT_EQUAL(node.IsText(), false); + UNIT_ASSERT_EQUAL(node.Name(), "c"); + + // use exact "name" to retrieve children and siblings + node = root.FirstChild("a"); + UNIT_ASSERT_EQUAL(node.IsNull(), false); + UNIT_ASSERT_EQUAL(node.Name(), "a"); + node = node.NextSibling("c"); + UNIT_ASSERT_EQUAL(node.IsNull(), false); + UNIT_ASSERT_EQUAL(node.Name(), "c"); + node = root.FirstChild("c"); // skip "a" + UNIT_ASSERT_EQUAL(node.IsNull(), false); + UNIT_ASSERT_EQUAL(node.Name(), "c"); + + // node not found: no exceptions, null nodes are returned + node = root.FirstChild("b"); // b is not direct child of root + UNIT_ASSERT_EQUAL(node.IsNull(), true); + node = root.FirstChild("nosuchnode"); + UNIT_ASSERT_EQUAL(node.IsNull(), true); + node = root.FirstChild(); + node = root.NextSibling("unknownnode"); + UNIT_ASSERT_EQUAL(node.IsNull(), true); + UNIT_ASSERT_EXCEPTION(node.Name(), yexception); UNIT_ASSERT_EXCEPTION(node.Value<TString>(), yexception); - UNIT_ASSERT_EXCEPTION(node.IsText(), yexception); + UNIT_ASSERT_EXCEPTION(node.IsText(), yexception); } Y_UNIT_TEST(DefVal) { using namespace NXml; @@ -235,49 +235,49 @@ Y_UNIT_TEST_SUITE(TestXmlDocument) { UNIT_ASSERT_VALUES_EQUAL(n.ToString(), "<a><b len=\"15\" correct=\"1\">hello world</b></a>"); } } - + Y_UNIT_TEST(ReuseXPathContext) { - using namespace NXml; - - TDocument xml( - "<?xml version=\"1.0\"?>\n" - "<root>\n" - "<a><b><c>Hello, world!</c></b></a>\n" - "<text x=\"10\">First</text>\n" - "<text y=\"20\">Second</text>\n" - "</root>", - TDocument::String); - - TXPathContextPtr rootCtxt = xml.Root().CreateXPathContext(); - - // Check Node() - TConstNode b = xml.Root().Node("a/b", false, *rootCtxt); - - // We can use root node context for xpath evaluation in any node - TConstNode c1 = b.Node("c", false, *rootCtxt); + using namespace NXml; + + TDocument xml( + "<?xml version=\"1.0\"?>\n" + "<root>\n" + "<a><b><c>Hello, world!</c></b></a>\n" + "<text x=\"10\">First</text>\n" + "<text y=\"20\">Second</text>\n" + "</root>", + TDocument::String); + + TXPathContextPtr rootCtxt = xml.Root().CreateXPathContext(); + + // Check Node() + TConstNode b = xml.Root().Node("a/b", false, *rootCtxt); + + // We can use root node context for xpath evaluation in any node + TConstNode c1 = b.Node("c", false, *rootCtxt); UNIT_ASSERT_EQUAL(c1.Value<TString>(), "Hello, world!"); - - TXPathContextPtr bCtxt = b.CreateXPathContext(); - TConstNode c2 = b.Node("c", false, *bCtxt); + + TXPathContextPtr bCtxt = b.CreateXPathContext(); + TConstNode c2 = b.Node("c", false, *bCtxt); UNIT_ASSERT_EQUAL(c2.Value<TString>(), "Hello, world!"); - - // Mixing contexts from different documents is forbidden - TDocument otherXml("<root></root>", TDocument::String); - TXPathContextPtr otherCtxt = otherXml.Root().CreateXPathContext(); - UNIT_ASSERT_EXCEPTION(b.Node("c", false, *otherCtxt), yexception); - - // Check Nodes() - TConstNodes texts = xml.Root().Nodes("text", true, *rootCtxt); - UNIT_ASSERT_EQUAL(texts.Size(), 2); - - // Nodes() does't work for non-element nodes - UNIT_ASSERT_EXCEPTION(xml.Root().Nodes("text/@x", true, *rootCtxt), yexception); - - // Check XPath() - TConstNodes ys = xml.Root().XPath("text/@y", true, *rootCtxt); - UNIT_ASSERT_EQUAL(ys.Size(), 1); - UNIT_ASSERT_EQUAL(ys[0].Value<int>(), 20); - } + + // Mixing contexts from different documents is forbidden + TDocument otherXml("<root></root>", TDocument::String); + TXPathContextPtr otherCtxt = otherXml.Root().CreateXPathContext(); + UNIT_ASSERT_EXCEPTION(b.Node("c", false, *otherCtxt), yexception); + + // Check Nodes() + TConstNodes texts = xml.Root().Nodes("text", true, *rootCtxt); + UNIT_ASSERT_EQUAL(texts.Size(), 2); + + // Nodes() does't work for non-element nodes + UNIT_ASSERT_EXCEPTION(xml.Root().Nodes("text/@x", true, *rootCtxt), yexception); + + // Check XPath() + TConstNodes ys = xml.Root().XPath("text/@y", true, *rootCtxt); + UNIT_ASSERT_EQUAL(ys.Size(), 1); + UNIT_ASSERT_EQUAL(ys[0].Value<int>(), 20); + } Y_UNIT_TEST(Html) { using namespace NXml; @@ -291,19 +291,19 @@ Y_UNIT_TEST_SUITE(TestXmlDocument) { videoNode.SaveAsHtml(ss); UNIT_ASSERT_EQUAL(ss.Str(), "<video controls></video>"); } - - Y_UNIT_TEST(Move) { - using namespace NXml; - - TDocument xml1("foo", TDocument::RootName); - xml1.Root().AddChild("bar"); - - UNIT_ASSERT_VALUES_EQUAL(xml1.Root().ToString(), "<foo><bar/></foo>"); - - TDocument xml2 = std::move(xml1); - UNIT_ASSERT_EXCEPTION(xml1.Root(), yexception); - UNIT_ASSERT_VALUES_EQUAL(xml2.Root().ToString(), "<foo><bar/></foo>"); - } + + Y_UNIT_TEST(Move) { + using namespace NXml; + + TDocument xml1("foo", TDocument::RootName); + xml1.Root().AddChild("bar"); + + UNIT_ASSERT_VALUES_EQUAL(xml1.Root().ToString(), "<foo><bar/></foo>"); + + TDocument xml2 = std::move(xml1); + UNIT_ASSERT_EXCEPTION(xml1.Root(), yexception); + UNIT_ASSERT_VALUES_EQUAL(xml2.Root().ToString(), "<foo><bar/></foo>"); + } Y_UNIT_TEST(StringConversion) { using namespace NXml; diff --git a/library/cpp/xml/document/xml-textreader.cpp b/library/cpp/xml/document/xml-textreader.cpp index b946f1fbf2..291c1a0f55 100644 --- a/library/cpp/xml/document/xml-textreader.cpp +++ b/library/cpp/xml/document/xml-textreader.cpp @@ -1,318 +1,318 @@ -#include "xml-textreader.h" - -#include <contrib/libs/libxml/include/libxml/xmlreader.h> - -#include <util/generic/yexception.h> -#include <util/string/strip.h> -#include <util/system/compiler.h> - -namespace NXml { +#include "xml-textreader.h" + +#include <contrib/libs/libxml/include/libxml/xmlreader.h> + +#include <util/generic/yexception.h> +#include <util/string/strip.h> +#include <util/system/compiler.h> + +namespace NXml { TTextReader::TTextReader(IInputStream& stream, const TOptions& options) - : Stream(stream) - , IsError(false) - { + : Stream(stream) + , IsError(false) + { Impl.Reset(xmlReaderForIO(ReadFromInputStreamCallback, nullptr, this, nullptr, nullptr, options.GetMask())); - - if (!Impl) { - ythrow yexception() << "cannot instantiate underlying xmlTextReader structure"; - } - SetupErrorHandler(); - CheckForExceptions(); - } - - TTextReader::~TTextReader() { - } - - bool TTextReader::Read() { - return BoolResult(xmlTextReaderRead(Impl.Get())); - } - + + if (!Impl) { + ythrow yexception() << "cannot instantiate underlying xmlTextReader structure"; + } + SetupErrorHandler(); + CheckForExceptions(); + } + + TTextReader::~TTextReader() { + } + + bool TTextReader::Read() { + return BoolResult(xmlTextReaderRead(Impl.Get())); + } + TString TTextReader::ReadInnerXml() const { - return TempStringOrEmptyResult(xmlTextReaderReadInnerXml(Impl.Get())); - } - + return TempStringOrEmptyResult(xmlTextReaderReadInnerXml(Impl.Get())); + } + TString TTextReader::ReadOuterXml() const { - return TempStringOrEmptyResult(xmlTextReaderReadOuterXml(Impl.Get())); - } - + return TempStringOrEmptyResult(xmlTextReaderReadOuterXml(Impl.Get())); + } + TString TTextReader::ReadString() const { - return TempStringOrEmptyResult(xmlTextReaderReadString(Impl.Get())); - } - - bool TTextReader::ReadAttributeValue() const { - return BoolResult(xmlTextReaderReadAttributeValue(Impl.Get())); - } - - int TTextReader::GetAttributeCount() const { - return IntResult(xmlTextReaderAttributeCount(Impl.Get())); - } - - TStringBuf TTextReader::GetBaseUri() const { - return ConstStringOrEmptyResult(xmlTextReaderConstBaseUri(Impl.Get())); - } - - int TTextReader::GetDepth() const { - return IntResult(xmlTextReaderDepth(Impl.Get())); - } - - bool TTextReader::HasAttributes() const { - return BoolResult(xmlTextReaderHasAttributes(Impl.Get())); - } - - bool TTextReader::HasValue() const { - return BoolResult(xmlTextReaderHasValue(Impl.Get())); - } - - bool TTextReader::IsDefault() const { - return BoolResult(xmlTextReaderIsDefault(Impl.Get())); - } - - bool TTextReader::IsEmptyElement() const { - return BoolResult(xmlTextReaderIsEmptyElement(Impl.Get())); - } - - TStringBuf TTextReader::GetLocalName() const { - return ConstStringOrEmptyResult(xmlTextReaderConstLocalName(Impl.Get())); - } - - TStringBuf TTextReader::GetName() const { - return ConstStringOrEmptyResult(xmlTextReaderConstName(Impl.Get())); - } - - TStringBuf TTextReader::GetNamespaceUri() const { - return ConstStringOrEmptyResult(xmlTextReaderConstNamespaceUri(Impl.Get())); - } - - TTextReader::ENodeType TTextReader::GetNodeType() const { - return static_cast<ENodeType>(IntResult(xmlTextReaderNodeType(Impl.Get()))); - } - - TStringBuf TTextReader::GetPrefix() const { - return ConstStringOrEmptyResult(xmlTextReaderConstPrefix(Impl.Get())); - } - - char TTextReader::GetQuoteChar() const { - return CharResult(xmlTextReaderQuoteChar(Impl.Get())); - } - - TStringBuf TTextReader::GetValue() const { - return ConstStringOrEmptyResult(xmlTextReaderConstValue(Impl.Get())); - } - - TTextReader::EReadState TTextReader::GetReadState() const { - return static_cast<EReadState>(IntResult(xmlTextReaderReadState(Impl.Get()))); - } - - void TTextReader::Close() { - if (xmlTextReaderClose(Impl.Get()) == -1) { - ThrowException(); - } - } - + return TempStringOrEmptyResult(xmlTextReaderReadString(Impl.Get())); + } + + bool TTextReader::ReadAttributeValue() const { + return BoolResult(xmlTextReaderReadAttributeValue(Impl.Get())); + } + + int TTextReader::GetAttributeCount() const { + return IntResult(xmlTextReaderAttributeCount(Impl.Get())); + } + + TStringBuf TTextReader::GetBaseUri() const { + return ConstStringOrEmptyResult(xmlTextReaderConstBaseUri(Impl.Get())); + } + + int TTextReader::GetDepth() const { + return IntResult(xmlTextReaderDepth(Impl.Get())); + } + + bool TTextReader::HasAttributes() const { + return BoolResult(xmlTextReaderHasAttributes(Impl.Get())); + } + + bool TTextReader::HasValue() const { + return BoolResult(xmlTextReaderHasValue(Impl.Get())); + } + + bool TTextReader::IsDefault() const { + return BoolResult(xmlTextReaderIsDefault(Impl.Get())); + } + + bool TTextReader::IsEmptyElement() const { + return BoolResult(xmlTextReaderIsEmptyElement(Impl.Get())); + } + + TStringBuf TTextReader::GetLocalName() const { + return ConstStringOrEmptyResult(xmlTextReaderConstLocalName(Impl.Get())); + } + + TStringBuf TTextReader::GetName() const { + return ConstStringOrEmptyResult(xmlTextReaderConstName(Impl.Get())); + } + + TStringBuf TTextReader::GetNamespaceUri() const { + return ConstStringOrEmptyResult(xmlTextReaderConstNamespaceUri(Impl.Get())); + } + + TTextReader::ENodeType TTextReader::GetNodeType() const { + return static_cast<ENodeType>(IntResult(xmlTextReaderNodeType(Impl.Get()))); + } + + TStringBuf TTextReader::GetPrefix() const { + return ConstStringOrEmptyResult(xmlTextReaderConstPrefix(Impl.Get())); + } + + char TTextReader::GetQuoteChar() const { + return CharResult(xmlTextReaderQuoteChar(Impl.Get())); + } + + TStringBuf TTextReader::GetValue() const { + return ConstStringOrEmptyResult(xmlTextReaderConstValue(Impl.Get())); + } + + TTextReader::EReadState TTextReader::GetReadState() const { + return static_cast<EReadState>(IntResult(xmlTextReaderReadState(Impl.Get()))); + } + + void TTextReader::Close() { + if (xmlTextReaderClose(Impl.Get()) == -1) { + ThrowException(); + } + } + TString TTextReader::GetAttribute(int number) const { - return TempStringResult(xmlTextReaderGetAttributeNo(Impl.Get(), number)); - } - + return TempStringResult(xmlTextReaderGetAttributeNo(Impl.Get(), number)); + } + TString TTextReader::GetAttribute(TZtStringBuf name) const { return TempStringResult(xmlTextReaderGetAttribute(Impl.Get(), XMLCHAR(name.data()))); - } - + } + TString TTextReader::GetAttribute(TZtStringBuf localName, TZtStringBuf nsUri) const { return TempStringResult(xmlTextReaderGetAttributeNs(Impl.Get(), XMLCHAR(localName.data()), XMLCHAR(nsUri.data()))); - } - + } + TString TTextReader::LookupNamespace(TZtStringBuf prefix) const { return TempStringResult(xmlTextReaderLookupNamespace(Impl.Get(), XMLCHAR(prefix.data()))); - } - - bool TTextReader::MoveToAttribute(int number) { - return BoolResult(xmlTextReaderMoveToAttributeNo(Impl.Get(), number)); - } - + } + + bool TTextReader::MoveToAttribute(int number) { + return BoolResult(xmlTextReaderMoveToAttributeNo(Impl.Get(), number)); + } + bool TTextReader::MoveToAttribute(TZtStringBuf name) { return BoolResult(xmlTextReaderMoveToAttribute(Impl.Get(), XMLCHAR(name.data()))); - } - + } + bool TTextReader::MoveToAttribute(TZtStringBuf localName, TZtStringBuf nsUri) { return BoolResult(xmlTextReaderMoveToAttributeNs(Impl.Get(), XMLCHAR(localName.data()), XMLCHAR(nsUri.data()))); - } - - bool TTextReader::MoveToFirstAttribute() { - return BoolResult(xmlTextReaderMoveToFirstAttribute(Impl.Get())); - } - - bool TTextReader::MoveToNextAttribute() { - return BoolResult(xmlTextReaderMoveToNextAttribute(Impl.Get())); - } - - bool TTextReader::MoveToElement() { - return BoolResult(xmlTextReaderMoveToElement(Impl.Get())); - } - - TConstNode TTextReader::Expand() const { - const xmlNodePtr node = xmlTextReaderExpand(Impl.Get()); - if (node == nullptr) { - ThrowException(); - } - return TConstNode(TNode(node->doc, node)); - } - - bool TTextReader::Next() { - return BoolResult(xmlTextReaderNext(Impl.Get())); - } - - bool TTextReader::IsValid() const { - return BoolResult(xmlTextReaderIsValid(Impl.Get())); - } - - // Callback for xmlReaderForIO() to read more data. + } + + bool TTextReader::MoveToFirstAttribute() { + return BoolResult(xmlTextReaderMoveToFirstAttribute(Impl.Get())); + } + + bool TTextReader::MoveToNextAttribute() { + return BoolResult(xmlTextReaderMoveToNextAttribute(Impl.Get())); + } + + bool TTextReader::MoveToElement() { + return BoolResult(xmlTextReaderMoveToElement(Impl.Get())); + } + + TConstNode TTextReader::Expand() const { + const xmlNodePtr node = xmlTextReaderExpand(Impl.Get()); + if (node == nullptr) { + ThrowException(); + } + return TConstNode(TNode(node->doc, node)); + } + + bool TTextReader::Next() { + return BoolResult(xmlTextReaderNext(Impl.Get())); + } + + bool TTextReader::IsValid() const { + return BoolResult(xmlTextReaderIsValid(Impl.Get())); + } + + // Callback for xmlReaderForIO() to read more data. // It is almost "noexcept" (std::bad_alloc may happen when saving exception message to new TString). - // Waiting for std::exception_ptr and std::rethrow_exception from C++11 in Arcadia to make it really "noexcept". - int TTextReader::ReadFromInputStreamCallback(void* context, char* buffer, int len) { + // Waiting for std::exception_ptr and std::rethrow_exception from C++11 in Arcadia to make it really "noexcept". + int TTextReader::ReadFromInputStreamCallback(void* context, char* buffer, int len) { Y_ASSERT(len >= 0); - TTextReader* reader = static_cast<TTextReader*>(context); - - int result = -1; - + TTextReader* reader = static_cast<TTextReader*>(context); + + int result = -1; + // Exception may be thrown by IInputStream::Read(). - // It is caught unconditionally because exceptions cannot safely pass through libxml2 plain C code - // (no destructors, no RAII, raw pointers, so in case of stack unwinding some memory gets leaked). - - try { - result = reader->Stream.Read(buffer, len); - } catch (const yexception& ex) { - reader->LogError() << "read from input stream failed: " << ex; - } catch (...) { - reader->LogError() << "read from input stream failed"; - } - - return result; - } - - void TTextReader::OnLibxmlError(void* arg, const char* msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator) { - TTextReader* reader = static_cast<TTextReader*>(arg); + // It is caught unconditionally because exceptions cannot safely pass through libxml2 plain C code + // (no destructors, no RAII, raw pointers, so in case of stack unwinding some memory gets leaked). + + try { + result = reader->Stream.Read(buffer, len); + } catch (const yexception& ex) { + reader->LogError() << "read from input stream failed: " << ex; + } catch (...) { + reader->LogError() << "read from input stream failed"; + } + + return result; + } + + void TTextReader::OnLibxmlError(void* arg, const char* msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator) { + TTextReader* reader = static_cast<TTextReader*>(arg); Y_ASSERT(reader != nullptr); - - TStringStream& out = reader->LogError(); - - if (severity == XML_PARSER_SEVERITY_ERROR) { - out << "libxml parse error"; - } else if (severity == XML_PARSER_SEVERITY_VALIDITY_ERROR) { - out << "libxml validity error"; - } else { - out << "libxml error"; - } - - if (locator != nullptr) { - const int line = xmlTextReaderLocatorLineNumber(locator); - const TCharPtr baseUri = xmlTextReaderLocatorBaseURI(locator); - out << " ("; - if (line != -1) { - out << "at line " << line; - if (baseUri) { - out << ", "; - } - } - if (baseUri) { - out << "base URI " << CAST2CHAR(baseUri.Get()); - } - out << ")"; - } - - TStringBuf message = (msg != nullptr) ? msg : "unknown"; - message = StripStringRight(message); // remove trailing \n that is added by libxml - if (!message.empty()) { - out << ": " << message; - } - } - - void TTextReader::SetupErrorHandler() { - xmlTextReaderErrorFunc func = nullptr; - void* arg = nullptr; - - // We respect any other error handlers already set up: - xmlTextReaderGetErrorHandler(Impl.Get(), &func, &arg); - if (!func) { - func = TTextReader::OnLibxmlError; - xmlTextReaderSetErrorHandler(Impl.Get(), func, this); - } - } - - TStringStream& TTextReader::LogError() const { - if (IsError) { // maybe there are previous errors - ErrorBuffer << Endl; - } - IsError = true; - return ErrorBuffer; - } - - void TTextReader::CheckForExceptions() const { + + TStringStream& out = reader->LogError(); + + if (severity == XML_PARSER_SEVERITY_ERROR) { + out << "libxml parse error"; + } else if (severity == XML_PARSER_SEVERITY_VALIDITY_ERROR) { + out << "libxml validity error"; + } else { + out << "libxml error"; + } + + if (locator != nullptr) { + const int line = xmlTextReaderLocatorLineNumber(locator); + const TCharPtr baseUri = xmlTextReaderLocatorBaseURI(locator); + out << " ("; + if (line != -1) { + out << "at line " << line; + if (baseUri) { + out << ", "; + } + } + if (baseUri) { + out << "base URI " << CAST2CHAR(baseUri.Get()); + } + out << ")"; + } + + TStringBuf message = (msg != nullptr) ? msg : "unknown"; + message = StripStringRight(message); // remove trailing \n that is added by libxml + if (!message.empty()) { + out << ": " << message; + } + } + + void TTextReader::SetupErrorHandler() { + xmlTextReaderErrorFunc func = nullptr; + void* arg = nullptr; + + // We respect any other error handlers already set up: + xmlTextReaderGetErrorHandler(Impl.Get(), &func, &arg); + if (!func) { + func = TTextReader::OnLibxmlError; + xmlTextReaderSetErrorHandler(Impl.Get(), func, this); + } + } + + TStringStream& TTextReader::LogError() const { + if (IsError) { // maybe there are previous errors + ErrorBuffer << Endl; + } + IsError = true; + return ErrorBuffer; + } + + void TTextReader::CheckForExceptions() const { if (Y_LIKELY(!IsError)) { - return; - } - + return; + } + const TString message = ErrorBuffer.Str(); - ErrorBuffer.clear(); - IsError = false; - - ythrow yexception() << message; - } - - void TTextReader::ThrowException() const { - CheckForExceptions(); - // Probably CheckForExceptions() would throw an exception with more verbose message. As the last resort - // (we do not even know the name of the failed libxml function, but it's possible to deduce it from stacktrace): - ythrow yexception() << "libxml function returned error exit code"; - } - - bool TTextReader::BoolResult(int value) const { + ErrorBuffer.clear(); + IsError = false; + + ythrow yexception() << message; + } + + void TTextReader::ThrowException() const { + CheckForExceptions(); + // Probably CheckForExceptions() would throw an exception with more verbose message. As the last resort + // (we do not even know the name of the failed libxml function, but it's possible to deduce it from stacktrace): + ythrow yexception() << "libxml function returned error exit code"; + } + + bool TTextReader::BoolResult(int value) const { if (Y_UNLIKELY(value == -1)) { - ThrowException(); - } - return (value != 0); - } - - int TTextReader::IntResult(int value) const { + ThrowException(); + } + return (value != 0); + } + + int TTextReader::IntResult(int value) const { if (Y_UNLIKELY(value == -1)) { - ThrowException(); - } - return value; - } - - char TTextReader::CharResult(int value) const { + ThrowException(); + } + return value; + } + + char TTextReader::CharResult(int value) const { if (Y_UNLIKELY(value == -1)) { - ThrowException(); - } - return static_cast<char>(value); - } - - TStringBuf TTextReader::ConstStringResult(const xmlChar* value) const { + ThrowException(); + } + return static_cast<char>(value); + } + + TStringBuf TTextReader::ConstStringResult(const xmlChar* value) const { if (Y_UNLIKELY(value == nullptr)) { - ThrowException(); - } - return CAST2CHAR(value); - } - - TStringBuf TTextReader::ConstStringOrEmptyResult(const xmlChar* value) const { - CheckForExceptions(); - return (value != nullptr) ? TStringBuf(CAST2CHAR(value)) : TStringBuf(); - } - + ThrowException(); + } + return CAST2CHAR(value); + } + + TStringBuf TTextReader::ConstStringOrEmptyResult(const xmlChar* value) const { + CheckForExceptions(); + return (value != nullptr) ? TStringBuf(CAST2CHAR(value)) : TStringBuf(); + } + TString TTextReader::TempStringResult(TCharPtr value) const { if (Y_UNLIKELY(value == nullptr)) { - ThrowException(); - } + ThrowException(); + } return TString(CAST2CHAR(value.Get())); - } - + } + TString TTextReader::TempStringOrEmptyResult(TCharPtr value) const { - CheckForExceptions(); + CheckForExceptions(); return (value != nullptr) ? TString(CAST2CHAR(value.Get())) : TString(); - } - - struct TTextReader::TDeleter { - static inline void Destroy(xmlTextReaderPtr handle) { - xmlFreeTextReader(handle); - } - }; + } + + struct TTextReader::TDeleter { + static inline void Destroy(xmlTextReaderPtr handle) { + xmlFreeTextReader(handle); + } + }; } diff --git a/library/cpp/xml/document/xml-textreader.h b/library/cpp/xml/document/xml-textreader.h index ab4c329d26..9e0b8be6ea 100644 --- a/library/cpp/xml/document/xml-textreader.h +++ b/library/cpp/xml/document/xml-textreader.h @@ -1,325 +1,325 @@ -#pragma once - -#include "xml-document.h" +#pragma once + +#include "xml-document.h" #include "xml-options.h" - -#include <contrib/libs/libxml/include/libxml/xmlreader.h> - + +#include <contrib/libs/libxml/include/libxml/xmlreader.h> + #include <library/cpp/string_utils/ztstrbuf/ztstrbuf.h> -#include <util/generic/noncopyable.h> -#include <util/generic/ptr.h> -#include <util/generic/strbuf.h> +#include <util/generic/noncopyable.h> +#include <util/generic/ptr.h> +#include <util/generic/strbuf.h> #include <util/generic/string.h> #include <functional> -#include <util/stream/input.h> -#include <util/stream/str.h> - -namespace NXml { - /** - * TextReader Parser - * - * API of the XML streaming API based on C# interfaces. - * Provides fast, non-cached, forward-only access to XML data. - * - * Like the SAX parser, the TextReader parser is suitable for sequential - * parsing, but instead of implementing handlers for specific parts of the - * document, it allows you to detect the current node type, process the node - * accordingly, and skip forward in the document as much as necessary. - * - * Unlike the DOM parser, you may not move backwards in the XML document. - * And unlike the SAX parser, you must not waste time processing nodes that do not - * interest you. - * - * All methods are on the single parser instance, but their result depends on the current context. - * For instance, use Read() to move to the next node, and MoveToElement() to navigate to child nodes. - * These methods will return false when no more nodes are available. Then use - * methods such as GetName() and GetValue() to examine the elements and their attributes. - * - * This wrapper is inspired by TextReader from libxml++. - */ - - class TTextReader: private TNonCopyable { - public: - // strongly-typed alias for enum from xmlreader.h - enum class ENodeType : int { - // clang-format off - Attribute = XML_READER_TYPE_ATTRIBUTE, - CDATA = XML_READER_TYPE_CDATA, - Comment = XML_READER_TYPE_COMMENT, - Document = XML_READER_TYPE_DOCUMENT, - DocumentFragment = XML_READER_TYPE_DOCUMENT_FRAGMENT, - DocumentType = XML_READER_TYPE_DOCUMENT_TYPE, - Element = XML_READER_TYPE_ELEMENT, - EndElement = XML_READER_TYPE_END_ELEMENT, - EndEntity = XML_READER_TYPE_END_ENTITY, - Entity = XML_READER_TYPE_ENTITY, - EntityReference = XML_READER_TYPE_ENTITY_REFERENCE, - None = XML_READER_TYPE_NONE, - Notation = XML_READER_TYPE_NOTATION, - ProcessingInstruction = XML_READER_TYPE_PROCESSING_INSTRUCTION, - SignificantWhitespace = XML_READER_TYPE_SIGNIFICANT_WHITESPACE, - Text = XML_READER_TYPE_TEXT, - Whitespace = XML_READER_TYPE_WHITESPACE, - XmlDeclaration = XML_READER_TYPE_XML_DECLARATION, - // clang-format on - }; - - enum class EReadState : int { - // clang-format off - Closed = XML_TEXTREADER_MODE_CLOSED, - EndOfFile = XML_TEXTREADER_MODE_EOF, - Error = XML_TEXTREADER_MODE_ERROR, - Initial = XML_TEXTREADER_MODE_INITIAL, - Interactive = XML_TEXTREADER_MODE_INTERACTIVE, - Reading = XML_TEXTREADER_MODE_READING, - // clang-format on - }; - - public: +#include <util/stream/input.h> +#include <util/stream/str.h> + +namespace NXml { + /** + * TextReader Parser + * + * API of the XML streaming API based on C# interfaces. + * Provides fast, non-cached, forward-only access to XML data. + * + * Like the SAX parser, the TextReader parser is suitable for sequential + * parsing, but instead of implementing handlers for specific parts of the + * document, it allows you to detect the current node type, process the node + * accordingly, and skip forward in the document as much as necessary. + * + * Unlike the DOM parser, you may not move backwards in the XML document. + * And unlike the SAX parser, you must not waste time processing nodes that do not + * interest you. + * + * All methods are on the single parser instance, but their result depends on the current context. + * For instance, use Read() to move to the next node, and MoveToElement() to navigate to child nodes. + * These methods will return false when no more nodes are available. Then use + * methods such as GetName() and GetValue() to examine the elements and their attributes. + * + * This wrapper is inspired by TextReader from libxml++. + */ + + class TTextReader: private TNonCopyable { + public: + // strongly-typed alias for enum from xmlreader.h + enum class ENodeType : int { + // clang-format off + Attribute = XML_READER_TYPE_ATTRIBUTE, + CDATA = XML_READER_TYPE_CDATA, + Comment = XML_READER_TYPE_COMMENT, + Document = XML_READER_TYPE_DOCUMENT, + DocumentFragment = XML_READER_TYPE_DOCUMENT_FRAGMENT, + DocumentType = XML_READER_TYPE_DOCUMENT_TYPE, + Element = XML_READER_TYPE_ELEMENT, + EndElement = XML_READER_TYPE_END_ELEMENT, + EndEntity = XML_READER_TYPE_END_ENTITY, + Entity = XML_READER_TYPE_ENTITY, + EntityReference = XML_READER_TYPE_ENTITY_REFERENCE, + None = XML_READER_TYPE_NONE, + Notation = XML_READER_TYPE_NOTATION, + ProcessingInstruction = XML_READER_TYPE_PROCESSING_INSTRUCTION, + SignificantWhitespace = XML_READER_TYPE_SIGNIFICANT_WHITESPACE, + Text = XML_READER_TYPE_TEXT, + Whitespace = XML_READER_TYPE_WHITESPACE, + XmlDeclaration = XML_READER_TYPE_XML_DECLARATION, + // clang-format on + }; + + enum class EReadState : int { + // clang-format off + Closed = XML_TEXTREADER_MODE_CLOSED, + EndOfFile = XML_TEXTREADER_MODE_EOF, + Error = XML_TEXTREADER_MODE_ERROR, + Initial = XML_TEXTREADER_MODE_INITIAL, + Interactive = XML_TEXTREADER_MODE_INTERACTIVE, + Reading = XML_TEXTREADER_MODE_READING, + // clang-format on + }; + + public: TTextReader(IInputStream& stream, const TOptions& options = TOptions()); - ~TTextReader(); - - /** - * Moves the position of the current instance to the next node in the stream, exposing its properties. - * @return true if the node was read successfully, false if there are no more nodes to read - */ - bool Read(); - - /** - * Reads the contents of the current node, including child nodes and markup. - * @return A string containing the XML content, or an empty string - * if the current node is neither an element nor attribute, or has no child nodes - */ + ~TTextReader(); + + /** + * Moves the position of the current instance to the next node in the stream, exposing its properties. + * @return true if the node was read successfully, false if there are no more nodes to read + */ + bool Read(); + + /** + * Reads the contents of the current node, including child nodes and markup. + * @return A string containing the XML content, or an empty string + * if the current node is neither an element nor attribute, or has no child nodes + */ TString ReadInnerXml() const; - - /** - * Reads the current node and its contents, including child nodes and markup. - * @return A string containing the XML content, or an empty string - * if the current node is neither an element nor attribute - */ + + /** + * Reads the current node and its contents, including child nodes and markup. + * @return A string containing the XML content, or an empty string + * if the current node is neither an element nor attribute + */ TString ReadOuterXml() const; - - /** - * Reads the contents of an element or a text node as a string. - * @return A string containing the contents of the Element or Text node, - * or an empty string if the reader is positioned on any other type of node - */ + + /** + * Reads the contents of an element or a text node as a string. + * @return A string containing the contents of the Element or Text node, + * or an empty string if the reader is positioned on any other type of node + */ TString ReadString() const; - - /** - * Parses an attribute value into one or more Text and EntityReference nodes. - * @return A bool where true indicates the attribute value was parsed, - * and false indicates the reader was not positioned on an attribute node - * or all the attribute values have been read - */ - bool ReadAttributeValue() const; - - /** - * Gets the number of attributes on the current node. - * @return The number of attributes on the current node, or zero if the current node - * does not support attributes - */ - int GetAttributeCount() const; - - /** - * Gets the base Uniform Resource Identifier (URI) of the current node. - * @return The base URI of the current node or an empty string if not available - */ - TStringBuf GetBaseUri() const; - - /** - * Gets the depth of the current node in the XML document. - * @return The depth of the current node in the XML document - */ - int GetDepth() const; - - /** - * Gets a value indicating whether the current node has any attributes. - * @return true if the current has attributes, false otherwise - */ - bool HasAttributes() const; - - /** - * Whether the node can have a text value. - * @return true if the current node can have an associated text value, false otherwise - */ - bool HasValue() const; - - /** - * Whether an Attribute node was generated from the default value defined in the DTD or schema. - * @return true if defaulted, false otherwise - */ - bool IsDefault() const; - - /** - * Check if the current node is empty. - * @return true if empty, false otherwise - */ - bool IsEmptyElement() const; - - /** - * The local name of the node. - * @return the local name or empty string if not available - */ - TStringBuf GetLocalName() const; - - /** - * The qualified name of the node, equal to Prefix:LocalName. - * @return the name or empty string if not available - */ - TStringBuf GetName() const; - - /** - * The URI defining the namespace associated with the node. - * @return the namespace URI or empty string if not available - */ - TStringBuf GetNamespaceUri() const; - - /** - * Get the node type of the current node. - * @return the ENodeType of the current node - */ - ENodeType GetNodeType() const; - - /** - * Get the namespace prefix associated with the current node. - * @return the namespace prefix, or an empty string if not available - */ - TStringBuf GetPrefix() const; - - /** - * Get the quotation mark character used to enclose the value of an attribute. - * @return " or ' - */ - char GetQuoteChar() const; - - /** - * Provides the text value of the node if present. - * @return the string or empty if not available - */ - TStringBuf GetValue() const; - - /** - * Gets the read state of the reader. - * @return the state value - */ - EReadState GetReadState() const; - - /** - * This method releases any resources allocated by the current instance - * changes the state to Closed and close any underlying input. - */ - void Close(); - - /** - * Provides the value of the attribute with the specified index relative to the containing element. - * @param number the zero-based index of the attribute relative to the containing element - */ + + /** + * Parses an attribute value into one or more Text and EntityReference nodes. + * @return A bool where true indicates the attribute value was parsed, + * and false indicates the reader was not positioned on an attribute node + * or all the attribute values have been read + */ + bool ReadAttributeValue() const; + + /** + * Gets the number of attributes on the current node. + * @return The number of attributes on the current node, or zero if the current node + * does not support attributes + */ + int GetAttributeCount() const; + + /** + * Gets the base Uniform Resource Identifier (URI) of the current node. + * @return The base URI of the current node or an empty string if not available + */ + TStringBuf GetBaseUri() const; + + /** + * Gets the depth of the current node in the XML document. + * @return The depth of the current node in the XML document + */ + int GetDepth() const; + + /** + * Gets a value indicating whether the current node has any attributes. + * @return true if the current has attributes, false otherwise + */ + bool HasAttributes() const; + + /** + * Whether the node can have a text value. + * @return true if the current node can have an associated text value, false otherwise + */ + bool HasValue() const; + + /** + * Whether an Attribute node was generated from the default value defined in the DTD or schema. + * @return true if defaulted, false otherwise + */ + bool IsDefault() const; + + /** + * Check if the current node is empty. + * @return true if empty, false otherwise + */ + bool IsEmptyElement() const; + + /** + * The local name of the node. + * @return the local name or empty string if not available + */ + TStringBuf GetLocalName() const; + + /** + * The qualified name of the node, equal to Prefix:LocalName. + * @return the name or empty string if not available + */ + TStringBuf GetName() const; + + /** + * The URI defining the namespace associated with the node. + * @return the namespace URI or empty string if not available + */ + TStringBuf GetNamespaceUri() const; + + /** + * Get the node type of the current node. + * @return the ENodeType of the current node + */ + ENodeType GetNodeType() const; + + /** + * Get the namespace prefix associated with the current node. + * @return the namespace prefix, or an empty string if not available + */ + TStringBuf GetPrefix() const; + + /** + * Get the quotation mark character used to enclose the value of an attribute. + * @return " or ' + */ + char GetQuoteChar() const; + + /** + * Provides the text value of the node if present. + * @return the string or empty if not available + */ + TStringBuf GetValue() const; + + /** + * Gets the read state of the reader. + * @return the state value + */ + EReadState GetReadState() const; + + /** + * This method releases any resources allocated by the current instance + * changes the state to Closed and close any underlying input. + */ + void Close(); + + /** + * Provides the value of the attribute with the specified index relative to the containing element. + * @param number the zero-based index of the attribute relative to the containing element + */ TString GetAttribute(int number) const; - - /** - * Provides the value of the attribute with the specified qualified name. - * @param name the qualified name of the attribute - */ + + /** + * Provides the value of the attribute with the specified qualified name. + * @param name the qualified name of the attribute + */ TString GetAttribute(TZtStringBuf name) const; - - /** - * Provides the value of the specified attribute. - * @param localName the local name of the attribute - * @param nsUri the namespace URI of the attribute - */ + + /** + * Provides the value of the specified attribute. + * @param localName the local name of the attribute + * @param nsUri the namespace URI of the attribute + */ TString GetAttribute(TZtStringBuf localName, TZtStringBuf nsUri) const; - - /** - * Resolves a namespace prefix in the scope of the current element. - * @param prefix the prefix whose namespace URI is to be resolved. To return the default namespace, specify empty string. - * @return a string containing the namespace URI to which the prefix maps. - */ + + /** + * Resolves a namespace prefix in the scope of the current element. + * @param prefix the prefix whose namespace URI is to be resolved. To return the default namespace, specify empty string. + * @return a string containing the namespace URI to which the prefix maps. + */ TString LookupNamespace(TZtStringBuf prefix) const; - - /** - * Moves the position of the current instance to the attribute with the specified index relative to the containing element. - * @param number the zero-based index of the attribute relative to the containing element - * @return true in case of success, false if not found - */ - bool MoveToAttribute(int number); - - /** - * Moves the position of the current instance to the attribute with the specified qualified name. - * @param name the qualified name of the attribute - * @return true in case of success, false if not found - */ + + /** + * Moves the position of the current instance to the attribute with the specified index relative to the containing element. + * @param number the zero-based index of the attribute relative to the containing element + * @return true in case of success, false if not found + */ + bool MoveToAttribute(int number); + + /** + * Moves the position of the current instance to the attribute with the specified qualified name. + * @param name the qualified name of the attribute + * @return true in case of success, false if not found + */ bool MoveToAttribute(TZtStringBuf name); - - /** - * Moves the position of the current instance to the attribute with the specified local name and namespace URI. - * @param localName the local name of the attribute - * @param nsUri the namespace URI of the attribute - * @return true in case of success, false if not found - */ + + /** + * Moves the position of the current instance to the attribute with the specified local name and namespace URI. + * @param localName the local name of the attribute + * @param nsUri the namespace URI of the attribute + * @return true in case of success, false if not found + */ bool MoveToAttribute(TZtStringBuf localName, TZtStringBuf nsUri); - - /** - * Moves the position of the current instance to the first attribute associated with the current node. - * @return true in case of success, false if not found - */ - bool MoveToFirstAttribute(); - - /** - * Moves the position of the current instance to the next attribute associated with the current node. - * @return true in case of success, false if not found - */ - bool MoveToNextAttribute(); - - /** - * Moves the position of the current instance to the node that contains the current Attribute node. - * @return true in case of success, false if not found - */ - bool MoveToElement(); - - /** - * Reads the contents of the current node and the full subtree. It then makes the subtree available until the next Read() call. - */ - TConstNode Expand() const; - - /** - * Skip to the node following the current one in document order while avoiding the subtree if any. - * @return true if the node was read successfully, false if there is no more nodes to read - */ - bool Next(); - - /** - * Retrieve the validity status from the parser context. - */ - bool IsValid() const; - - private: - static int ReadFromInputStreamCallback(void* context, char* buffer, int len); - static void OnLibxmlError(void* arg, const char* msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator); - - void SetupErrorHandler(); - TStringStream& LogError() const; - void CheckForExceptions() const; - void ThrowException() const; - - // helpers that check return codes of C functions from libxml - bool BoolResult(int value) const; - int IntResult(int value) const; - char CharResult(int value) const; - TStringBuf ConstStringResult(const xmlChar* value) const; - TStringBuf ConstStringOrEmptyResult(const xmlChar* value) const; + + /** + * Moves the position of the current instance to the first attribute associated with the current node. + * @return true in case of success, false if not found + */ + bool MoveToFirstAttribute(); + + /** + * Moves the position of the current instance to the next attribute associated with the current node. + * @return true in case of success, false if not found + */ + bool MoveToNextAttribute(); + + /** + * Moves the position of the current instance to the node that contains the current Attribute node. + * @return true in case of success, false if not found + */ + bool MoveToElement(); + + /** + * Reads the contents of the current node and the full subtree. It then makes the subtree available until the next Read() call. + */ + TConstNode Expand() const; + + /** + * Skip to the node following the current one in document order while avoiding the subtree if any. + * @return true if the node was read successfully, false if there is no more nodes to read + */ + bool Next(); + + /** + * Retrieve the validity status from the parser context. + */ + bool IsValid() const; + + private: + static int ReadFromInputStreamCallback(void* context, char* buffer, int len); + static void OnLibxmlError(void* arg, const char* msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator); + + void SetupErrorHandler(); + TStringStream& LogError() const; + void CheckForExceptions() const; + void ThrowException() const; + + // helpers that check return codes of C functions from libxml + bool BoolResult(int value) const; + int IntResult(int value) const; + char CharResult(int value) const; + TStringBuf ConstStringResult(const xmlChar* value) const; + TStringBuf ConstStringOrEmptyResult(const xmlChar* value) const; TString TempStringResult(TCharPtr value) const; TString TempStringOrEmptyResult(TCharPtr value) const; - - private: + + private: IInputStream& Stream; - - mutable bool IsError; - mutable TStringStream ErrorBuffer; - - struct TDeleter; - THolder<xmlTextReader, TDeleter> Impl; - }; - + + mutable bool IsError; + mutable TStringStream ErrorBuffer; + + struct TDeleter; + THolder<xmlTextReader, TDeleter> Impl; + }; + } diff --git a/library/cpp/xml/document/xml-textreader_ut.cpp b/library/cpp/xml/document/xml-textreader_ut.cpp index 6232dfe47e..9f54523fef 100644 --- a/library/cpp/xml/document/xml-textreader_ut.cpp +++ b/library/cpp/xml/document/xml-textreader_ut.cpp @@ -1,34 +1,34 @@ -#include "xml-textreader.h" - +#include "xml-textreader.h" + #include <library/cpp/testing/unittest/registar.h> - -#include <util/generic/hash.h> -#include <util/generic/vector.h> -#include <util/string/join.h> - -namespace { - /** - * Simple wrapper around the xmlTextReader wrapper - */ + +#include <util/generic/hash.h> +#include <util/generic/vector.h> +#include <util/string/join.h> + +namespace { + /** + * Simple wrapper around the xmlTextReader wrapper + */ void ParseXml(const TString& xmlData, std::function<void(NXml::TConstNode)> nodeHandlerFunc, const TString& localName, const TString& namespaceUri = TString()) { - TStringInput in(xmlData); - NXml::TTextReader reader(in); - - while (reader.Read()) { - if (reader.GetNodeType() == NXml::TTextReader::ENodeType::Element && - reader.GetLocalName() == localName && + TStringInput in(xmlData); + NXml::TTextReader reader(in); + + while (reader.Read()) { + if (reader.GetNodeType() == NXml::TTextReader::ENodeType::Element && + reader.GetLocalName() == localName && reader.GetNamespaceUri() == namespaceUri) { - const NXml::TConstNode node = reader.Expand(); - nodeHandlerFunc(node); - } - } - } + const NXml::TConstNode node = reader.Expand(); + nodeHandlerFunc(node); + } + } + } } - + Y_UNIT_TEST_SUITE(TestXmlTextReader) { Y_UNIT_TEST(BasicExample) { const TString xml = "<?xml version=\"1.0\"?>\n" @@ -40,73 +40,73 @@ Y_UNIT_TEST_SUITE(TestXmlTextReader) { " <child_of_child>Some content : -)</child_of_child>\n" " </examplechild>\n" "</example>\n"; - - TStringInput input(xml); - NXml::TTextReader reader(input); - - using ENT = NXml::TTextReader::ENodeType; - - struct TItem { - int Depth; - ENT Type; + + TStringInput input(xml); + NXml::TTextReader reader(input); + + using ENT = NXml::TTextReader::ENodeType; + + struct TItem { + int Depth; + ENT Type; TString Name; TString Attrs; TString Value; - }; - + }; + TVector<TItem> found; TVector<TString> msgs; - - while (reader.Read()) { - // dump attributes as "k1: v1, k2: v2, ..." + + while (reader.Read()) { + // dump attributes as "k1: v1, k2: v2, ..." TVector<TString> kv; - if (reader.HasAttributes()) { - reader.MoveToFirstAttribute(); - do { + if (reader.HasAttributes()) { + reader.MoveToFirstAttribute(); + do { kv.push_back(TString::Join(reader.GetName(), ": ", reader.GetValue())); - } while (reader.MoveToNextAttribute()); - reader.MoveToElement(); - } - - found.push_back(TItem{ - reader.GetDepth(), - reader.GetNodeType(), + } while (reader.MoveToNextAttribute()); + reader.MoveToElement(); + } + + found.push_back(TItem{ + reader.GetDepth(), + reader.GetNodeType(), TString(reader.GetName()), - JoinSeq(", ", kv), + JoinSeq(", ", kv), reader.HasValue() ? TString(reader.GetValue()) : TString(), - }); - } - + }); + } + const TVector<TItem> expected = { - TItem{0, ENT::Element, "example", "toto: 1", ""}, - TItem{1, ENT::SignificantWhitespace, "#text", "", "\n "}, - TItem{1, ENT::Element, "examplechild", "id: 1", ""}, - TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, - TItem{2, ENT::Element, "child_of_child", "", ""}, - TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, - TItem{1, ENT::EndElement, "examplechild", "id: 1", ""}, - TItem{1, ENT::SignificantWhitespace, "#text", "", "\n "}, - TItem{1, ENT::Element, "examplechild", "id: 2, toto: 3", ""}, - TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, - TItem{2, ENT::Element, "child_of_child", "", ""}, - TItem{3, ENT::Text, "#text", "", "Some content : -)"}, - TItem{2, ENT::EndElement, "child_of_child", "", ""}, - TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, - TItem{1, ENT::EndElement, "examplechild", "id: 2, toto: 3", ""}, - TItem{1, ENT::SignificantWhitespace, "#text", "", "\n"}, + TItem{0, ENT::Element, "example", "toto: 1", ""}, + TItem{1, ENT::SignificantWhitespace, "#text", "", "\n "}, + TItem{1, ENT::Element, "examplechild", "id: 1", ""}, + TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, + TItem{2, ENT::Element, "child_of_child", "", ""}, + TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, + TItem{1, ENT::EndElement, "examplechild", "id: 1", ""}, + TItem{1, ENT::SignificantWhitespace, "#text", "", "\n "}, + TItem{1, ENT::Element, "examplechild", "id: 2, toto: 3", ""}, + TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, + TItem{2, ENT::Element, "child_of_child", "", ""}, + TItem{3, ENT::Text, "#text", "", "Some content : -)"}, + TItem{2, ENT::EndElement, "child_of_child", "", ""}, + TItem{2, ENT::SignificantWhitespace, "#text", "", "\n "}, + TItem{1, ENT::EndElement, "examplechild", "id: 2, toto: 3", ""}, + TItem{1, ENT::SignificantWhitespace, "#text", "", "\n"}, TItem{0, ENT::EndElement, "example", "toto: 1", ""}}; - - UNIT_ASSERT_VALUES_EQUAL(found.size(), expected.size()); - - for (size_t i = 0; i < expected.size(); ++i) { - UNIT_ASSERT_VALUES_EQUAL_C(found[i].Depth, expected[i].Depth, "line " << i); - UNIT_ASSERT_EQUAL_C(found[i].Type, expected[i].Type, "line " << i); - UNIT_ASSERT_VALUES_EQUAL_C(found[i].Name, expected[i].Name, "line " << i); - UNIT_ASSERT_VALUES_EQUAL_C(found[i].Attrs, expected[i].Attrs, "line " << i); - UNIT_ASSERT_VALUES_EQUAL_C(found[i].Value, expected[i].Value, "line " << i); - } - } - + + UNIT_ASSERT_VALUES_EQUAL(found.size(), expected.size()); + + for (size_t i = 0; i < expected.size(); ++i) { + UNIT_ASSERT_VALUES_EQUAL_C(found[i].Depth, expected[i].Depth, "line " << i); + UNIT_ASSERT_EQUAL_C(found[i].Type, expected[i].Type, "line " << i); + UNIT_ASSERT_VALUES_EQUAL_C(found[i].Name, expected[i].Name, "line " << i); + UNIT_ASSERT_VALUES_EQUAL_C(found[i].Attrs, expected[i].Attrs, "line " << i); + UNIT_ASSERT_VALUES_EQUAL_C(found[i].Value, expected[i].Value, "line " << i); + } + } + const TString GEODATA = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<root>" "" @@ -133,158 +133,158 @@ Y_UNIT_TEST_SUITE(TestXmlTextReader) { " </country>" "" "</root>"; - + Y_UNIT_TEST(ParseXmlSimple) { - struct TCountry { + struct TCountry { TString Name; TVector<TString> Cities; - }; - + }; + THashMap<int, TCountry> data; - - auto handler = [&data](NXml::TConstNode node) { - const int id = node.Attr<int>("id"); - - TCountry& c = data[id]; - + + auto handler = [&data](NXml::TConstNode node) { + const int id = node.Attr<int>("id"); + + TCountry& c = data[id]; + c.Name = node.FirstChild("name").Value<TString>(); - - const NXml::TConstNodes cityNodes = node.Nodes("cities/city"); + + const NXml::TConstNodes cityNodes = node.Nodes("cities/city"); for (auto cityNode : cityNodes) { c.Cities.push_back(cityNode.Value<TString>()); - } - }; - - ParseXml(GEODATA, handler, "country"); - - UNIT_ASSERT_EQUAL(data.size(), 3); - + } + }; + + ParseXml(GEODATA, handler, "country"); + + UNIT_ASSERT_EQUAL(data.size(), 3); + UNIT_ASSERT(data.contains(225)); - const TCountry& russia = data.at(225); - UNIT_ASSERT_EQUAL(russia.Name, "Россия"); - UNIT_ASSERT_EQUAL(russia.Cities.size(), 2); - UNIT_ASSERT_EQUAL(russia.Cities[0], "Москва"); - UNIT_ASSERT_EQUAL(russia.Cities[1], "Санкт-Петербург"); - + const TCountry& russia = data.at(225); + UNIT_ASSERT_EQUAL(russia.Name, "Россия"); + UNIT_ASSERT_EQUAL(russia.Cities.size(), 2); + UNIT_ASSERT_EQUAL(russia.Cities[0], "Москва"); + UNIT_ASSERT_EQUAL(russia.Cities[1], "Санкт-Петербург"); + UNIT_ASSERT(data.contains(149)); - const TCountry& belarus = data.at(149); - UNIT_ASSERT_EQUAL(belarus.Name, "Беларусь"); - UNIT_ASSERT_EQUAL(belarus.Cities.size(), 1); - UNIT_ASSERT_EQUAL(belarus.Cities[0], "Минск"); - + const TCountry& belarus = data.at(149); + UNIT_ASSERT_EQUAL(belarus.Name, "Беларусь"); + UNIT_ASSERT_EQUAL(belarus.Cities.size(), 1); + UNIT_ASSERT_EQUAL(belarus.Cities[0], "Минск"); + UNIT_ASSERT(data.contains(187)); - const TCountry& ukraine = data.at(187); - UNIT_ASSERT_EQUAL(ukraine.Name, "Украина"); - UNIT_ASSERT_EQUAL(ukraine.Cities.size(), 1); - UNIT_ASSERT_EQUAL(ukraine.Cities[0], "Киев"); - } - + const TCountry& ukraine = data.at(187); + UNIT_ASSERT_EQUAL(ukraine.Name, "Украина"); + UNIT_ASSERT_EQUAL(ukraine.Cities.size(), 1); + UNIT_ASSERT_EQUAL(ukraine.Cities[0], "Киев"); + } + Y_UNIT_TEST(ParseXmlDeepLevel) { TVector<TString> cities; - - auto handler = [&cities](NXml::TConstNode node) { + + auto handler = [&cities](NXml::TConstNode node) { cities.push_back(node.Value<TString>()); - }; - - ParseXml(GEODATA, handler, "city"); - - UNIT_ASSERT_EQUAL(cities.size(), 4); - UNIT_ASSERT_EQUAL(cities[0], "Москва"); - UNIT_ASSERT_EQUAL(cities[1], "Санкт-Петербург"); - UNIT_ASSERT_EQUAL(cities[2], "Минск"); - UNIT_ASSERT_EQUAL(cities[3], "Киев"); - } - + }; + + ParseXml(GEODATA, handler, "city"); + + UNIT_ASSERT_EQUAL(cities.size(), 4); + UNIT_ASSERT_EQUAL(cities[0], "Москва"); + UNIT_ASSERT_EQUAL(cities[1], "Санкт-Петербург"); + UNIT_ASSERT_EQUAL(cities[2], "Минск"); + UNIT_ASSERT_EQUAL(cities[3], "Киев"); + } + Y_UNIT_TEST(ParseXmlException) { - // Check that exception properly passes through plain C code of libxml, - // no leaks are detected by valgrind. - auto handler = [](NXml::TConstNode node) { - const int id = node.Attr<int>("id"); - if (id != 225) { - ythrow yexception() << "unsupported id: " << id; - } - }; - - UNIT_ASSERT_EXCEPTION(ParseXml(GEODATA, handler, "country"), yexception); - UNIT_ASSERT_EXCEPTION(ParseXml("<a></b>", handler, "a"), yexception); - UNIT_ASSERT_EXCEPTION(ParseXml("<root><a id=\"1\"></a><a id=\"2\"></b></root>", handler, "a"), yexception); - UNIT_ASSERT_EXCEPTION(ParseXml("<root><a id=\"1\"></a><a id=\"2></a></root>", handler, "a"), yexception); - } - + // Check that exception properly passes through plain C code of libxml, + // no leaks are detected by valgrind. + auto handler = [](NXml::TConstNode node) { + const int id = node.Attr<int>("id"); + if (id != 225) { + ythrow yexception() << "unsupported id: " << id; + } + }; + + UNIT_ASSERT_EXCEPTION(ParseXml(GEODATA, handler, "country"), yexception); + UNIT_ASSERT_EXCEPTION(ParseXml("<a></b>", handler, "a"), yexception); + UNIT_ASSERT_EXCEPTION(ParseXml("<root><a id=\"1\"></a><a id=\"2\"></b></root>", handler, "a"), yexception); + UNIT_ASSERT_EXCEPTION(ParseXml("<root><a id=\"1\"></a><a id=\"2></a></root>", handler, "a"), yexception); + } + const TString BACKA = // UTF-8 encoding is used implicitly - "<Companies" - " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" - " xmlns=\"http://maps.yandex.ru/backa/1.x\"" - " xmlns:atom=\"http://www.w3.org/2005/Atom\"" - " xmlns:biz=\"http://maps.yandex.ru/business/1.x\"" - " xmlns:xal=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\"" - " xmlns:gml=\"http://www.opengis.net/gml\"" - ">" - "" - " <Company id=\"0001\">" - " <Geo>" - " <Location>" - " <gml:pos>37.62669 55.664827</gml:pos>" - " <kind>house</kind>" - " </Location>" - " <AddressDetails xmlns=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\">" - " <Country>" - " <AddressLine xml:lang=\"ru\">Москва, Каширское ш., 14</AddressLine>" - " </Country>" - " </AddressDetails>" - " </Geo>" - " </Company>" - "" - " <Company id=\"0002\">" - " <Geo>" - " <Location>" - " <pos xmlns=\"http://www.opengis.net/gml\">150.819797 59.56092</pos>" - " <kind>locality</kind>" - " </Location>" - " <xal:AddressDetails>" - " <xal:Country>" - " <xal:AddressLine xml:lang=\"ru\">Магадан, ул. Пролетарская, 43</xal:AddressLine>" - " </xal:Country>" - " </xal:AddressDetails>" - " </Geo>" - " </Company>" - "" - "</Companies>"; - + "<Companies" + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + " xmlns=\"http://maps.yandex.ru/backa/1.x\"" + " xmlns:atom=\"http://www.w3.org/2005/Atom\"" + " xmlns:biz=\"http://maps.yandex.ru/business/1.x\"" + " xmlns:xal=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\"" + " xmlns:gml=\"http://www.opengis.net/gml\"" + ">" + "" + " <Company id=\"0001\">" + " <Geo>" + " <Location>" + " <gml:pos>37.62669 55.664827</gml:pos>" + " <kind>house</kind>" + " </Location>" + " <AddressDetails xmlns=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\">" + " <Country>" + " <AddressLine xml:lang=\"ru\">Москва, Каширское ш., 14</AddressLine>" + " </Country>" + " </AddressDetails>" + " </Geo>" + " </Company>" + "" + " <Company id=\"0002\">" + " <Geo>" + " <Location>" + " <pos xmlns=\"http://www.opengis.net/gml\">150.819797 59.56092</pos>" + " <kind>locality</kind>" + " </Location>" + " <xal:AddressDetails>" + " <xal:Country>" + " <xal:AddressLine xml:lang=\"ru\">Магадан, ул. Пролетарская, 43</xal:AddressLine>" + " </xal:Country>" + " </xal:AddressDetails>" + " </Geo>" + " </Company>" + "" + "</Companies>"; + Y_UNIT_TEST(NamespaceHell) { - using TNS = NXml::TNamespaceForXPath; + using TNS = NXml::TNamespaceForXPath; const NXml::TNamespacesForXPath ns = { - TNS{"b", "http://maps.yandex.ru/backa/1.x"}, - TNS{"gml", "http://www.opengis.net/gml"}, + TNS{"b", "http://maps.yandex.ru/backa/1.x"}, + TNS{"gml", "http://www.opengis.net/gml"}, TNS{"xal", "urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"}}; - - int count = 0; + + int count = 0; THashMap<TString, TString> positions; THashMap<TString, TString> addresses; - - auto handler = [&](NXml::TConstNode node) { - count++; + + auto handler = [&](NXml::TConstNode node) { + count++; const auto id = node.Attr<TString>("id"); - - NXml::TXPathContextPtr ctxt = node.CreateXPathContext(ns); - - const NXml::TConstNode location = node.Node("b:Geo/b:Location", false, *ctxt); + + NXml::TXPathContextPtr ctxt = node.CreateXPathContext(ns); + + const NXml::TConstNode location = node.Node("b:Geo/b:Location", false, *ctxt); positions[id] = location.Node("gml:pos", false, *ctxt).Value<TString>(); addresses[id] = node.Node("b:Geo/xal:AddressDetails/xal:Country/xal:AddressLine", false, *ctxt).Value<TString>(); - }; - - ParseXml(BACKA, handler, "Company"); - UNIT_ASSERT_EQUAL(count, 0); - // nothing found because namespace was not specified - - ParseXml(BACKA, handler, "Company", "http://maps.yandex.ru/backa/1.x"); - - UNIT_ASSERT_VALUES_EQUAL(count, 2); - - UNIT_ASSERT_VALUES_EQUAL(positions["0001"], "37.62669 55.664827"); - UNIT_ASSERT_VALUES_EQUAL(positions["0002"], "150.819797 59.56092"); - - UNIT_ASSERT_VALUES_EQUAL(addresses["0001"], "Москва, Каширское ш., 14"); - UNIT_ASSERT_VALUES_EQUAL(addresses["0002"], "Магадан, ул. Пролетарская, 43"); - } -} + }; + + ParseXml(BACKA, handler, "Company"); + UNIT_ASSERT_EQUAL(count, 0); + // nothing found because namespace was not specified + + ParseXml(BACKA, handler, "Company", "http://maps.yandex.ru/backa/1.x"); + + UNIT_ASSERT_VALUES_EQUAL(count, 2); + + UNIT_ASSERT_VALUES_EQUAL(positions["0001"], "37.62669 55.664827"); + UNIT_ASSERT_VALUES_EQUAL(positions["0002"], "150.819797 59.56092"); + + UNIT_ASSERT_VALUES_EQUAL(addresses["0001"], "Москва, Каширское ш., 14"); + UNIT_ASSERT_VALUES_EQUAL(addresses["0002"], "Магадан, ул. Пролетарская, 43"); + } +} diff --git a/library/cpp/xml/document/ya.make b/library/cpp/xml/document/ya.make index 86bbd639cf..06a0065972 100644 --- a/library/cpp/xml/document/ya.make +++ b/library/cpp/xml/document/ya.make @@ -4,7 +4,7 @@ OWNER(finder) SRCS( xml-document.cpp - xml-textreader.cpp + xml-textreader.cpp xml-options.cpp ) diff --git a/library/cpp/ya.make b/library/cpp/ya.make index 8c1193b007..7c808ec29b 100644 --- a/library/cpp/ya.make +++ b/library/cpp/ya.make @@ -129,7 +129,7 @@ RECURSE( fuid fuid/ut function_tracer - geo + geo geobase geobase/ut geohash diff --git a/library/python/pytest/plugins/collection.py b/library/python/pytest/plugins/collection.py index e36f47a78f..f49c675d36 100644 --- a/library/python/pytest/plugins/collection.py +++ b/library/python/pytest/plugins/collection.py @@ -85,8 +85,8 @@ def pytest_ignore_collect(module, session, filenames_from_full_filters, accept_f if filenames_from_full_filters is not None and module.name not in filenames_from_full_filters: return True - test_file_filter = getattr(session.config.option, 'test_file_filter', None) - if test_file_filter is None: + test_file_filter = getattr(session.config.option, 'test_file_filter', None) + if test_file_filter is None: return False if module.name != test_file_filter.replace('/', '.'): return True diff --git a/library/python/pytest/yatest_tools.py b/library/python/pytest/yatest_tools.py index 6b8b896394..7b37688fd4 100644 --- a/library/python/pytest/yatest_tools.py +++ b/library/python/pytest/yatest_tools.py @@ -210,8 +210,8 @@ def get_unique_file_path(dir_path, filename, cache=collections.defaultdict(set)) max_path = 260 filename_len = len(dir_path) + len(extension) + tail_length + len(os.sep) if filename_len < max_path: - filename = yatest_lib.tools.trim_string(filename, max_path - filename_len) - filename = yatest_lib.tools.trim_string(filename, get_max_filename_length(dir_path) - tail_length - len(extension)) + extension + filename = yatest_lib.tools.trim_string(filename, max_path - filename_len) + filename = yatest_lib.tools.trim_string(filename, get_max_filename_length(dir_path) - tail_length - len(extension)) + extension candidate = os.path.join(dir_path, filename) key = dir_path + filename diff --git a/library/python/testing/recipe/__init__.py b/library/python/testing/recipe/__init__.py index 5ef9c5c189..91d31d370a 100644 --- a/library/python/testing/recipe/__init__.py +++ b/library/python/testing/recipe/__init__.py @@ -1,5 +1,5 @@ -from __future__ import print_function - +from __future__ import print_function + import os import sys import json @@ -86,7 +86,7 @@ def declare_recipe(start, stop): parsed_args, argv = get_options() if parsed_args.show_cwd: - print("Recipe \"{} {}\" working dir is {}".format(sys.argv[0], " ".join(argv), os.getcwd())) + print("Recipe \"{} {}\" working dir is {}".format(sys.argv[0], " ".join(argv), os.getcwd())) try: if argv[0] == RECIPE_START_OPTION: diff --git a/library/python/testing/recipe/ya.make b/library/python/testing/recipe/ya.make index dd323aa245..0d98ecc3d6 100644 --- a/library/python/testing/recipe/ya.make +++ b/library/python/testing/recipe/ya.make @@ -3,7 +3,7 @@ OWNER( g:yatest ) -PY23_LIBRARY() +PY23_LIBRARY() PY_SRCS( __init__.py diff --git a/library/python/testing/yatest_lib/tools.py b/library/python/testing/yatest_lib/tools.py index b72d79c162..0cf2ce87c8 100644 --- a/library/python/testing/yatest_lib/tools.py +++ b/library/python/testing/yatest_lib/tools.py @@ -1,4 +1,4 @@ -import six +import six import sys @@ -16,46 +16,46 @@ def to_utf8(value): return value.encode('utf-8', 'ignore') else: return str(value) - - -def trim_string(s, max_bytes): - """ - Adjusts the length of the string s in order to fit it - into max_bytes bytes of storage after encoding as UTF-8. - Useful when cutting filesystem paths. - :param s: unicode string - :param max_bytes: number of bytes - :return the prefix of s - """ - if isinstance(s, six.text_type): - return _trim_unicode_string(s, max_bytes) - - if isinstance(s, six.binary_type): - if len(s) <= max_bytes: - return s - s = s.decode('utf-8', errors='ignore') - s = _trim_unicode_string(s, max_bytes) - s = s.encode('utf-8', errors='ignore') - return s - - raise TypeError('a string is expected') - - -def _trim_unicode_string(s, max_bytes): - if len(s) * 4 <= max_bytes: - # UTF-8 uses at most 4 bytes per character - return s - - result = [] - cur_byte_length = 0 - - for ch in s: - cur_byte_length += len(ch.encode('utf-8')) - if cur_byte_length > max_bytes: - break - result.append(ch) - - return ''.join(result) + + +def trim_string(s, max_bytes): + """ + Adjusts the length of the string s in order to fit it + into max_bytes bytes of storage after encoding as UTF-8. + Useful when cutting filesystem paths. + :param s: unicode string + :param max_bytes: number of bytes + :return the prefix of s + """ + if isinstance(s, six.text_type): + return _trim_unicode_string(s, max_bytes) + + if isinstance(s, six.binary_type): + if len(s) <= max_bytes: + return s + s = s.decode('utf-8', errors='ignore') + s = _trim_unicode_string(s, max_bytes) + s = s.encode('utf-8', errors='ignore') + return s + + raise TypeError('a string is expected') + + +def _trim_unicode_string(s, max_bytes): + if len(s) * 4 <= max_bytes: + # UTF-8 uses at most 4 bytes per character + return s + + result = [] + cur_byte_length = 0 + + for ch in s: + cur_byte_length += len(ch.encode('utf-8')) + if cur_byte_length > max_bytes: + break + result.append(ch) + + return ''.join(result) def to_str(s): |