Annotation of nono/lib/test_mystring.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2021 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: 
        !             8: #include <vector>
        !             9: #include <tuple>
        !            10: #include <functional>
        !            11: #include "mystring.h"
        !            12: 
        !            13: // デバッグ文字列を返す
        !            14: // プリミティブ型
        !            15: template <class T>
        !            16: std::string
        !            17: ToDebugString(T x) {
        !            18:        return std::to_string(x);
        !            19: }
        !            20: 
        !            21: // デバッグ文字列を返す
        !            22: // bool 型
        !            23: static std::string
        !            24: ToDebugString(bool x)
        !            25: {
        !            26:        return x ? "true" : "false";
        !            27: }
        !            28: 
        !            29: // デバッグ文字列を返す
        !            30: // string 型
        !            31: static std::string
        !            32: ToDebugString(const std::string& x)
        !            33: {
        !            34:        std::string rv { '"' };
        !            35:        // TODO: escape
        !            36:        rv += x;
        !            37:        rv += '"';
        !            38:        return rv;
        !            39: }
        !            40: 
        !            41: static std::string
        !            42: ToDebugString(const char *x)
        !            43: {
        !            44:        return ToDebugString(std::string { x });
        !            45: }
        !            46: 
        !            47: // Tuple with ToDebugString
        !            48: 
        !            49: // 前方宣言
        !            50: template <class... Args>
        !            51: class TestTuple;
        !            52: 
        !            53: // デバッグ文字列を返す
        !            54: // TestTuple 型
        !            55: template <class... Args>
        !            56: std::string
        !            57: ToDebugString(const TestTuple<Args...>& x)
        !            58: {
        !            59:        return x.ToDebugString();
        !            60: }
        !            61: 
        !            62: // オレオレタプル
        !            63: template <class... Args>
        !            64: class TestTuple : public std::tuple<Args...>
        !            65: {
        !            66:        // 継承コンストラクタ宣言
        !            67:        using std::tuple<Args...>::tuple;
        !            68: 
        !            69:  public:
        !            70:        // デバッグ文字列を返す
        !            71:        std::string ToDebugString() const {
        !            72:                return ToD(std::index_sequence_for<Args...>{});
        !            73:        }
        !            74: 
        !            75:        // std::get のメンバ関数化
        !            76:        // 型が決まらないといけないので [] には出来ない。
        !            77:        template <size_t i>
        !            78:        auto get() const {
        !            79:                return std::get<i>(*this);
        !            80:        }
        !            81: 
        !            82:  private:
        !            83:        // このへん参照
        !            84:        // https://theolizer.com/cpp-school2/cpp-school2-21/
        !            85: 
        !            86:        template <size_t... indices>
        !            87:        std::string ToD(std::index_sequence<indices...>) const {
        !            88:                // get<> にはテンプレート引数を渡さないといけないので
        !            89:                // 配列要素数がコンパイル時展開になるようにする。
        !            90:                // これでタプルの各要素が型ごとに異なる ToDebugString()
        !            91:                // の実体関数を呼び出して、結果の文字列が配列に入っている
        !            92:                // 状態になる、ようだ。
        !            93:                std::string a[] = {
        !            94:                        (::ToDebugString(get<indices>()))...
        !            95:                };
        !            96: 
        !            97:                // a[] をよしなに連結すれば良い
        !            98:                std::string rv { '{' };
        !            99:                bool first = true;
        !           100:                for (const auto& s : a) {
        !           101:                        if (first) {
        !           102:                                first = false;
        !           103:                        } else {
        !           104:                                rv += ',';
        !           105:                        }
        !           106:                        rv += s;
        !           107:                }
        !           108:                rv += '}';
        !           109:                return rv;
        !           110:        }
        !           111: };
        !           112: 
        !           113: // テストデータ用テーブル
        !           114: template <class... Args>
        !           115: class TestTable : public std::vector<TestTuple<Args...> >
        !           116: {
        !           117:        // 継承コンストラクタ宣言
        !           118:        using std::vector<TestTuple<Args... > >::vector;
        !           119: };
        !           120: 
        !           121: 
        !           122: // Test
        !           123: 
        !           124: class TestClass
        !           125: {
        !           126:  public:
        !           127:        virtual ~TestClass() {}
        !           128: 
        !           129:        template <class T, class R>
        !           130:        void Fail(T expectobj, R real) {
        !           131:                printf("Failed at: %s but %s\n",
        !           132:                        ToDebugString(expectobj).c_str(),
        !           133:                        ToDebugString(real).c_str());
        !           134:                exit(1);
        !           135:        }
        !           136: 
        !           137:        void Test() {
        !           138:                Init();
        !           139: 
        !           140:                for (auto&& t : testlist) {
        !           141:                        printf("Testing: %s ", t.name.c_str());
        !           142:                        t.func();
        !           143:                        printf("Ok\n");
        !           144:                }
        !           145:        }
        !           146: 
        !           147:  protected:
        !           148:        // 継承して、TESTDEF マクロを使って testlist を作ってください。
        !           149:        virtual void Init() = 0;
        !           150: 
        !           151:        // テスト関数のリスト
        !           152:        class Entry {
        !           153:         public:
        !           154:                std::string name;
        !           155:                std::function<void(void)> func;
        !           156:        };
        !           157:        std::vector<Entry> testlist;
        !           158: 
        !           159: #define TESTDEF(x) testlist.push_back({ #x, [&]() { x(); } })
        !           160: 
        !           161: 
        !           162:        template <class T, class TWhere>
        !           163:        void xp_eq(T expect, T actual, const TWhere& where)
        !           164:        {
        !           165:                // eq なので == で比較。演算子オーバーロード対策。
        !           166:                if (expect == actual) {
        !           167:                        return;
        !           168:                }
        !           169: 
        !           170:                Fail(where, actual);
        !           171:        }
        !           172: };
        !           173: 
        !           174: class Test_MyString : public TestClass
        !           175: {
        !           176:  protected:
        !           177:        void Init() override {
        !           178:                // TESTDEF マクロに、テスト実行関数の識別子を渡します。
        !           179:                TESTDEF(startwith_ignorecase_1);
        !           180:                TESTDEF(string_ltrim_1);
        !           181:        }
        !           182: 
        !           183:        void startwith_ignorecase_1() {
        !           184:                TestTable<std::string, std::string, bool> table = {
        !           185:                        { "ABCDEF", "A", true },
        !           186:                        { "ABCDEF", "B", false },
        !           187:                        { "ABCDEF", "AB", true },
        !           188:                        { "ABCDEF", "BC", false },
        !           189:                        { "ABCDEF", "a", true },
        !           190:                        { "ABCDEF", "b", false },
        !           191:                        { "ABCDEF", "ab", true },
        !           192:                        { "ABCDEF", "bc", false },
        !           193:                        { "aBCDEF", "a", true },
        !           194:                        { "aBCDEF", "b", false },
        !           195:                        { "aBCDEF", "ab", true },
        !           196:                        { "aBCDEF", "ABcd", true },
        !           197:                        { "", "A", false },
        !           198:                        { "", "", true },       // ??? これはまだわかる
        !           199:                        { "A", "", true },      // ??? 概念的には true だが果たして?
        !           200:                };
        !           201: 
        !           202:                for (auto t : table) {
        !           203:                        auto arg0 = t.get<0>();
        !           204:                        auto arg1 = t.get<1>();
        !           205:                        auto expect = t.get<2>();
        !           206: 
        !           207:                        xp_eq(expect, starts_with_ignorecase(arg0, arg1), t);
        !           208:                }
        !           209:        }
        !           210: 
        !           211:        void string_ltrim_1()
        !           212:        {
        !           213:                Fail("NOT IMPL", "");
        !           214:        }
        !           215: };
        !           216: 
        !           217: int
        !           218: main(int ac, char *av[])
        !           219: {
        !           220:        printf("compiled by ");
        !           221: #if defined(__clang_version__)
        !           222:        printf("clang %s", __clang_version__);
        !           223: #elif defined(__GNUC__) && defined(__VERSION__)
        !           224:        printf("gcc %s", __VERSION__);
        !           225: #else
        !           226:        printf("unknown compiler");
        !           227: #endif
        !           228:        printf("\n");
        !           229: 
        !           230:        Test_MyString{}.Test();
        !           231:        return 0;
        !           232: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.