<commit_before>#include "testing/testing.hpp"

#include "search/search_tests_support/helpers.hpp"
#include "search/search_tests_support/test_results_matching.hpp"
#include "search/search_tests_support/test_search_request.hpp"

#include "generator/feature_builder.hpp"
#include "generator/generator_tests_support/test_feature.hpp"
#include "generator/generator_tests_support/test_mwm_builder.hpp"

#include "indexer/classificator.hpp"
#include "indexer/feature_meta.hpp"

#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"

#include "base/string_utils.hpp"

#include <string>

using namespace generator::tests_support;
using namespace search::tests_support;
using namespace std;

namespace search
{
namespace
{
class IncorrectCountry : public TestCountry
{
public:
  IncorrectCountry(m2::PointD const & center, string const & name, string const & lang)
    : TestCountry(center, name, lang)
  {
  }

  // TestFeature overrides:
  void Serialize(FeatureBuilder1 & fb) const override
  {
    fb.GetMetadataForTesting().Set(feature::Metadata::FMD_TEST_ID, strings::to_string(m_id));
    fb.SetCenter(m_center);

    if (!m_name.empty())
      CHECK(fb.AddName(m_lang, m_name), ("Can't set feature name:", m_name, "(", m_lang, ")"));

    auto const & classificator = classif();
    fb.AddType(classificator.GetTypeByPath({"place", "country"}));
  }
};

class SmokeTest : public SearchTest
{
};

class AlcoShop : public TestPOI
{
public:
  AlcoShop(m2::PointD const & center, string const & name, string const & lang)
    : TestPOI(center, name, lang)
  {
    SetTypes({{"shop", "alcohol"}});
  }

  ~AlcoShop() override = default;
};

class SubwayStation : public TestPOI
{
public:
  SubwayStation(m2::PointD const & center, string const & name, string const & lang)
    : TestPOI(center, name, lang)
  {
    SetTypes({{"railway", "station", "subway"}});
  }

  ~SubwayStation() override = default;
};

class SubwayStationMoscow : public TestPOI
{
public:
  SubwayStationMoscow(m2::PointD const & center, string const & name, string const & lang)
    : TestPOI(center, name, lang)
  {
    SetTypes({{"railway", "station", "subway", "moscow"}});
  }

  ~SubwayStationMoscow() override = default;
};

UNIT_CLASS_TEST(SmokeTest, Smoke)
{
  char const kCountryName[] = "BuzzTown";

  AlcoShop wineShop(m2::PointD(0, 0), "Wine shop", "en");
  AlcoShop tequilaShop(m2::PointD(1, 0), "Tequila shop", "en");
  AlcoShop brandyShop(m2::PointD(0, 1), "Brandy shop", "en");
  AlcoShop vodkaShop(m2::PointD(1, 1), "Russian vodka shop", "en");

  auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) {
    builder.Add(wineShop);
    builder.Add(tequilaShop);
    builder.Add(brandyShop);
    builder.Add(vodkaShop);
  });

  TEST_EQUAL(4, CountFeatures(m2::RectD(m2::PointD(0, 0), m2::PointD(1, 1))), ());
  TEST_EQUAL(2, CountFeatures(m2::RectD(m2::PointD(-0.5, -0.5), m2::PointD(0.5, 1.5))), ());

  SetViewport(m2::RectD(m2::PointD(0, 0), m2::PointD(100, 100)));
  {
    TRules rules = {ExactMatch(id, wineShop)};
    TEST(ResultsMatch("wine ", rules), ());
  }

  {
    TRules rules = {ExactMatch(id, wineShop), ExactMatch(id, tequilaShop),
                    ExactMatch(id, brandyShop), ExactMatch(id, vodkaShop)};
    TEST(ResultsMatch("shop ", rules), ());
  }
}

UNIT_CLASS_TEST(SmokeTest, DeepCategoryTest)
{
  char const kCountryName[] = "Wonderland";

  SubwayStation redStation(m2::PointD(0, 0), "red", "en");
  SubwayStationMoscow blueStation(m2::PointD(1, 1), "blue", "en");

  auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) {
    builder.Add(redStation);
    builder.Add(blueStation);
  });

  SetViewport(m2::RectD(m2::PointD(0, 0), m2::PointD(1, 1)));
  {
    TRules rules = {ExactMatch(id, redStation), ExactMatch(id, blueStation)};
    TEST(ResultsMatch("Subway ", rules), ());
  }
}

UNIT_CLASS_TEST(SmokeTest, CategoriesTest)
{
  // todo(@t.yan): fix some or delete category.
  vector<vector<string>> const invisibleTags = {{"amenity", "driving_school"},
                                                {"military", "bunker"},
                                                {"waterway", "canal"},
                                                {"waterway", "river"},
                                                {"waterway", "riverbank"},
                                                {"waterway", "stream"},
                                                {"landuse", "basin"},
                                                {"place", "county"},
                                                {"place", "islet"},
                                                {"power", "pole"},
                                                {"highway", "footway"},
                                                {"highway", "living_street"},
                                                {"highway", "motorway"},
                                                {"highway", "motorway_link"},
                                                {"highway", "path"},
                                                {"highway", "pedestrian"},
                                                {"highway", "primary"},
                                                {"highway", "primary_link"},
                                                {"highway", "raceway"},
                                                {"highway", "residential"},
                                                {"highway", "road"},
                                                {"highway", "secondary"},
                                                {"highway", "secondary_link"},
                                                {"highway", "service"},
                                                {"highway", "steps"},
                                                {"area:highway", "steps"},
                                                {"highway", "tertiary"},
                                                {"highway", "tertiary_link"},
                                                {"highway", "track"},
                                                {"highway", "traffic_signals"},
                                                {"highway", "trunk"},
                                                {"highway", "trunk_link"},
                                                {"highway", "unclassified"},
                                                {"man_made", "surveillance"},
                                                {"man_made", "tower"},
                                                {"man_made", "water_tower"},
                                                {"man_made", "water_well"},
                                                {"natural", "pond"},
                                                {"natural", "tree"},
                                                {"natural", "wood"}};
  set<uint32_t> invisibleTypes;
  for (auto const & tags : invisibleTags)
    invisibleTypes.insert(classif().GetTypeByPath(tags));

  vector<vector<string>> const notSupportedTags = {// Not visible because excluded by TypesSkipper.
                                                   {"building", "address"},
                                                   {"entrance"},
                                                   // Not visible for country scale range.
                                                   {"place", "continent"},
                                                   {"place", "region"}};
  set<uint32_t> notSupportedTypes;
  for (auto const & tags : notSupportedTags)
    notSupportedTypes.insert(classif().GetTypeByPath(tags));

  auto const & holder = GetDefaultCategories();
  auto testCategory = [&](uint32_t type, CategoriesHolder::Category const &) {
    if (invisibleTypes.find(type) != invisibleTypes.end())
      return;

    if (notSupportedTypes.find(type) != notSupportedTypes.end())
      return;

    string const countryName = "Wonderland";

    TestPOI poi(m2::PointD(1.0, 1.0), "poi", "en");
    poi.SetTypes({strings::Tokenize(classif().GetFullObjectName(type), "|")});

    auto id = BuildMwm(countryName, feature::DataHeader::country,
                       [&](TestMwmBuilder & builder) { builder.Add(poi); });

    SetViewport(m2::RectD(m2::PointD(0.0, 0.0), m2::PointD(2.0, 2.0)));
    {
      TRules rules = {ExactMatch(id, poi)};
      auto const query = holder.GetReadableFeatureType(type, CategoriesHolder::kEnglishCode) + " ";
      TEST(ResultsMatch(query, rules), ());
    }
    DeregisterMap(countryName);
  };

  holder.ForEachTypeAndCategory(testCategory);
}

UNIT_CLASS_TEST(SmokeTest, NotPrefixFreeNames)
{
  char const kCountryName[] = "ATown";

  auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) {
    builder.Add(TestPOI(m2::PointD(0, 0), "a", "en"));
    builder.Add(TestPOI(m2::PointD(0, 1), "aa", "en"));
    builder.Add(TestPOI(m2::PointD(1, 1), "aa", "en"));
    builder.Add(TestPOI(m2::PointD(1, 0), "aaa", "en"));
    builder.Add(TestPOI(m2::PointD(2, 0), "aaa", "en"));
    builder.Add(TestPOI(m2::PointD(2, 1), "aaa", "en"));
  });

  TEST_EQUAL(6, CountFeatures(m2::RectD(m2::PointD(0, 0), m2::PointD(2, 2))), ());

  m2::RectD const viewport(m2::PointD(0, 0), m2::PointD(100, 100));
  {
    TestSearchRequest request(m_engine, "a ", "en", Mode::Viewport, viewport);
    request.Run();
    TEST_EQUAL(1, request.Results().size(), ());
  }
  {
    TestSearchRequest request(m_engine, "aa ", "en", Mode::Viewport, viewport);
    request.Run();
    TEST_EQUAL(2, request.Results().size(), ());
  }
  {
    TestSearchRequest request(m_engine, "aaa ", "en", search::Mode::Viewport, viewport);
    request.Run();
    TEST_EQUAL(3, request.Results().size(), ());
  }
}

UNIT_CLASS_TEST(SmokeTest, NoDefaultNameTest)
{
  char const kCountryName[] = "Wonderland";

  IncorrectCountry wonderland(m2::PointD(0, 0), kCountryName, "en");
  auto worldId = BuildWorld([&](TestMwmBuilder & builder) { builder.Add(wonderland); });

  SetViewport(m2::RectD(m2::PointD(-0.5, -0.5), m2::PointD(0.5, 0.5)));
  TEST(ResultsMatch("Wonderland", {ExactMatch(worldId, wonderland)}), ());
}
}  // namespace
}  // namespace search
<commit_msg>[search] Add test for POI with address<commit_after>#include "testing/testing.hpp"

#include "search/search_tests_support/helpers.hpp"
#include "search/search_tests_support/test_results_matching.hpp"
#include "search/search_tests_support/test_search_request.hpp"

#include "generator/feature_builder.hpp"
#include "generator/generator_tests_support/test_feature.hpp"
#include "generator/generator_tests_support/test_mwm_builder.hpp"

#include "indexer/classificator.hpp"
#include "indexer/feature_meta.hpp"

#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"

#include "base/string_utils.hpp"

#include <string>

using namespace generator::tests_support;
using namespace search::tests_support;
using namespace std;

namespace search
{
namespace
{
class IncorrectCountry : public TestCountry
{
public:
  IncorrectCountry(m2::PointD const & center, string const & name, string const & lang)
    : TestCountry(center, name, lang)
  {
  }

  // TestFeature overrides:
  void Serialize(FeatureBuilder1 & fb) const override
  {
    fb.GetMetadataForTesting().Set(feature::Metadata::FMD_TEST_ID, strings::to_string(m_id));
    fb.SetCenter(m_center);

    if (!m_name.empty())
      CHECK(fb.AddName(m_lang, m_name), ("Can't set feature name:", m_name, "(", m_lang, ")"));

    auto const & classificator = classif();
    fb.AddType(classificator.GetTypeByPath({"place", "country"}));
  }
};

class SmokeTest : public SearchTest
{
};

class AlcoShop : public TestPOI
{
public:
  AlcoShop(m2::PointD const & center, string const & name, string const & lang)
    : TestPOI(center, name, lang)
  {
    SetTypes({{"shop", "alcohol"}});
  }

  ~AlcoShop() override = default;
};

class SubwayStation : public TestPOI
{
public:
  SubwayStation(m2::PointD const & center, string const & name, string const & lang)
    : TestPOI(center, name, lang)
  {
    SetTypes({{"railway", "station", "subway"}});
  }

  ~SubwayStation() override = default;
};

class SubwayStationMoscow : public TestPOI
{
public:
  SubwayStationMoscow(m2::PointD const & center, string const & name, string const & lang)
    : TestPOI(center, name, lang)
  {
    SetTypes({{"railway", "station", "subway", "moscow"}});
  }

  ~SubwayStationMoscow() override = default;
};

UNIT_CLASS_TEST(SmokeTest, Smoke)
{
  char const kCountryName[] = "BuzzTown";

  AlcoShop wineShop(m2::PointD(0, 0), "Wine shop", "en");
  AlcoShop tequilaShop(m2::PointD(1, 0), "Tequila shop", "en");
  AlcoShop brandyShop(m2::PointD(0, 1), "Brandy shop", "en");
  AlcoShop vodkaShop(m2::PointD(1, 1), "Russian vodka shop", "en");

  auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) {
    builder.Add(wineShop);
    builder.Add(tequilaShop);
    builder.Add(brandyShop);
    builder.Add(vodkaShop);
  });

  TEST_EQUAL(4, CountFeatures(m2::RectD(m2::PointD(0, 0), m2::PointD(1, 1))), ());
  TEST_EQUAL(2, CountFeatures(m2::RectD(m2::PointD(-0.5, -0.5), m2::PointD(0.5, 1.5))), ());

  SetViewport(m2::RectD(m2::PointD(0, 0), m2::PointD(100, 100)));
  {
    TRules rules = {ExactMatch(id, wineShop)};
    TEST(ResultsMatch("wine ", rules), ());
  }

  {
    TRules rules = {ExactMatch(id, wineShop), ExactMatch(id, tequilaShop),
                    ExactMatch(id, brandyShop), ExactMatch(id, vodkaShop)};
    TEST(ResultsMatch("shop ", rules), ());
  }
}

UNIT_CLASS_TEST(SmokeTest, DeepCategoryTest)
{
  char const kCountryName[] = "Wonderland";

  SubwayStation redStation(m2::PointD(0, 0), "red", "en");
  SubwayStationMoscow blueStation(m2::PointD(1, 1), "blue", "en");

  auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) {
    builder.Add(redStation);
    builder.Add(blueStation);
  });

  SetViewport(m2::RectD(m2::PointD(0, 0), m2::PointD(1, 1)));
  {
    TRules rules = {ExactMatch(id, redStation), ExactMatch(id, blueStation)};
    TEST(ResultsMatch("Subway ", rules), ());
  }
}

UNIT_CLASS_TEST(SmokeTest, CategoriesTest)
{
  // todo(@t.yan): fix some or delete category.
  vector<vector<string>> const invisibleTags = {{"amenity", "driving_school"},
                                                {"military", "bunker"},
                                                {"waterway", "canal"},
                                                {"waterway", "river"},
                                                {"waterway", "riverbank"},
                                                {"waterway", "stream"},
                                                {"landuse", "basin"},
                                                {"place", "county"},
                                                {"place", "islet"},
                                                {"power", "pole"},
                                                {"highway", "footway"},
                                                {"highway", "living_street"},
                                                {"highway", "motorway"},
                                                {"highway", "motorway_link"},
                                                {"highway", "path"},
                                                {"highway", "pedestrian"},
                                                {"highway", "primary"},
                                                {"highway", "primary_link"},
                                                {"highway", "raceway"},
                                                {"highway", "residential"},
                                                {"highway", "road"},
                                                {"highway", "secondary"},
                                                {"highway", "secondary_link"},
                                                {"highway", "service"},
                                                {"highway", "steps"},
                                                {"area:highway", "steps"},
                                                {"highway", "tertiary"},
                                                {"highway", "tertiary_link"},
                                                {"highway", "track"},
                                                {"highway", "traffic_signals"},
                                                {"highway", "trunk"},
                                                {"highway", "trunk_link"},
                                                {"highway", "unclassified"},
                                                {"man_made", "surveillance"},
                                                {"man_made", "tower"},
                                                {"man_made", "water_tower"},
                                                {"man_made", "water_well"},
                                                {"natural", "pond"},
                                                {"natural", "tree"},
                                                {"natural", "wood"}};
  set<uint32_t> invisibleTypes;
  for (auto const & tags : invisibleTags)
    invisibleTypes.insert(classif().GetTypeByPath(tags));

  vector<vector<string>> const notSupportedTags = {// Not visible because excluded by TypesSkipper.
                                                   {"building", "address"},
                                                   {"entrance"},
                                                   // Not visible for country scale range.
                                                   {"place", "continent"},
                                                   {"place", "region"}};
  set<uint32_t> notSupportedTypes;
  for (auto const & tags : notSupportedTags)
    notSupportedTypes.insert(classif().GetTypeByPath(tags));

  auto const & holder = GetDefaultCategories();
  auto testCategory = [&](uint32_t type, CategoriesHolder::Category const &) {
    if (invisibleTypes.find(type) != invisibleTypes.end())
      return;

    if (notSupportedTypes.find(type) != notSupportedTypes.end())
      return;

    string const countryName = "Wonderland";

    TestPOI poi(m2::PointD(1.0, 1.0), "poi", "en");
    poi.SetTypes({strings::Tokenize(classif().GetFullObjectName(type), "|")});

    auto id = BuildMwm(countryName, feature::DataHeader::country,
                       [&](TestMwmBuilder & builder) { builder.Add(poi); });

    SetViewport(m2::RectD(m2::PointD(0.0, 0.0), m2::PointD(2.0, 2.0)));
    {
      TRules rules = {ExactMatch(id, poi)};
      auto const query = holder.GetReadableFeatureType(type, CategoriesHolder::kEnglishCode) + " ";
      TEST(ResultsMatch(query, rules), ());
    }
    DeregisterMap(countryName);
  };

  holder.ForEachTypeAndCategory(testCategory);
}

UNIT_CLASS_TEST(SmokeTest, NotPrefixFreeNames)
{
  char const kCountryName[] = "ATown";

  auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) {
    builder.Add(TestPOI(m2::PointD(0, 0), "a", "en"));
    builder.Add(TestPOI(m2::PointD(0, 1), "aa", "en"));
    builder.Add(TestPOI(m2::PointD(1, 1), "aa", "en"));
    builder.Add(TestPOI(m2::PointD(1, 0), "aaa", "en"));
    builder.Add(TestPOI(m2::PointD(2, 0), "aaa", "en"));
    builder.Add(TestPOI(m2::PointD(2, 1), "aaa", "en"));
  });

  TEST_EQUAL(6, CountFeatures(m2::RectD(m2::PointD(0, 0), m2::PointD(2, 2))), ());

  m2::RectD const viewport(m2::PointD(0, 0), m2::PointD(100, 100));
  {
    TestSearchRequest request(m_engine, "a ", "en", Mode::Viewport, viewport);
    request.Run();
    TEST_EQUAL(1, request.Results().size(), ());
  }
  {
    TestSearchRequest request(m_engine, "aa ", "en", Mode::Viewport, viewport);
    request.Run();
    TEST_EQUAL(2, request.Results().size(), ());
  }
  {
    TestSearchRequest request(m_engine, "aaa ", "en", search::Mode::Viewport, viewport);
    request.Run();
    TEST_EQUAL(3, request.Results().size(), ());
  }
}

UNIT_CLASS_TEST(SmokeTest, NoDefaultNameTest)
{
  char const kCountryName[] = "Wonderland";

  IncorrectCountry wonderland(m2::PointD(0, 0), kCountryName, "en");
  auto worldId = BuildWorld([&](TestMwmBuilder & builder) { builder.Add(wonderland); });

  SetViewport(m2::RectD(m2::PointD(-0.5, -0.5), m2::PointD(0.5, 0.5)));
  TEST(ResultsMatch("Wonderland", {ExactMatch(worldId, wonderland)}), ());
}

UNIT_CLASS_TEST(SmokeTest, PoiWithAddress)
{
  char const kCountryName[] = "Wonderland";
  TestStreet mainStreet({m2::PointD(0.0, 0.0), m2::PointD(1.0, 1.0), m2::PointD(2.0, 2.0)},
                        "Main Street", "en");
  TestCafe cafe(m2::PointD(1.0, 1.0), "Starbucks", "en");
  cafe.SetStreet(mainStreet);
  cafe.SetHouseNumber("27");

  auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) {
    builder.Add(mainStreet);
    builder.Add(cafe);
  });

  SetViewport(m2::RectD(m2::PointD(0.0, 0.0), m2::PointD(2.0, 2.0)));
  {
    TRules rules = {ExactMatch(id, cafe)};
    TEST(ResultsMatch("Starbucks ", rules), ());
    TEST(ResultsMatch("Main street 27 ", rules), ());
    TEST(ResultsMatch("Main street 27 Starbucks ", rules), ());
    TEST(ResultsMatch("Starbucks Main street 27 ", rules), ());
  }
}
}  // namespace
}  // namespace search
<|endoftext|>


<commit_before>#include "CppUnitTest.h"
#include <string>
#include <vector>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;

namespace algo
{
    struct token
    {
        enum toktype { root_node, named_node, edge_name, horizontal_edge };
        toktype type;
        string name;
    };

    bool operator==(const token& lhs, const token& rhs)
    {
        return true;
    }

    struct ascii_tree
    {
        static vector<token> tokenize(const string& s)
        {
            enum { none, open_square_brace, asterisk, dash, edge_name } prev = none;

            for (auto ch : s)
            {
                if (ch == '[')
                {
                    prev = open_square_brace;
                }
                else if (ch == ']')
                {
                    if (prev == asterisk)
                    {
                        token newtok = { token::root_node, "" };
                        return vector<token>(1, newtok);
                    }
                    else
                    {
                        string name = s.substr(1, s.size() - 2);
                        token newtok = { token::named_node, name };
                        return vector<token>(1, newtok);
                    }
                }
                else if (ch == '*')
                {
                    prev = asterisk;
                }
                else if (ch == '-')
                {
                    if (prev == dash)
                    {
                        string name = s.substr(2, s.size() - 4);
                        token newtok = { token::horizontal_edge, name };
                        return vector<token>(1, newtok);
                    }
                    prev = dash;
                }
                else
                {
                    if (prev == none)
                    {
                        prev = edge_name;
                    }
                }
            }

            return (prev == edge_name)
                ? vector<token>(1, token { token::edge_name, s })
                : vector<token>();
        }
    };
}

namespace Microsoft { namespace VisualStudio { namespace CppUnitTestFramework
{
    template<>
    wstring ToString<algo::token::toktype>(const algo::token::toktype& type)
    {
        switch (type)
        {
        case algo::token::root_node:
            return L"root_node";
        case algo::token::named_node:
            return L"named_node";
        case algo::token::edge_name:
            return L"edge_name";
        case algo::token::horizontal_edge:
            return L"horizontal_edge";
        default:
            return L"unknown token";
        }
    }
}}}

namespace algo { namespace spec
{
	TEST_CLASS(can_recognize_ascii_tree_tokens)
	{
	public:

        TEST_METHOD(should_not_recognize_any_tokens_in_an_empty_string)
        {
            auto tokens = ascii_tree::tokenize("");
            Assert::IsTrue(tokens.empty());
        }

		TEST_METHOD(should_recognize_a_root_node)
		{
            auto tokens = ascii_tree::tokenize("[*]");
            Assert::AreEqual(token::root_node, tokens.front().type);
        }

        TEST_METHOD(should_recognize_a_named_node)
        {
            auto tokens = ascii_tree::tokenize("[a]");
            Assert::AreEqual(token::named_node, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_edge_name)
        {
            auto tokens = ascii_tree::tokenize("a");
            Assert::AreEqual(token::edge_name, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_horizontal_edge)
        {
            auto tokens = ascii_tree::tokenize("--a--");
            Assert::AreEqual(token::horizontal_edge, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

    };
}}
<commit_msg>recognize an ascending edge part<commit_after>#include "CppUnitTest.h"
#include <string>
#include <vector>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;

namespace algo
{
    struct token
    {
        enum toktype { root_node, named_node, edge_name, horizontal_edge, ascending_edge_part };
        toktype type;
        string name;
    };

    bool operator==(const token& lhs, const token& rhs)
    {
        return true;
    }

    struct ascii_tree
    {
        static vector<token> tokenize(const string& s)
        {
            enum { none, open_square_brace, asterisk, dash, edge_name } prev = none;

            for (auto ch : s)
            {
                if (ch == '[')
                {
                    prev = open_square_brace;
                }
                else if (ch == ']')
                {
                    if (prev == asterisk)
                    {
                        token newtok = { token::root_node, "" };
                        return vector<token>(1, newtok);
                    }
                    else
                    {
                        string name = s.substr(1, s.size() - 2);
                        token newtok = { token::named_node, name };
                        return vector<token>(1, newtok);
                    }
                }
                else if (ch == '*')
                {
                    prev = asterisk;
                }
                else if (ch == '-')
                {
                    if (prev == dash)
                    {
                        string name = s.substr(2, s.size() - 4);
                        token newtok = { token::horizontal_edge, name };
                        return vector<token>(1, newtok);
                    }
                    prev = dash;
                }
                else if (ch == '/')
                {
                    token newtok = { token::ascending_edge_part, "" };
                    return vector<token>(1, newtok);
                }
                else
                {
                    if (prev == none)
                    {
                        prev = edge_name;
                    }
                }
            }

            return (prev == edge_name)
                ? vector<token>(1, token { token::edge_name, s })
                : vector<token>();
        }
    };
}

namespace Microsoft { namespace VisualStudio { namespace CppUnitTestFramework
{
    template<>
    wstring ToString<algo::token::toktype>(const algo::token::toktype& type)
    {
        switch (type)
        {
        case algo::token::root_node:
            return L"root_node";
        case algo::token::named_node:
            return L"named_node";
        case algo::token::edge_name:
            return L"edge_name";
        case algo::token::horizontal_edge:
            return L"horizontal_edge";
        case algo::token::ascending_edge_part:
            return L"ascending_edge_part";
        default:
            return L"unknown token";
        }
    }
}}}

namespace algo { namespace spec
{
	TEST_CLASS(can_recognize_ascii_tree_tokens)
	{
	public:

        TEST_METHOD(should_not_recognize_any_tokens_in_an_empty_string)
        {
            auto tokens = ascii_tree::tokenize("");
            Assert::IsTrue(tokens.empty());
        }

		TEST_METHOD(should_recognize_a_root_node)
		{
            auto tokens = ascii_tree::tokenize("[*]");
            Assert::AreEqual(token::root_node, tokens.front().type);
        }

        TEST_METHOD(should_recognize_a_named_node)
        {
            auto tokens = ascii_tree::tokenize("[a]");
            Assert::AreEqual(token::named_node, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_edge_name)
        {
            auto tokens = ascii_tree::tokenize("a");
            Assert::AreEqual(token::edge_name, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_asceding_edge_part)
        {
            auto tokens = ascii_tree::tokenize("/");
            Assert::AreEqual(token::ascending_edge_part, tokens.front().type);
        }

        TEST_METHOD(should_recognize_an_horizontal_edge)
        {
            auto tokens = ascii_tree::tokenize("--a--");
            Assert::AreEqual(token::horizontal_edge, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

    };
}}
<|endoftext|>


<commit_before>#include "CppUnitTest.h"
#include <string>
#include <vector>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;

namespace algo
{
    struct token
    {
        enum toktype { root_node, named_node, edge_name, horizontal_edge, ascending_edge_part };
        toktype type;
        string name;
    };

    bool operator==(const token& lhs, const token& rhs)
    {
        return true;
    }

    struct ascii_tree
    {
        static vector<token> tokenize(const string& s)
        {
            enum { none, open_square_brace, asterisk, dash, edge_name } prev = none;

            for (auto ch : s)
            {
                if (ch == '[')
                {
                    prev = open_square_brace;
                }
                else if (ch == ']')
                {
                    if (prev == asterisk)
                    {
                        token newtok = { token::root_node, "" };
                        return vector<token>(1, newtok);
                    }
                    else
                    {
                        string name = s.substr(1, s.size() - 2);
                        token newtok = { token::named_node, name };
                        return vector<token>(1, newtok);
                    }
                }
                else if (ch == '*')
                {
                    prev = asterisk;
                }
                else if (ch == '-')
                {
                    if (prev == dash)
                    {
                        string name = s.substr(2, s.size() - 4);
                        token newtok = { token::horizontal_edge, name };
                        return vector<token>(1, newtok);
                    }
                    prev = dash;
                }
                else if (ch == '/')
                {
                    token newtok = { token::ascending_edge_part, "" };
                    return vector<token>(1, newtok);
                }
                else
                {
                    if (prev == none)
                    {
                        prev = edge_name;
                    }
                }
            }

            return (prev == edge_name)
                ? vector<token>(1, token { token::edge_name, s })
                : vector<token>();
        }
    };
}

namespace Microsoft { namespace VisualStudio { namespace CppUnitTestFramework
{
    template<>
    wstring ToString<algo::token::toktype>(const algo::token::toktype& type)
    {
        switch (type)
        {
        case algo::token::root_node:
            return L"root_node";
        case algo::token::named_node:
            return L"named_node";
        case algo::token::edge_name:
            return L"edge_name";
        case algo::token::horizontal_edge:
            return L"horizontal_edge";
        case algo::token::ascending_edge_part:
            return L"ascending_edge_part";
        default:
            return L"unknown token";
        }
    }
}}}

namespace algo { namespace spec
{
	TEST_CLASS(can_recognize_ascii_tree_tokens)
	{
	public:

        TEST_METHOD(should_not_recognize_any_tokens_in_an_empty_string)
        {
            auto tokens = ascii_tree::tokenize("");
            Assert::IsTrue(tokens.empty());
        }

		TEST_METHOD(should_recognize_a_root_node)
		{
            auto tokens = ascii_tree::tokenize("[*]");
            Assert::AreEqual(token::root_node, tokens.front().type);
        }

        TEST_METHOD(should_recognize_a_named_node)
        {
            auto tokens = ascii_tree::tokenize("[a]");
            Assert::AreEqual(token::named_node, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_edge_name)
        {
            auto tokens = ascii_tree::tokenize("a");
            Assert::AreEqual(token::edge_name, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_asceding_edge_part)
        {
            auto tokens = ascii_tree::tokenize("/");
            Assert::AreEqual(token::ascending_edge_part, tokens.front().type);
        }

        TEST_METHOD(should_recognize_an_horizontal_edge)
        {
            auto tokens = ascii_tree::tokenize("--a--");
            Assert::AreEqual(token::horizontal_edge, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

    };
}}
<commit_msg>recognize a descending edge part<commit_after>#include "CppUnitTest.h"
#include <string>
#include <vector>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;

namespace algo
{
    struct token
    {
        enum toktype { root_node, named_node, edge_name, horizontal_edge, ascending_edge_part, descending_edge_part };
        toktype type;
        string name;
    };

    bool operator==(const token& lhs, const token& rhs)
    {
        return true;
    }

    struct ascii_tree
    {
        static vector<token> tokenize(const string& s)
        {
            enum { none, open_square_brace, asterisk, dash, edge_name } prev = none;

            for (auto ch : s)
            {
                if (ch == '[')
                {
                    prev = open_square_brace;
                }
                else if (ch == ']')
                {
                    if (prev == asterisk)
                    {
                        token newtok = { token::root_node, "" };
                        return vector<token>(1, newtok);
                    }
                    else
                    {
                        string name = s.substr(1, s.size() - 2);
                        token newtok = { token::named_node, name };
                        return vector<token>(1, newtok);
                    }
                }
                else if (ch == '*')
                {
                    prev = asterisk;
                }
                else if (ch == '-')
                {
                    if (prev == dash)
                    {
                        string name = s.substr(2, s.size() - 4);
                        token newtok = { token::horizontal_edge, name };
                        return vector<token>(1, newtok);
                    }
                    prev = dash;
                }
                else if (ch == '/')
                {
                    token newtok = { token::ascending_edge_part, "" };
                    return vector<token>(1, newtok);
                }
                else if (ch == '\\')
                {
                    token newtok = { token::descending_edge_part, "" };
                    return vector<token>(1, newtok);
                }
                else
                {
                    if (prev == none)
                    {
                        prev = edge_name;
                    }
                }
            }

            return (prev == edge_name)
                ? vector<token>(1, token { token::edge_name, s })
                : vector<token>();
        }
    };
}

namespace Microsoft { namespace VisualStudio { namespace CppUnitTestFramework
{
    template<>
    wstring ToString<algo::token::toktype>(const algo::token::toktype& type)
    {
        switch (type)
        {
        case algo::token::root_node:
            return L"root_node";
        case algo::token::named_node:
            return L"named_node";
        case algo::token::edge_name:
            return L"edge_name";
        case algo::token::horizontal_edge:
            return L"horizontal_edge";
        case algo::token::ascending_edge_part:
            return L"ascending_edge_part";
        case algo::token::descending_edge_part:
            return L"descending_edge_part";
        default:
            return L"unknown token";
        }
    }
}}}

namespace algo { namespace spec
{
	TEST_CLASS(can_recognize_ascii_tree_tokens)
	{
	public:

        TEST_METHOD(should_not_recognize_any_tokens_in_an_empty_string)
        {
            auto tokens = ascii_tree::tokenize("");
            Assert::IsTrue(tokens.empty());
        }

		TEST_METHOD(should_recognize_a_root_node)
		{
            auto tokens = ascii_tree::tokenize("[*]");
            Assert::AreEqual(token::root_node, tokens.front().type);
        }

        TEST_METHOD(should_recognize_a_named_node)
        {
            auto tokens = ascii_tree::tokenize("[a]");
            Assert::AreEqual(token::named_node, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_edge_name)
        {
            auto tokens = ascii_tree::tokenize("a");
            Assert::AreEqual(token::edge_name, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

        TEST_METHOD(should_recognize_an_ascending_edge_part)
        {
            auto tokens = ascii_tree::tokenize("/");
            Assert::AreEqual(token::ascending_edge_part, tokens.front().type);
        }

        TEST_METHOD(should_recognize_a_descending_edge_part)
        {
            auto tokens = ascii_tree::tokenize("\\");
            Assert::AreEqual(token::descending_edge_part, tokens.front().type);
        }

        TEST_METHOD(should_recognize_an_horizontal_edge)
        {
            auto tokens = ascii_tree::tokenize("--a--");
            Assert::AreEqual(token::horizontal_edge, tokens.front().type);
            Assert::AreEqual("a", tokens.front().name.c_str());
        }

    };
}}
<|endoftext|>


<commit_before>#include <inly.h>

#include <string>
#include <boost/program_options.hpp>
#include <cstdlib>

NAMESPACE_USING__INLY

int m2raw()
{
	CInly	Inly;

	std::string	strRaw = Inly.GetRawString();
	if (strRaw.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strRaw << std::endl;

	return (EXIT_SUCCESS);
}

int m2hw()
{
	CInly	Inly;

	std::string	strHardware = Inly.GetHardwareString();
	if (strHardware.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strHardware << std::endl;

	return (EXIT_SUCCESS);
}

int m2lic()
{
	CInly	Inly;

	std::string	strLicense = Inly.GetLicenseString();
	if (strLicense.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strLicense << std::endl;

	return (EXIT_SUCCESS);
}

int raw2hw(const std_string &r_strRaw)
{
	CInly	Inly;

	std::string	strHardware = Inly.GetHardwareString(r_strRaw);
	if (strHardware.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strHardware << std::endl;

	return (EXIT_SUCCESS);
}

int main(int argc, char **argv)
{
	namespace po = boost::program_options;

	po::options_description desc("inly_tool args description");
	desc.add_options()
    	("help,h", "show this message and exit")
    	("version,v", "show version and exit")

    	//字符串系列的选项开关
    	("m2raw", "input: none/null; output: raw machine string")
    	("m2hw", "input: none/null; output: hardware string")
    	("m2lic", "input: none/null; output: license string")
    	("raw2hw", po::value< std::string >(), "input: raw machine string; output: hardware string")
    	("raw2lic", po::value< std::string >(), "input: raw machine string; output: license string")
    	("hw2lic", po::value< std::string >(), "input: hardware string; output: license string")
    	("hw2raw", po::value< std::string >(), "input: hardware string; output: raw machine string")
    	("lic2raw", po::value< std::string >(), "input: license string; output: raw machine string")
    	("lic2hw", po::value< std::string >(), "input: license string; output: raw hardware string")

		//检验系列的选项开关
		//不再开放其它的(x7y)，一方面它不是直接所需的接口，另一方面，通过x2y系列的接口可以等价地实现
    	("m7hw", po::value< std::string >(), "check: hardware string with current machine")
    	("m7lic", po::value< std::string >(), "check: license string with current machine")
	;

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	if (vm.count("help")) {
		desc.print(std::cout);
	    std::exit(EXIT_SUCCESS);
	} else if (vm.count("version")) {
		std::cout << "inly_tool 1.0.0" << std::endl;
		std::exit(EXIT_SUCCESS);
	} else if (vm.count("m2raw")) {
		int iRet = m2raw();
		std::exit(iRet);
	} else if (vm.count("m2hw")) {
		int iRet = m2hw();
		std::exit(iRet);
	} else if (vm.count("m2lic")) {
		int iRet = m2lic();
		std::exit(iRet);
	} else if (vm.count("raw2hw")) {
		int iRet = raw2hw(vm["raw2hw"].as< std::string >());
		std::exit(iRet);
	}

//	if (vm.count("compression")) {
//	    cout << "Compression level was set to "
//	 << vm["compression"].as() << ".\n";
//	} else {
//	    cout << "Compression level was not set.\n";
//	}

	return (0);

}

/*
在main函数还未增加选项开关之前的相关测试代码片断

	CInly	Inly;

	//Inly.test("dano306");
	//std::cout << "hello world, dano306!" << std::endl;

	{
		std::string	strHardware;
		strHardware = Inly.GetHardwareString();
		inly_cout(strHardware);
	}

	{
		std::string	strLicense;
		strLicense = Inly.GetLicenseString();
		inly_cout(strLicense);
	}

	{
		std::string	strHardware = "4007D2B98B95BD4AE2B444C64A57816EC2";
		std::string	strLicense;
		strLicense = Inly.GetLicenseString(strHardware);
		inly_cout(strLicense);
	}

	{
		std::string	strLicense = "4407D8BEAC9DCD4AE0954AC93E258F4CE198263A0F5666093B6BB5A52199157D327E";
		bool	bRet_CheckLicenseString = Inly.CheckLicenseString(strLicense);
		inly_cout(bRet_CheckLicenseString);
	}

	{
		std::string	strLicense = "4407D8BEAC9DCD4AE0954AC93E258F4CE198263A0F5666093B6BB5A52199157D327E";
		std::string	strHardwarePlain = Inly.DumpLicenseDetail(strLicense);
		inly_cout(strHardwarePlain);
	}

	{
		std::string	strHardware = "4007D2B98B95BD4AE2B444C64A57816EC2";
		std::string	strHardwarePlain = Inly.DumpHardwareDetail(strHardware);
		inly_cout(strHardwarePlain);
	}

*/
<commit_msg>inly_tool增加raw2lic<commit_after>#include <inly.h>

#include <string>
#include <boost/program_options.hpp>
#include <cstdlib>

NAMESPACE_USING__INLY

int m2raw()
{
	CInly	Inly;

	std::string	strRaw = Inly.GetRawString();
	if (strRaw.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strRaw << std::endl;

	return (EXIT_SUCCESS);
}

int m2hw()
{
	CInly	Inly;

	std::string	strHardware = Inly.GetHardwareString();
	if (strHardware.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strHardware << std::endl;

	return (EXIT_SUCCESS);
}

int m2lic()
{
	CInly	Inly;

	std::string	strLicense = Inly.GetLicenseString();
	if (strLicense.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strLicense << std::endl;

	return (EXIT_SUCCESS);
}

int raw2hw(const std_string &r_strRaw)
{
	CInly	Inly;

	std::string	strHardware = Inly.GetHardwareString(r_strRaw);
	if (strHardware.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strHardware << std::endl;

	return (EXIT_SUCCESS);
}

int raw2lic(const std_string &r_strRaw)
{
	CInly	Inly;

	std::string	strHardware = Inly.GetHardwareString(r_strRaw);
	if (strHardware.empty()) {
		return (EXIT_FAILURE);
	}

	std::string	strLicense = Inly.GetLicenseString(strHardware);
	if (strLicense.empty()) {
		return (EXIT_FAILURE);
	}
	std::cout << strLicense << std::endl;

	return (EXIT_SUCCESS);
}

int main(int argc, char **argv)
{
	namespace po = boost::program_options;

	po::options_description desc("inly_tool args description");
	desc.add_options()
    	("help,h", "show this message and exit")
    	("version,v", "show version and exit")

    	//字符串系列的选项开关
    	("m2raw", "input: none/null; output: raw machine string")
    	("m2hw", "input: none/null; output: hardware string")
    	("m2lic", "input: none/null; output: license string")
    	("raw2hw", po::value< std::string >(), "input: raw machine string; output: hardware string")
    	("raw2lic", po::value< std::string >(), "input: raw machine string; output: license string")
    	("hw2lic", po::value< std::string >(), "input: hardware string; output: license string")
    	("hw2raw", po::value< std::string >(), "input: hardware string; output: raw machine string")
    	("lic2raw", po::value< std::string >(), "input: license string; output: raw machine string")
    	("lic2hw", po::value< std::string >(), "input: license string; output: raw hardware string")

		//检验系列的选项开关
		//不再开放其它的(x7y)，一方面它不是直接所需的接口，另一方面，通过x2y系列的接口可以等价地实现
    	("m7hw", po::value< std::string >(), "check: hardware string with current machine")
    	("m7lic", po::value< std::string >(), "check: license string with current machine")
	;

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	if (vm.count("help")) {
		desc.print(std::cout);
	    std::exit(EXIT_SUCCESS);
	} else if (vm.count("version")) {
		std::cout << "inly_tool 1.0.0" << std::endl;
		std::exit(EXIT_SUCCESS);
	} else if (vm.count("m2raw")) {
		int iRet = m2raw();
		std::exit(iRet);
	} else if (vm.count("m2hw")) {
		int iRet = m2hw();
		std::exit(iRet);
	} else if (vm.count("m2lic")) {
		int iRet = m2lic();
		std::exit(iRet);
	} else if (vm.count("raw2hw")) {
		int iRet = raw2hw(vm["raw2hw"].as< std::string >());
		std::exit(iRet);
	} else if (vm.count("raw2lic")) {
		int iRet = raw2lic(vm["raw2lic"].as< std::string >());
		std::exit(iRet);
	}

	return (0);

}

/*
在main函数还未增加选项开关之前的相关测试代码片断

	CInly	Inly;

	//Inly.test("dano306");
	//std::cout << "hello world, dano306!" << std::endl;

	{
		std::string	strHardware;
		strHardware = Inly.GetHardwareString();
		inly_cout(strHardware);
	}

	{
		std::string	strLicense;
		strLicense = Inly.GetLicenseString();
		inly_cout(strLicense);
	}

	{
		std::string	strHardware = "4007D2B98B95BD4AE2B444C64A57816EC2";
		std::string	strLicense;
		strLicense = Inly.GetLicenseString(strHardware);
		inly_cout(strLicense);
	}

	{
		std::string	strLicense = "4407D8BEAC9DCD4AE0954AC93E258F4CE198263A0F5666093B6BB5A52199157D327E";
		bool	bRet_CheckLicenseString = Inly.CheckLicenseString(strLicense);
		inly_cout(bRet_CheckLicenseString);
	}

	{
		std::string	strLicense = "4407D8BEAC9DCD4AE0954AC93E258F4CE198263A0F5666093B6BB5A52199157D327E";
		std::string	strHardwarePlain = Inly.DumpLicenseDetail(strLicense);
		inly_cout(strHardwarePlain);
	}

	{
		std::string	strHardware = "4007D2B98B95BD4AE2B444C64A57816EC2";
		std::string	strHardwarePlain = Inly.DumpHardwareDetail(strHardware);
		inly_cout(strHardwarePlain);
	}

*/
<|endoftext|>


<commit_before>#include <bits/stdc++.h>

using namespace std;
#define DEBUG_ON 1

#define INF 0x3f3f3f3f
#define NSYNC ios::sync_with_stdio(false);
#define FOR(i,a,b) for(int i=a; i<(b); ++i)
#define FOR0(i,b) for(int i=0; i<(b); ++i)
#define TRAV(it,c) for(__typeof((c).begin()) it=(c).begin(); it!=(c).end(); ++it)
#define RTRAV(it,c) for(__typeof((c).rbegin()) it=(c).rbegin(); it!=(c).rend(); ++it)
#define DBG(x) if(DEBUG_ON) cout << #x << " == " << x << endl
#define DBGP(x) if(DEBUG_ON) cout << "(" << (x).first << ", " << (x).second << ")" << endl
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define R(x) scanf(" %d",&(x))
#define RR(x,y) scanf(" %d %d",&(x), &(y))
#define RRR(x,y,z) scanf(" %d %d %d",&(x), &(y),&(z))
#define CLR(v) memset(v, 0, sizeof(v))
#define SET(v) memset(v, -1, sizeof(v))

typedef long long ll;
typedef int int_type;
typedef pair<int_type, int_type> pii;
typedef vector<int_type> vi;

const int MAXN = 200010;
const int LOGMAXN = 20;
int p[LOGMAXN][MAXN];
int sa[MAXN];
int step;
pair<pii,int> vaux[MAXN];
string s;

void calcsa() {
	int n = s.size();
	FOR0(i,n) p[0][i] = s[i];
	if(n==1) p[0][0] = 0;
	int pot;
	for(step=1,pot=2; pot<2*n; ++step, pot*=2) {
		FOR0(i,n) {
			vaux[i].first.first = p[step-1][i];
			vaux[i].first.second =  (i+pot/2 < n ? p[step-1][i+pot/2] : -1);
			vaux[i].second = i;
		}
		sort(vaux,vaux+n);
		int id = 0;
		FOR0(i,n) {
			if(i && vaux[i].first != vaux[i-1].first) ++id;
			p[step][vaux[i].second] = id;
		}
	}
	--step;
	FOR0(i,n) {
		sa[p[step][i]] = i;
	}
}

int lcp(int x, int y) {
	int n = s.size();
	if(x==y) return n-x;
	int ans = 0;
	for(int i=step; i>=0; --i) {
		if(p[i][x]==p[i][y]) {
			ans |= (1<<i);
			x += (1<<i);
			y += (1<<i);
			if(x>=n || y>=n) break;
		}
	}
	return ans;
}

int main() {
	NSYNC;
	cin >> s;
	reverse(s.begin(),s.end());
	calcsa();
	int q;
	cin >> q;
	int n = s.size();
	while(q--) {
		int x;
		cin >> x;
		cout << lcp(0,n-x) << endl;
	}
	return 0;
}<commit_msg>Update suffarray.cpp<commit_after>#include <bits/stdc++.h>

using namespace std;
#define DEBUG_ON 1

#define INF 0x3f3f3f3f
#define NSYNC ios::sync_with_stdio(false);
#define FOR(i,a,b) for(int i=a; i<(b); ++i)
#define FOR0(i,b) for(int i=0; i<(b); ++i)
#define TRAV(it,c) for(__typeof((c).begin()) it=(c).begin(); it!=(c).end(); ++it)
#define RTRAV(it,c) for(__typeof((c).rbegin()) it=(c).rbegin(); it!=(c).rend(); ++it)
#define DBG(x) if(DEBUG_ON) cout << #x << " == " << x << endl
#define DBGP(x) if(DEBUG_ON) cout << "(" << (x).first << ", " << (x).second << ")" << endl
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define R(x) scanf(" %d",&(x))
#define RR(x,y) scanf(" %d %d",&(x), &(y))
#define RRR(x,y,z) scanf(" %d %d %d",&(x), &(y),&(z))
#define CLR(v) memset(v, 0, sizeof(v))
#define SET(v) memset(v, -1, sizeof(v))

typedef long long ll;
typedef int int_type;
typedef pair<int_type, int_type> pii;
typedef vector<int_type> vi;

const int MAXN = 200010;
const int LOGMAXN = 20; // > floor(log(MAXN))
int p[LOGMAXN][MAXN];
int sa[MAXN];
int step;
pair<pii,int> vaux[MAXN];
string s;

void calcsa() {
	int n = s.size();
	FOR0(i,n) p[0][i] = s[i];
	if(n==1) p[0][0] = 0;
	int pot;
	for(step=1,pot=2; pot<2*n; ++step, pot*=2) {
		FOR0(i,n) {
			vaux[i].first.first = p[step-1][i];
			vaux[i].first.second =  (i+pot/2 < n ? p[step-1][i+pot/2] : -1);
			vaux[i].second = i;
		}
		sort(vaux,vaux+n);
		int id = 0;
		FOR0(i,n) {
			if(i && vaux[i].first != vaux[i-1].first) ++id;
			p[step][vaux[i].second] = id;
		}
	}
	--step;
	FOR0(i,n) {
		sa[p[step][i]] = i;
	}
}
//sa[i] = index of the i-th suffix

int lcp(int x, int y) {	//x,y are idx of suffix
	int n = s.size();
	if(x==y) return n-x;
	int ans = 0;
	for(int i=step; i>=0; --i) {
		if(p[i][x]==p[i][y]) {
			ans |= (1<<i);
			x += (1<<i);
			y += (1<<i);
			if(x>=n || y>=n) break;
		}
	}
	return ans;
}

int main() {
	NSYNC;
	cin >> s;
	reverse(s.begin(),s.end());
	calcsa();
	int q;
	cin >> q;
	int n = s.size();
	while(q--) {
		int x;
		cin >> x;
		cout << lcp(0,n-x) << endl;
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "dreal/dreal_main.h"

#include <iostream>

#include "dreal/dr/run.h"
#include "dreal/smt2/run.h"
#include "dreal/solver/context.h"
#include "dreal/util/exception.h"
#include "dreal/util/filesystem.h"
#include "dreal/util/logging.h"

namespace dreal {

using std::cerr;
using std::endl;
using std::string;
using std::vector;

MainProgram::MainProgram(int argc, const char* argv[]) {
  AddOptions();
  opt_.parse(argc, argv);  // Parse Options
  is_options_all_valid_ = ValidateOptions();
}

void MainProgram::PrintUsage() {
  string usage;
  opt_.getUsage(usage);
  cerr << usage;
}

void MainProgram::AddOptions() {
  opt_.overview =
      "dReal v" + Context::version() + " : delta-complete SMT solver";
  opt_.syntax = "dreal [OPTIONS] <input file> (.smt2 or .dr)";

  // NOTE: Make sure to match the default values specified here with the ones
  // specified in dreal/solver/config.h.
  opt_.add("" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Display usage instructions.", "-h", "-help", "--help", "--usage");

  const double d[1] = {0.0};
  ez::ezOptionValidator* const precision_option_validator =
      new ez::ezOptionValidator(ez::ezOptionValidator::D,
                                ez::ezOptionValidator::GT, d, 1);

  opt_.add("0.001" /* Default */, false /* Required? */,
           1 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Precision (default = 0.001)\n", "--precision",
           precision_option_validator);

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Produce models if delta-sat\n", "--produce-models", "--model");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Debug scanning/lexing\n", "--debug-scanning");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */, "Debug parsing\n",
           "--debug-parsing");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Use polytope contractor.\n", "--polytope");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Use polytope contractor in forall contractor.\n",
           "--forall-polytope");

  ez::ezOptionValidator* const verbose_option_validator =
      new ez::ezOptionValidator(
          "t", "in", "trace,debug,info,warning,error,critical,off", true);
  opt_.add(
      "error",  // Default.
      0,        // Required?
      1,        // Number of args expected.
      0,        // Delimiter if expecting multiple args.
      "Verbosity level. Either one of these (default = error):\n"
      "trace, debug, info, warning, error, critical, off",  // Help description.
      "--verbose",                                          // Flag token.
      verbose_option_validator);
}

bool MainProgram::ValidateOptions() {
  // Checks bad options and bad arguments.
  vector<string> badOptions;
  vector<string> badArgs;
  if (!opt_.gotRequired(badOptions)) {
    for (size_t i = 0; i < badOptions.size(); ++i)
      cerr << "ERROR: Missing required option " << badOptions[i] << ".\n\n";
    PrintUsage();
    return false;
  }
  if (!opt_.gotExpected(badOptions)) {
    for (size_t i = 0; i < badOptions.size(); ++i)
      cerr << "ERROR: Got unexpected number of arguments for option "
           << badOptions[i] << ".\n\n";
    PrintUsage();
    return false;
  }
  if (!opt_.gotValid(badOptions, badArgs)) {
    for (size_t i = 0; i < badOptions.size(); ++i)
      cerr << "ERROR: Got invalid argument \"" << badArgs[i] << "\" for option "
           << badOptions[i] << ".\n\n";
    PrintUsage();
    return false;
  }
  // After filtering out bad options/arguments, save the valid ones in `args_`.
  args_.insert(args_.end(), opt_.firstArgs.begin() + 1, opt_.firstArgs.end());
  args_.insert(args_.end(), opt_.unknownArgs.begin(), opt_.unknownArgs.end());
  args_.insert(args_.end(), opt_.lastArgs.begin(), opt_.lastArgs.end());
  if (opt_.isSet("-h") || args_.size() != 1) {
    PrintUsage();
    return false;
  }
  return true;
}

void MainProgram::ExtractOptions() {
  // Temporary variables used to set options.
  string verbosity;
  double precision{0.0};

  opt_.get("--verbose")->getString(verbosity);
  if (verbosity == "trace") {
    log()->set_level(spdlog::level::trace);
  } else if (verbosity == "debug") {
    log()->set_level(spdlog::level::debug);
  } else if (verbosity == "info") {
    log()->set_level(spdlog::level::info);
  } else if (verbosity == "warning") {
    log()->set_level(spdlog::level::warn);
  } else if (verbosity == "error") {
    log()->set_level(spdlog::level::err);
  } else if (verbosity == "critical") {
    log()->set_level(spdlog::level::critical);
  } else {
    log()->set_level(spdlog::level::off);
  }
  // --precision
  if (opt_.isSet("--precision")) {
    opt_.get("--precision")->getDouble(precision);
    config_.mutable_precision().set_from_command_line(precision);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --precision = {}",
                    config_.precision());
  }
  // --produce-model
  if (opt_.isSet("--produce-models")) {
    config_.mutable_produce_models().set_from_command_line(true);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --produce-models = {}",
                    config_.produce_models());
  }

  // --polytope
  if (opt_.isSet("--polytope")) {
    config_.mutable_use_polytope().set_from_command_line(true);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --polytope = {}",
                    config_.use_polytope());
  }

  // --forall-polytope
  if (opt_.isSet("--forall-polytope")) {
    config_.mutable_use_polytope_in_forall().set_from_command_line(true);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --forall-polytope = {}",
                    config_.use_polytope_in_forall());
  }
}

int MainProgram::Run() {
  if (!is_options_all_valid_) {
    return 1;
  }
  ExtractOptions();
  const string& filename{*args_[0]};
  if (!file_exists(filename)) {
    cerr << "File not found: " << filename << "\n" << endl;
    PrintUsage();
    return 1;
  }
  const string extension{get_extension(filename)};
  if (extension == "smt2") {
    RunSmt2(filename, config_, opt_.isSet("--debug-scanning"),
            opt_.isSet("--debug-parsing"));
  } else if (extension == "dr") {
    RunDr(filename, config_, opt_.isSet("--debug-scanning"),
          opt_.isSet("--debug-parsing"));
  } else {
    cerr << "Unknown extension: " << filename << "\n" << endl;
    PrintUsage();
    return 1;
  }
  return 0;
}
}  // namespace dreal

int main(int argc, const char* argv[]) {
  dreal::MainProgram main_program{argc, argv};
  return main_program.Run();
}
<commit_msg>feat(dreal_main.cc): Mention build type<commit_after>#include "dreal/dreal_main.h"

#include <iostream>

#include "dreal/dr/run.h"
#include "dreal/smt2/run.h"
#include "dreal/solver/context.h"
#include "dreal/util/exception.h"
#include "dreal/util/filesystem.h"
#include "dreal/util/logging.h"

namespace dreal {

using std::cerr;
using std::endl;
using std::string;
using std::vector;

MainProgram::MainProgram(int argc, const char* argv[]) {
  AddOptions();
  opt_.parse(argc, argv);  // Parse Options
  is_options_all_valid_ = ValidateOptions();
}

void MainProgram::PrintUsage() {
  string usage;
  opt_.getUsage(usage);
  cerr << usage;
}

void MainProgram::AddOptions() {
#ifndef NDEBUG
  const string build_type{"Debug"};
#else
  const string build_type{"Release"};
#endif
  opt_.overview =
      fmt::format("dReal v{} ({} Build) : delta-complete SMT solver",
                  Context::version(), build_type);
  opt_.syntax = "dreal [OPTIONS] <input file> (.smt2 or .dr)";

  // NOTE: Make sure to match the default values specified here with the ones
  // specified in dreal/solver/config.h.
  opt_.add("" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Display usage instructions.", "-h", "-help", "--help", "--usage");

  const double d[1] = {0.0};
  ez::ezOptionValidator* const precision_option_validator =
      new ez::ezOptionValidator(ez::ezOptionValidator::D,
                                ez::ezOptionValidator::GT, d, 1);

  opt_.add("0.001" /* Default */, false /* Required? */,
           1 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Precision (default = 0.001)\n", "--precision",
           precision_option_validator);

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Produce models if delta-sat\n", "--produce-models", "--model");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Debug scanning/lexing\n", "--debug-scanning");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */, "Debug parsing\n",
           "--debug-parsing");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Use polytope contractor.\n", "--polytope");

  opt_.add("false" /* Default */, false /* Required? */,
           0 /* Number of args expected. */,
           0 /* Delimiter if expecting multiple args. */,
           "Use polytope contractor in forall contractor.\n",
           "--forall-polytope");

  ez::ezOptionValidator* const verbose_option_validator =
      new ez::ezOptionValidator(
          "t", "in", "trace,debug,info,warning,error,critical,off", true);
  opt_.add(
      "error",  // Default.
      0,        // Required?
      1,        // Number of args expected.
      0,        // Delimiter if expecting multiple args.
      "Verbosity level. Either one of these (default = error):\n"
      "trace, debug, info, warning, error, critical, off",  // Help description.
      "--verbose",                                          // Flag token.
      verbose_option_validator);
}

bool MainProgram::ValidateOptions() {
  // Checks bad options and bad arguments.
  vector<string> badOptions;
  vector<string> badArgs;
  if (!opt_.gotRequired(badOptions)) {
    for (size_t i = 0; i < badOptions.size(); ++i)
      cerr << "ERROR: Missing required option " << badOptions[i] << ".\n\n";
    PrintUsage();
    return false;
  }
  if (!opt_.gotExpected(badOptions)) {
    for (size_t i = 0; i < badOptions.size(); ++i)
      cerr << "ERROR: Got unexpected number of arguments for option "
           << badOptions[i] << ".\n\n";
    PrintUsage();
    return false;
  }
  if (!opt_.gotValid(badOptions, badArgs)) {
    for (size_t i = 0; i < badOptions.size(); ++i)
      cerr << "ERROR: Got invalid argument \"" << badArgs[i] << "\" for option "
           << badOptions[i] << ".\n\n";
    PrintUsage();
    return false;
  }
  // After filtering out bad options/arguments, save the valid ones in `args_`.
  args_.insert(args_.end(), opt_.firstArgs.begin() + 1, opt_.firstArgs.end());
  args_.insert(args_.end(), opt_.unknownArgs.begin(), opt_.unknownArgs.end());
  args_.insert(args_.end(), opt_.lastArgs.begin(), opt_.lastArgs.end());
  if (opt_.isSet("-h") || args_.size() != 1) {
    PrintUsage();
    return false;
  }
  return true;
}

void MainProgram::ExtractOptions() {
  // Temporary variables used to set options.
  string verbosity;
  double precision{0.0};

  opt_.get("--verbose")->getString(verbosity);
  if (verbosity == "trace") {
    log()->set_level(spdlog::level::trace);
  } else if (verbosity == "debug") {
    log()->set_level(spdlog::level::debug);
  } else if (verbosity == "info") {
    log()->set_level(spdlog::level::info);
  } else if (verbosity == "warning") {
    log()->set_level(spdlog::level::warn);
  } else if (verbosity == "error") {
    log()->set_level(spdlog::level::err);
  } else if (verbosity == "critical") {
    log()->set_level(spdlog::level::critical);
  } else {
    log()->set_level(spdlog::level::off);
  }
  // --precision
  if (opt_.isSet("--precision")) {
    opt_.get("--precision")->getDouble(precision);
    config_.mutable_precision().set_from_command_line(precision);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --precision = {}",
                    config_.precision());
  }
  // --produce-model
  if (opt_.isSet("--produce-models")) {
    config_.mutable_produce_models().set_from_command_line(true);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --produce-models = {}",
                    config_.produce_models());
  }

  // --polytope
  if (opt_.isSet("--polytope")) {
    config_.mutable_use_polytope().set_from_command_line(true);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --polytope = {}",
                    config_.use_polytope());
  }

  // --forall-polytope
  if (opt_.isSet("--forall-polytope")) {
    config_.mutable_use_polytope_in_forall().set_from_command_line(true);
    DREAL_LOG_DEBUG("MainProgram::ExtractOptions() --forall-polytope = {}",
                    config_.use_polytope_in_forall());
  }
}

int MainProgram::Run() {
  if (!is_options_all_valid_) {
    return 1;
  }
  ExtractOptions();
  const string& filename{*args_[0]};
  if (!file_exists(filename)) {
    cerr << "File not found: " << filename << "\n" << endl;
    PrintUsage();
    return 1;
  }
  const string extension{get_extension(filename)};
  if (extension == "smt2") {
    RunSmt2(filename, config_, opt_.isSet("--debug-scanning"),
            opt_.isSet("--debug-parsing"));
  } else if (extension == "dr") {
    RunDr(filename, config_, opt_.isSet("--debug-scanning"),
          opt_.isSet("--debug-parsing"));
  } else {
    cerr << "Unknown extension: " << filename << "\n" << endl;
    PrintUsage();
    return 1;
  }
  return 0;
}
}  // namespace dreal

int main(int argc, const char* argv[]) {
  dreal::MainProgram main_program{argc, argv};
  return main_program.Run();
}
<|endoftext|>


<commit_before>//===-- sanitizer_libignore.cc --------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"
#if SANITIZER_LINUX

#include "sanitizer_libignore.h"
#include "sanitizer_procmaps.h"

namespace __sanitizer {

LibIgnore::LibIgnore(LinkerInitialized) {
}

void LibIgnore::Init(const SuppressionContext &supp) {
  BlockingMutexLock lock(&mutex_);
  CHECK_EQ(count_, 0);
  const uptr n = supp.SuppressionCount();
  for (uptr i = 0; i < n; i++) {
    const Suppression *s = supp.SuppressionAt(i);
    if (s->type != SuppressionLib)
      continue;
    if (count_ >= kMaxLibs) {
      Report("%s: too many called_from_lib suppressions (max: %d)\n",
             SanitizerToolName, kMaxLibs);
      Die();
    }
    Lib *lib = &libs_[count_++];
    lib->templ = internal_strdup(s->templ);
    lib->name = 0;
    lib->loaded = false;
  }
}

void LibIgnore::OnLibraryLoaded(const char *name) {
  const char *real_name = 0;
  InternalScopedBuffer<char> buf(4096);
  if (name != 0 && internal_readlink(name, buf.data(), buf.size() - 1) > 0)
    real_name = buf.data();

  BlockingMutexLock lock(&mutex_);
  MemoryMappingLayout proc_maps(/*cache_enabled*/false);
  InternalScopedBuffer<char> fn(4096);
  for (uptr i = 0; i < count_; i++) {
    Lib *lib = &libs_[i];
    bool loaded = false;
    proc_maps.Reset();
    uptr b, e, off, prot;
    while (proc_maps.Next(&b, &e, &off, fn.data(), fn.size(), &prot)) {
      bool symlink = false;
      if (((prot & MemoryMappingLayout::kProtectionExecute) != 0) &&
          (TemplateMatch(lib->templ, fn.data()) ||
          // Resolve symlinks.
          (real_name != 0 && real_name[0] != 0 &&
          TemplateMatch(lib->templ, name) &&
          internal_strcmp(real_name, fn.data()) == 0 &&
          (symlink = true)))) {
        if (loaded) {
          Report("%s: called_from_lib suppression '%s' is matched against"
                 " 2 libraries: '%s' and '%s'\n",
                 SanitizerToolName, lib->templ, lib->name, fn.data());
          Die();
        }
        loaded = true;
        if (!lib->loaded) {
          lib->loaded = true;
          lib->name = internal_strdup(fn.data());
          if (symlink)
            lib->real_name = internal_strdup(real_name);
          const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed);
          code_ranges_[idx].begin = b;
          code_ranges_[idx].end = e;
          atomic_store(&loaded_count_, idx + 1, memory_order_release);
        }
      }
    }
    if (lib->loaded && !loaded) {
      Report("%s: library '%s' that was matched against called_from_lib"
             " suppression '%s' is unloaded\n",
             SanitizerToolName, lib->name, lib->templ);
      Die();
    }
  }
}

void LibIgnore::OnLibraryUnloaded() {
  OnLibraryLoaded(0);
}

}  // namespace __sanitizer

#endif  // #if SANITIZER_LINUX
<commit_msg>tsan: refactor overly-complex logical condition<commit_after>//===-- sanitizer_libignore.cc --------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"
#if SANITIZER_LINUX

#include "sanitizer_libignore.h"
#include "sanitizer_procmaps.h"

namespace __sanitizer {

LibIgnore::LibIgnore(LinkerInitialized) {
}

void LibIgnore::Init(const SuppressionContext &supp) {
  BlockingMutexLock lock(&mutex_);
  CHECK_EQ(count_, 0);
  const uptr n = supp.SuppressionCount();
  for (uptr i = 0; i < n; i++) {
    const Suppression *s = supp.SuppressionAt(i);
    if (s->type != SuppressionLib)
      continue;
    if (count_ >= kMaxLibs) {
      Report("%s: too many called_from_lib suppressions (max: %d)\n",
             SanitizerToolName, kMaxLibs);
      Die();
    }
    Lib *lib = &libs_[count_++];
    lib->templ = internal_strdup(s->templ);
    lib->name = 0;
    lib->loaded = false;
  }
}

void LibIgnore::OnLibraryLoaded(const char *name) {
  const char *real_name = 0;
  InternalScopedBuffer<char> buf(4096);
  if (name != 0 && internal_readlink(name, buf.data(), buf.size() - 1) > 0)
    real_name = buf.data();

  BlockingMutexLock lock(&mutex_);
  MemoryMappingLayout proc_maps(/*cache_enabled*/false);
  InternalScopedBuffer<char> module(4096);
  for (uptr i = 0; i < count_; i++) {
    Lib *lib = &libs_[i];
    bool loaded = false;
    proc_maps.Reset();
    uptr b, e, off, prot;
    while (proc_maps.Next(&b, &e, &off, module.data(), module.size(), &prot)) {
      if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
        continue;
      bool matched = false;
      bool symlink = false;
      if (TemplateMatch(lib->templ, module.data()))
        matched = true;
      // Resolve symlinks.
      if (real_name != 0 && real_name[0] != 0 &&
          TemplateMatch(lib->templ, name) &&
          internal_strcmp(real_name, module.data()) == 0) {
        matched = true;
        symlink = true;
      }
      if (!matched)
        continue;
      if (loaded) {
        Report("%s: called_from_lib suppression '%s' is matched against"
               " 2 libraries: '%s' and '%s'\n",
               SanitizerToolName, lib->templ, lib->name, module.data());
        Die();
      }
      loaded = true;
      if (lib->loaded)
        continue;
      lib->loaded = true;
      lib->name = internal_strdup(module.data());
      if (symlink)
        lib->real_name = internal_strdup(real_name);
      const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed);
      code_ranges_[idx].begin = b;
      code_ranges_[idx].end = e;
      atomic_store(&loaded_count_, idx + 1, memory_order_release);
    }
    if (lib->loaded && !loaded) {
      Report("%s: library '%s' that was matched against called_from_lib"
             " suppression '%s' is unloaded\n",
             SanitizerToolName, lib->name, lib->templ);
      Die();
    }
  }
}

void LibIgnore::OnLibraryUnloaded() {
  OnLibraryLoaded(0);
}

}  // namespace __sanitizer

#endif  // #if SANITIZER_LINUX
<|endoftext|>


<commit_before>// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE

/* This executable is used for testing parser/writer using real JSON files.
 */

#include <json/json.h>
#include <algorithm> // sort
#include <sstream>
#include <stdio.h>

#if defined(_MSC_VER) && _MSC_VER >= 1310
#pragma warning(disable : 4996) // disable fopen deprecation warning
#endif

static std::string normalizeFloatingPointStr(double value) {
  char buffer[32];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
  sprintf_s(buffer, sizeof(buffer), "%.16g", value);
#else
  snprintf(buffer, sizeof(buffer), "%.16g", value);
#endif
  buffer[sizeof(buffer) - 1] = 0;
  std::string s(buffer);
  std::string::size_type index = s.find_last_of("eE");
  if (index != std::string::npos) {
    std::string::size_type hasSign =
        (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
    std::string::size_type exponentStartIndex = index + 1 + hasSign;
    std::string normalized = s.substr(0, exponentStartIndex);
    std::string::size_type indexDigit =
        s.find_first_not_of('0', exponentStartIndex);
    std::string exponent = "0";
    if (indexDigit !=
        std::string::npos) // There is an exponent different from 0
    {
      exponent = s.substr(indexDigit);
    }
    return normalized + exponent;
  }
  return s;
}

static std::string readInputTestFile(const char* path) {
  FILE* file = fopen(path, "rb");
  if (!file)
    return std::string("");
  fseek(file, 0, SEEK_END);
  long size = ftell(file);
  fseek(file, 0, SEEK_SET);
  std::string text;
  char* buffer = new char[size + 1];
  buffer[size] = 0;
  if (fread(buffer, 1, size, file) == (unsigned long)size)
    text = buffer;
  fclose(file);
  delete[] buffer;
  return text;
}

static void
printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
  if (value.hasComment(Json::commentBefore)) {
    fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str());
  }
  switch (value.type()) {
  case Json::nullValue:
    fprintf(fout, "%s=null\n", path.c_str());
    break;
  case Json::intValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            Json::valueToString(value.asLargestInt()).c_str());
    break;
  case Json::uintValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            Json::valueToString(value.asLargestUInt()).c_str());
    break;
  case Json::realValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            normalizeFloatingPointStr(value.asDouble()).c_str());
    break;
  case Json::stringValue:
    fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str());
    break;
  case Json::booleanValue:
    fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false");
    break;
  case Json::arrayValue: {
    fprintf(fout, "%s=[]\n", path.c_str());
    int size = value.size();
    for (int index = 0; index < size; ++index) {
      static char buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
      sprintf_s(buffer, sizeof(buffer), "[%d]", index);
#else
      snprintf(buffer, sizeof(buffer), "[%d]", index);
#endif
      printValueTree(fout, value[index], path + buffer);
    }
  } break;
  case Json::objectValue: {
    fprintf(fout, "%s={}\n", path.c_str());
    Json::Value::Members members(value.getMemberNames());
    std::sort(members.begin(), members.end());
    std::string suffix = *(path.end() - 1) == '.' ? "" : ".";
    for (Json::Value::Members::iterator it = members.begin();
         it != members.end();
         ++it) {
      const std::string& name = *it;
      printValueTree(fout, value[name], path + suffix + name);
    }
  } break;
  default:
    break;
  }

  if (value.hasComment(Json::commentAfter)) {
    fprintf(fout, "%s\n", value.getComment(Json::commentAfter).c_str());
  }
}

static int parseAndSaveValueTree(const std::string& input,
                                 const std::string& actual,
                                 const std::string& kind,
                                 const Json::Features& features,
                                 bool parseOnly,
                                 Json::Value* root) {
  Json::Reader reader(features);
  bool parsingSuccessful = reader.parse(input, *root);
  if (!parsingSuccessful) {
    printf("Failed to parse %s file: \n%s\n",
           kind.c_str(),
           reader.getFormattedErrorMessages().c_str());
    return 1;
  }

  if (!parseOnly) {
    FILE* factual = fopen(actual.c_str(), "wt");
    if (!factual) {
      printf("Failed to create %s actual file.\n", kind.c_str());
      return 2;
    }
    printValueTree(factual, *root);
    fclose(factual);
  }
  return 0;
}

static int rewriteValueTree(const std::string& rewritePath,
                            const Json::Value& root,
                            std::string* rewrite) {
  // Json::FastWriter writer;
  // writer.enableYAMLCompatibility();
  Json::StyledStreamWriter writer;
  std::ostringstream sout;
  writer.write(sout, root);
  *rewrite = sout.str();
  FILE* fout = fopen(rewritePath.c_str(), "wt");
  if (!fout) {
    printf("Failed to create rewrite file: %s\n", rewritePath.c_str());
    return 2;
  }
  fprintf(fout, "%s\n", rewrite->c_str());
  fclose(fout);
  return 0;
}

static std::string removeSuffix(const std::string& path,
                                const std::string& extension) {
  if (extension.length() >= path.length())
    return std::string("");
  std::string suffix = path.substr(path.length() - extension.length());
  if (suffix != extension)
    return std::string("");
  return path.substr(0, path.length() - extension.length());
}

static void printConfig() {
// Print the configuration used to compile JsonCpp
#if defined(JSON_NO_INT64)
  printf("JSON_NO_INT64=1\n");
#else
  printf("JSON_NO_INT64=0\n");
#endif
}

static int printUsage(const char* argv[]) {
  printf("Usage: %s [--strict] input-json-file", argv[0]);
  return 3;
}

int parseCommandLine(int argc,
                     const char* argv[],
                     Json::Features& features,
                     std::string& path,
                     bool& parseOnly) {
  parseOnly = false;
  if (argc < 2) {
    return printUsage(argv);
  }

  int index = 1;
  if (std::string(argv[1]) == "--json-checker") {
    features = Json::Features::strictMode();
    parseOnly = true;
    ++index;
  }

  if (std::string(argv[1]) == "--json-config") {
    printConfig();
    return 3;
  }

  if (index == argc || index + 1 < argc) {
    return printUsage(argv);
  }

  path = argv[index];
  return 0;
}

int main(int argc, const char* argv[]) {
  std::string path;
  Json::Features features;
  bool parseOnly;
  int exitCode = parseCommandLine(argc, argv, features, path, parseOnly);
  if (exitCode != 0) {
    return exitCode;
  }

  try {
    std::string input = readInputTestFile(path.c_str());
    if (input.empty()) {
      printf("Failed to read input or empty input: %s\n", path.c_str());
      return 3;
    }

    std::string basePath = removeSuffix(argv[1], ".json");
    if (!parseOnly && basePath.empty()) {
      printf("Bad input path. Path does not end with '.expected':\n%s\n",
             path.c_str());
      return 3;
    }

    std::string const actualPath = basePath + ".actual";
    std::string const rewritePath = basePath + ".rewrite";
    std::string const rewriteActualPath = basePath + ".actual-rewrite";

    Json::Value root;
    exitCode = parseAndSaveValueTree(
        input, actualPath, "input", features, parseOnly, &root);
    if (exitCode || parseOnly) {
      return exitCode;
    }
    std::string rewrite;
    exitCode = rewriteValueTree(rewritePath, root, &rewrite);
    if (exitCode) {
      return exitCode;
    }
    Json::Value rewriteRoot;
    exitCode = parseAndSaveValueTree(
        rewrite, rewriteActualPath, "rewrite", features, parseOnly, &rewriteRoot);
    if (exitCode) {
      return exitCode;
    }
  }
  catch (const std::exception& e) {
    printf("Unhandled exception:\n%s\n", e.what());
    exitCode = 1;
  }

  return exitCode;
}
<commit_msg>Options class for test<commit_after>// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE

/* This executable is used for testing parser/writer using real JSON files.
 */

#include <json/json.h>
#include <algorithm> // sort
#include <sstream>
#include <stdio.h>

#if defined(_MSC_VER) && _MSC_VER >= 1310
#pragma warning(disable : 4996) // disable fopen deprecation warning
#endif

static std::string normalizeFloatingPointStr(double value) {
  char buffer[32];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
  sprintf_s(buffer, sizeof(buffer), "%.16g", value);
#else
  snprintf(buffer, sizeof(buffer), "%.16g", value);
#endif
  buffer[sizeof(buffer) - 1] = 0;
  std::string s(buffer);
  std::string::size_type index = s.find_last_of("eE");
  if (index != std::string::npos) {
    std::string::size_type hasSign =
        (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
    std::string::size_type exponentStartIndex = index + 1 + hasSign;
    std::string normalized = s.substr(0, exponentStartIndex);
    std::string::size_type indexDigit =
        s.find_first_not_of('0', exponentStartIndex);
    std::string exponent = "0";
    if (indexDigit !=
        std::string::npos) // There is an exponent different from 0
    {
      exponent = s.substr(indexDigit);
    }
    return normalized + exponent;
  }
  return s;
}

static std::string readInputTestFile(const char* path) {
  FILE* file = fopen(path, "rb");
  if (!file)
    return std::string("");
  fseek(file, 0, SEEK_END);
  long size = ftell(file);
  fseek(file, 0, SEEK_SET);
  std::string text;
  char* buffer = new char[size + 1];
  buffer[size] = 0;
  if (fread(buffer, 1, size, file) == (unsigned long)size)
    text = buffer;
  fclose(file);
  delete[] buffer;
  return text;
}

static void
printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
  if (value.hasComment(Json::commentBefore)) {
    fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str());
  }
  switch (value.type()) {
  case Json::nullValue:
    fprintf(fout, "%s=null\n", path.c_str());
    break;
  case Json::intValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            Json::valueToString(value.asLargestInt()).c_str());
    break;
  case Json::uintValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            Json::valueToString(value.asLargestUInt()).c_str());
    break;
  case Json::realValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            normalizeFloatingPointStr(value.asDouble()).c_str());
    break;
  case Json::stringValue:
    fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str());
    break;
  case Json::booleanValue:
    fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false");
    break;
  case Json::arrayValue: {
    fprintf(fout, "%s=[]\n", path.c_str());
    int size = value.size();
    for (int index = 0; index < size; ++index) {
      static char buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
      sprintf_s(buffer, sizeof(buffer), "[%d]", index);
#else
      snprintf(buffer, sizeof(buffer), "[%d]", index);
#endif
      printValueTree(fout, value[index], path + buffer);
    }
  } break;
  case Json::objectValue: {
    fprintf(fout, "%s={}\n", path.c_str());
    Json::Value::Members members(value.getMemberNames());
    std::sort(members.begin(), members.end());
    std::string suffix = *(path.end() - 1) == '.' ? "" : ".";
    for (Json::Value::Members::iterator it = members.begin();
         it != members.end();
         ++it) {
      const std::string& name = *it;
      printValueTree(fout, value[name], path + suffix + name);
    }
  } break;
  default:
    break;
  }

  if (value.hasComment(Json::commentAfter)) {
    fprintf(fout, "%s\n", value.getComment(Json::commentAfter).c_str());
  }
}

static int parseAndSaveValueTree(const std::string& input,
                                 const std::string& actual,
                                 const std::string& kind,
                                 const Json::Features& features,
                                 bool parseOnly,
                                 Json::Value* root)
{
  Json::Reader reader(features);
  bool parsingSuccessful = reader.parse(input, *root);
  if (!parsingSuccessful) {
    printf("Failed to parse %s file: \n%s\n",
           kind.c_str(),
           reader.getFormattedErrorMessages().c_str());
    return 1;
  }

  if (!parseOnly) {
    FILE* factual = fopen(actual.c_str(), "wt");
    if (!factual) {
      printf("Failed to create %s actual file.\n", kind.c_str());
      return 2;
    }
    printValueTree(factual, *root);
    fclose(factual);
  }
  return 0;
}
// static std::string useFastWriter(Json::Value const& root) {
//   Json::FastWriter writer;
//   writer.enableYAMLCompatibility();
//   return writer.write(root);
// }
static std::string useStyledWriter(
    Json::Value const& root)
{
  Json::StyledWriter writer;
  return writer.write(root);
}
static std::string useStyledStreamWriter(
    Json::Value const& root)
{
  Json::StyledStreamWriter writer;
  std::ostringstream sout;
  writer.write(sout, root);
  return sout.str();
}
static int rewriteValueTree(
    const std::string& rewritePath,
    const Json::Value& root,
    std::string* rewrite)
{
  *rewrite = useStyledWriter(root);
  FILE* fout = fopen(rewritePath.c_str(), "wt");
  if (!fout) {
    printf("Failed to create rewrite file: %s\n", rewritePath.c_str());
    return 2;
  }
  fprintf(fout, "%s\n", rewrite->c_str());
  fclose(fout);
  return 0;
}

static std::string removeSuffix(const std::string& path,
                                const std::string& extension) {
  if (extension.length() >= path.length())
    return std::string("");
  std::string suffix = path.substr(path.length() - extension.length());
  if (suffix != extension)
    return std::string("");
  return path.substr(0, path.length() - extension.length());
}

static void printConfig() {
// Print the configuration used to compile JsonCpp
#if defined(JSON_NO_INT64)
  printf("JSON_NO_INT64=1\n");
#else
  printf("JSON_NO_INT64=0\n");
#endif
}

static int printUsage(const char* argv[]) {
  printf("Usage: %s [--strict] input-json-file", argv[0]);
  return 3;
}

struct Options
{
  std::string path;
  Json::Features features;
  bool parseOnly;
};
static int parseCommandLine(
    int argc, const char* argv[], Options* opts)
{
  opts->parseOnly = false;
  if (argc < 2) {
    return printUsage(argv);
  }
  int index = 1;
  if (std::string(argv[1]) == "--json-checker") {
    opts->features = Json::Features::strictMode();
    opts->parseOnly = true;
    ++index;
  }
  if (std::string(argv[1]) == "--json-config") {
    printConfig();
    return 3;
  }
  if (index == argc || index + 1 < argc) {
    return printUsage(argv);
  }
  opts->path = argv[index];
  return 0;
}
static void tryTest(Options const& opts)
{
}
int main(int argc, const char* argv[]) {
  Options opts;
  int exitCode = parseCommandLine(argc, argv, &opts);
  if (exitCode != 0) {
    return exitCode;
  }

  try {
    std::string input = readInputTestFile(opts.path.c_str());
    if (input.empty()) {
      printf("Failed to read input or empty input: %s\n", opts.path.c_str());
      return 3;
    }

    std::string basePath = removeSuffix(argv[1], ".json");
    if (!opts.parseOnly && basePath.empty()) {
      printf("Bad input path. Path does not end with '.expected':\n%s\n",
             opts.path.c_str());
      return 3;
    }

    std::string const actualPath = basePath + ".actual";
    std::string const rewritePath = basePath + ".rewrite";
    std::string const rewriteActualPath = basePath + ".actual-rewrite";

    Json::Value root;
    exitCode = parseAndSaveValueTree(
        input, actualPath, "input",
        opts.features, opts.parseOnly, &root);
    if (exitCode || opts.parseOnly) {
      return exitCode;
    }
    std::string rewrite;
    exitCode = rewriteValueTree(rewritePath, root, &rewrite);
    if (exitCode) {
      return exitCode;
    }
    Json::Value rewriteRoot;
    exitCode = parseAndSaveValueTree(
        rewrite, rewriteActualPath, "rewrite",
        opts.features, opts.parseOnly, &rewriteRoot);
    if (exitCode) {
      return exitCode;
    }
  }
  catch (const std::exception& e) {
    printf("Unhandled exception:\n%s\n", e.what());
    exitCode = 1;
  }

  return exitCode;
}
<|endoftext|>