1 module yu..string;
2 
3 import std.array;
4 import std.string;
5 import std.traits;
6 import std.range;
7 import std.experimental.allocator.common;
8 
9 void splitNameValue(TChar, Char, bool caseSensitive = true)(TChar[] data,
10     in Char pDelim, in Char vDelim, scope bool delegate(TChar[], TChar[]) callback) if (
11         isSomeChar!(Unqual!TChar) && isSomeChar!(Unqual!Char)) {
12     enum size_t blen = 1;
13     enum size_t elen = 1;
14     const dchar pairDelim = pDelim;
15     const dchar valueDelim = vDelim;
16 
17     mixin(TSplitNameValue!());
18 }
19 
20 void splitNameValue(TChar, Char, bool caseSensitive = true)(TChar[] data,
21     const(Char)[] pairDelim, const(Char)[] valueDelim, scope bool delegate(TChar[],
22     TChar[]) callback) if (isSomeChar!(Unqual!TChar) && isSomeChar!(Unqual!Char)) {
23     const size_t blen = pairDelim.length;
24     const size_t elen = valueDelim.length;
25 
26     mixin(TSplitNameValue!());
27 
28 }
29 
30 bool isSameIngnoreLowUp(TChar)(TChar[] s1, TChar[] s2) if (isSomeChar!(Unqual!TChar)) {
31     import std.uni;
32 
33     if (s1.length != s2.length)
34         return false;
35     for (size_t i = 0; i < s1.length; ++i) {
36         dchar c1 = toLower(s1[i]);
37         dchar c2 = toLower(s2[i]);
38         if (c1 != c2)
39             return false;
40     }
41     return true;
42 }
43 
44 @trusted struct CStr(Alloc) {
45     enum isStaticAlloc = (stateSize!Alloc == 0);
46     @disable this();
47     @disable this(this);
48 
49     static if (isStaticAlloc) {
50         this(string str) {
51             setString(str);
52         }
53     } else {
54         this(string str, Alloc alloc) {
55             _alloc = alloc;
56             setString(str);
57         }
58     }
59 
60     ~this() {
61         if (_data.ptr !is null)
62             _alloc.deallocate(_data);
63     }
64 
65     @property const(char*) ptr() const nothrow{
66         return _data.ptr;
67     }
68 
69     @property length() const nothrow {
70         return _data.length;
71     }
72 
73 private:
74     void setString(string str) {
75         import core.stdc.string;
76 
77         if (str.length == 0)
78             return;
79         size_t size = str.length + 1;
80         _data = cast(char[]) _alloc.allocate(size);
81         if (_data.length == 0)
82             return;
83         memcpy(_data.ptr, str.ptr, str.length);
84         _data[str.length] = '\0';
85     }
86 
87     static if (isStaticAlloc)
88         alias _alloc = Alloc.instance;
89     else
90         Alloc _alloc;
91     char[] _data;
92 }
93 
94 @safe ubyte formHex(in char[2] chs) {
95     import std.uri;
96 
97     ubyte charToByte(dchar ch) {
98         switch (ch) {
99         case '0':
100             return 0x00;
101         case '1':
102             return 0x01;
103         case '2':
104             return 0x02;
105         case '3':
106             return 0x03;
107         case '4':
108             return 0x04;
109         case '5':
110             return 0x05;
111         case '6':
112             return 0x06;
113         case '7':
114             return 0x07;
115         case '8':
116             return 0x08;
117         case '9':
118             return 0x09;
119         case 'A':
120             return 0x0A; // 10
121         case 'B':
122             return 0x0B; // 11
123         case 'C':
124             return 0x0C; // 12
125         case 'D':
126             return 0x0D; // 13
127         case 'E':
128             return 0x0E; // 14
129         case 'F':
130             return 0x0F; // 15
131         default:
132             throw new StringException("Hex char is inVaild!");
133         }
134     }
135 
136     import std.uni;
137 
138     dchar ch = toUpper(chs[0]);
139     ubyte frist = charToByte(ch);
140     ch = toUpper(chs[1]);
141     ubyte seced = charToByte(ch);
142     return cast(ubyte)((frist << 4) | seced);
143 }
144 
145 
146 private template TSplitNameValue() {
147     enum TSplitNameValue = q{
148 		static if(caseSensitive)
149 			enum thecaseSensitive = CaseSensitive.yes;
150 		else
151 			enum thecaseSensitive = CaseSensitive.no;
152 		while(data.length > 0)
153 		{
154 			auto index = data.indexOf(pairDelim,thecaseSensitive);
155 			string keyValue;
156 			if(index < 0){
157 				keyValue = data;
158 				data.length = 0;
159 			} else {
160 				keyValue = data[0..index];
161 				data = data[(index + blen) .. $];
162 			}
163 			if(keyValue.length == 0)
164 				continue;
165 			auto valueDelimPos = keyValue.indexOf(valueDelim,thecaseSensitive);
166 			if(valueDelimPos < 0){
167 				if(!callback(keyValue,string.init))
168 					return;
169 			} else {
170 				auto name = keyValue[0..valueDelimPos];
171 				auto value = keyValue[(valueDelimPos + elen)..$];
172 				if(!callback(name,value))
173 					return;
174 			}
175 		}
176 	};
177 }
178 
179 unittest {
180     import std.stdio;
181 
182     string hh = "ggujg=wee&ggg=ytgy&ggg0HH&hjkhk=00";
183     string hh2 = "ggujg$=wee&$ggg=ytgy&$ggg0HH&hjkhk$=00";
184 
185     splitNameValue!(immutable char, char)(hh, '&', '=', (string key, string value) {
186         writeln("1.   ", key, "  ", value);
187         return true;
188     });
189 
190     splitNameValue!(immutable char, char)(hh2, "&$", "$=", (string key, string value) {
191         writeln("2.   ", key, "  ", value);
192         return true;
193     });
194 
195     writeln(isSameIngnoreLowUp("AAA12345", "aaa12345"));
196 }