|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.