|
1
|
1 #pragma once
|
|
|
2 #include "array.h"
|
|
|
3 #include "string_base.h"
|
|
|
4
|
|
|
5 namespace pfc {
|
|
|
6 template<typename t_output, typename t_splitCheck>
|
|
|
7 void splitStringEx(t_output& p_output, const t_splitCheck& p_check, const char* p_string, t_size p_stringLen = SIZE_MAX) {
|
|
|
8 t_size walk = 0, splitBase = 0;
|
|
|
9 const t_size max = strlen_max(p_string, p_stringLen);
|
|
|
10 for (; walk < max;) {
|
|
|
11 t_size delta = p_check(p_string + walk, max - walk);
|
|
|
12 if (delta > 0) {
|
|
|
13 if (walk > splitBase) p_output(p_string + splitBase, walk - splitBase);
|
|
|
14 splitBase = walk + delta;
|
|
|
15 } else {
|
|
|
16 delta = utf8_char_len(p_string + walk, max - walk);
|
|
|
17 if (delta == 0) break;
|
|
|
18 }
|
|
|
19 walk += delta;
|
|
|
20 }
|
|
|
21 if (walk > splitBase) p_output(p_string + splitBase, walk - splitBase);
|
|
|
22 }
|
|
|
23
|
|
|
24 class __splitStringSimple_calculateSubstringCount {
|
|
|
25 public:
|
|
|
26 __splitStringSimple_calculateSubstringCount() : m_count() {}
|
|
|
27 void operator() (const char*, t_size) { ++m_count; }
|
|
|
28 t_size get() const { return m_count; }
|
|
|
29 private:
|
|
|
30 t_size m_count;
|
|
|
31 };
|
|
|
32
|
|
|
33 template<typename t_param> class _splitStringSimple_check;
|
|
|
34
|
|
|
35 template<> class _splitStringSimple_check<const char*> {
|
|
|
36 public:
|
|
|
37 _splitStringSimple_check(const char* p_chars) {
|
|
|
38 m_chars.set_size(strlen_utf8(p_chars));
|
|
|
39 for (t_size walk = 0, ptr = 0; walk < m_chars.get_size(); ++walk) {
|
|
|
40 ptr += utf8_decode_char(p_chars + ptr, m_chars[walk]);
|
|
|
41 }
|
|
|
42 }
|
|
|
43 t_size operator()(const char* p_string, t_size p_stringLen) const {
|
|
|
44 t_uint32 c;
|
|
|
45 t_size delta = utf8_decode_char(p_string, c, p_stringLen);
|
|
|
46 if (delta > 0) {
|
|
|
47 for (t_size walk = 0; walk < m_chars.get_size(); ++walk) {
|
|
|
48 if (m_chars[walk] == c) return delta;
|
|
|
49 }
|
|
|
50 }
|
|
|
51 return 0;
|
|
|
52 }
|
|
|
53 private:
|
|
|
54 array_t<t_uint32> m_chars;
|
|
|
55 };
|
|
|
56 template<> class _splitStringSimple_check<char> {
|
|
|
57 public:
|
|
|
58 _splitStringSimple_check(char c) : m_char(c) {}
|
|
|
59 t_size operator()(const char* str, t_size len) const {
|
|
|
60 PFC_ASSERT(len > 0); (void)len;
|
|
|
61 if (*str == m_char) return 1;
|
|
|
62 else return 0;
|
|
|
63 }
|
|
|
64 private:
|
|
|
65 const char m_char;
|
|
|
66 };
|
|
|
67 template<typename t_array>
|
|
|
68 class __splitStringSimple_arrayWrapper {
|
|
|
69 public:
|
|
|
70 __splitStringSimple_arrayWrapper(t_array& p_array) : m_walk(), m_array(p_array) {}
|
|
|
71 void operator()(const char* p_string, t_size p_stringLen) {
|
|
|
72 m_array[m_walk++] = string_part(p_string, p_stringLen);
|
|
|
73 }
|
|
|
74 private:
|
|
|
75 t_size m_walk;
|
|
|
76 t_array& m_array;
|
|
|
77 };
|
|
|
78 template<typename t_list>
|
|
|
79 class __splitStringSimple_listWrapper {
|
|
|
80 public:
|
|
|
81 __splitStringSimple_listWrapper(t_list& p_list) : m_list(p_list) {}
|
|
|
82 void operator()(const char* p_string, t_size p_stringLen) {
|
|
|
83 m_list += string_part(p_string, p_stringLen);
|
|
|
84 }
|
|
|
85 private:
|
|
|
86 t_list& m_list;
|
|
|
87 };
|
|
|
88
|
|
|
89 template<typename t_array, typename t_split>
|
|
|
90 void splitStringSimple_toArray(t_array& p_output, t_split p_split, const char* p_string, t_size p_stringLen = SIZE_MAX) {
|
|
|
91 _splitStringSimple_check<t_split> strCheck(p_split);
|
|
|
92
|
|
|
93 {
|
|
|
94 __splitStringSimple_calculateSubstringCount wrapper;
|
|
|
95 splitStringEx(wrapper, strCheck, p_string, p_stringLen);
|
|
|
96 p_output.set_size(wrapper.get());
|
|
|
97 }
|
|
|
98
|
|
|
99 {
|
|
|
100 __splitStringSimple_arrayWrapper<t_array> wrapper(p_output);
|
|
|
101 splitStringEx(wrapper, strCheck, p_string, p_stringLen);
|
|
|
102 }
|
|
|
103 }
|
|
|
104 template<typename t_list, typename t_split>
|
|
|
105 void splitStringSimple_toList(t_list& p_output, t_split p_split, const char* p_string, t_size p_stringLen = SIZE_MAX) {
|
|
|
106 _splitStringSimple_check<t_split> strCheck(p_split);
|
|
|
107
|
|
|
108 __splitStringSimple_listWrapper<t_list> wrapper(p_output);
|
|
|
109 splitStringEx(wrapper, strCheck, p_string, p_stringLen);
|
|
|
110 }
|
|
|
111
|
|
|
112 template<typename t_out> void splitStringByLines(t_out& out, const char* str) {
|
|
|
113 for (;;) {
|
|
|
114 const char* next = strchr(str, '\n');
|
|
|
115 if (next == NULL) {
|
|
|
116 out += string_part(str, strlen(str)); break;
|
|
|
117 }
|
|
|
118 const char* walk = next;
|
|
|
119 while (walk > str && walk[-1] == '\r') --walk;
|
|
|
120 out += string_part(str, walk - str);
|
|
|
121 str = next + 1;
|
|
|
122 }
|
|
|
123 }
|
|
|
124 template<typename t_out> void splitStringByChar(t_out& out, const char* str, char c) {
|
|
|
125 for (;;) {
|
|
|
126 const char* next = strchr(str, c);
|
|
|
127 if (next == NULL) {
|
|
|
128 out += string_part(str, strlen(str)); break;
|
|
|
129 }
|
|
|
130 out += string_part(str, next - str);
|
|
|
131 str = next + 1;
|
|
|
132 }
|
|
|
133 }
|
|
|
134 template<typename t_out> void splitStringBySubstring(t_out& out, const char* str, const char* split) {
|
|
|
135 for (;;) {
|
|
|
136 const char* next = strstr(str, split);
|
|
|
137 if (next == NULL) {
|
|
|
138 out += string_part(str, strlen(str)); break;
|
|
|
139 }
|
|
|
140 out += string_part(str, next - str);
|
|
|
141 str = next + strlen(split);
|
|
|
142 }
|
|
|
143 }
|
|
|
144 }
|