|
|
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.