Changeset 37
- Timestamp:
- 02/21/08 15:14:27 (11 months ago)
- Files:
-
- trunk/doost/core/Traits.d (modified) (1 diff)
- trunk/doost/storage (added)
- trunk/doost/storage/FileStorage.d (added)
- trunk/doost/storage/Storage.d (added)
- trunk/doost/text/Escaper.d (modified) (5 diffs)
- trunk/doost/text/Scanner.d (added)
- trunk/doost/text/Tokenizer.d (deleted)
- trunk/doost/util/DUnit.d (modified) (15 diffs)
- trunk/doost/util/serializer/Serializer.d (modified) (7 diffs)
- trunk/doost/util/serializer/archive/JsonArchive.d (modified) (36 diffs)
- trunk/doost/util/serializer/archive/TextArchive.d (modified) (39 diffs)
- trunk/examples/text/FunctionTest.d (deleted)
- trunk/examples/text/PackageTest.d (added)
- trunk/examples/text/text.cbp (modified) (3 diffs)
- trunk/examples/util/serializer/FunctionTest.d (modified) (13 diffs)
- trunk/examples/util/serializer/FunctionTest1.d (modified) (4 diffs)
- trunk/examples/util/serializer/util_serializer.cbp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/doost/core/Traits.d
r32 r37 37 37 else 38 38 static assert(false, "'" ~ T.stringof ~ "' is not an array."); 39 }40 41 /*******************************************************************************42 Evaluates to type of array element43 ******************************************************************************/44 //TODO: checki na speÅnianie wymagaÅ co do array45 template elementType(T) {46 static if( is( T U : U[] ) ) {47 pragma(msg, "elementType: " ~ T.stringof ~ " -> " ~ U.stringof);48 alias U elementType;49 } else50 static if( is( typeof(T.get(1u)) U == U[]) ) {51 pragma(msg, "elementType: " ~ T.stringof ~ " -> " ~ U.stringof);52 alias U elementType;53 } else54 static assert(false, "'" ~ T.stringof ~ "' can not be threated as array.");55 39 } 56 40 trunk/doost/text/Escaper.d
r31 r37 1 /******************************************************************************* 2 3 License: Boost Software License, v. 1.0 4 Academic Free License, v. 3.0 5 BSD License 6 7 Authors: Marcin Kuszczak, www.zapytajmnie.com (author's christian site) 8 9 Version: 0.9.0 10 Date: 18 Jan 2008 11 12 History: 0.9.0 - initial public beta version 13 14 ******************************************************************************/ 15 1 16 module doost.text.Escaper; 2 17 18 import std.stdio; 19 20 import doost.util.DUnit; 3 21 import doost.core.Traits; 4 import std.stdio; 5 import doost.util.DUnit; 6 7 //------------------------------------------------------------------------------ 8 9 //TODO: add other escape sequences from: http://www.digitalmars.com/d/lex.html 10 11 22 import doost.text.Scanner; 23 24 import doost.storage.Storage; 25 26 //------------------------------------------------------------------------------ 27 28 unittest { 29 testSuite.timing.width(100).repeat(1).begin("Escaper module"); 30 } 31 32 //------------------------------------------------------------------------------ 33 34 /******************************************************************************* 35 ******************************************************************************/ 12 36 class UnescapeException : Exception { 13 37 this(string str) { … … 16 40 } 17 41 42 //------------------------------------------------------------------------------ 43 18 44 /******************************************************************************* 45 Params: 46 full = replaces also characters using named characters (slower) 19 47 ******************************************************************************/ 20 T escape(T)(T str) {48 T escape(T)(T input, bool full = false) { 21 49 static assert(isString!(T), "Only unicode strings allowed"); 22 50 51 uint pos; 52 Matcher m; 53 T result; 54 55 while(!input.eos(pos)) { 56 m = scan(input, SequenceSet!(T).escchar, pos); 57 58 if (cast(bool)m) { 59 result ~= input.get(pos); 60 input.get(m.position - pos); 61 62 result ~= '\\' ~ SequenceSet!(T).escseq.matching(m); 63 pos = 0; 64 continue; 65 } 66 67 if (full) { 68 m = scan(input, SequenceSet!(T).namedchar, pos); 69 70 if (cast(bool)m) { 71 result ~= input.get(pos); 72 input.get(m.position - pos); 73 74 result ~= r"\&" ~ SequenceSet!(T).namedseq.matching(m); 75 pos = 0; 76 continue; 77 } 78 } 79 80 ++pos; 81 } 82 83 result ~= input.get(pos); 84 85 return result; 86 } 87 88 //------------------------------------------------------------------------------ 89 90 T escapeOld(T)(T input, bool full = false) { 91 //poniÅŒsze jest 5x szybsze niÅŒ nowa implementacja 23 92 T result; 24 foreach(c; str) {93 foreach(c; input) { 25 94 switch (c) { 26 95 case '\\' : result ~= "\\\\"; break; … … 43 112 //------------------------------------------------------------------------------ 44 113 114 unittest { testCase.repeat(1).execute("basic escape characters", { 115 assert(escape("\""[]) == "\\\""); 116 assert(escape("\?"[]) == "\\?"); 117 assert(escape("\\"[]) == "\\\\"); 118 assert(escape("\a"[]) == "\\a"); 119 assert(escape("\b"[]) == "\\b"); 120 assert(escape("\f"[]) == "\\f"); 121 assert(escape("\n"[]) == "\\n"); 122 assert(escape("\r"[]) == "\\r"); 123 assert(escape("\t"[]) == "\\t"); 124 assert(escape("\v"[]) == "\\v"); 125 });} 126 127 //------------------------------------------------------------------------------ 128 129 unittest { testCase.repeat(1).execute("basic old implementation escape characters", { 130 assert(escapeOld("\""[]) == "\\\""); 131 assert(escapeOld("\?"[]) == "\\?"); 132 assert(escapeOld("\\"[]) == "\\\\"); 133 assert(escapeOld("\a"[]) == "\\a"); 134 assert(escapeOld("\b"[]) == "\\b"); 135 assert(escapeOld("\f"[]) == "\\f"); 136 assert(escapeOld("\n"[]) == "\\n"); 137 assert(escapeOld("\r"[]) == "\\r"); 138 assert(escapeOld("\t"[]) == "\\t"); 139 assert(escapeOld("\v"[]) == "\\v"); 140 });} 141 142 //------------------------------------------------------------------------------ 143 144 unittest { testCase.execute("escape with named characters", { 145 //full escape with named characters 146 assert(escape("\♥"[], true) == r"\♥"); 147 assert(escape("\∅"[], true) == r"\∅"); 148 assert(escape("\∑"[], true) == r"\∑"); 149 });} 150 151 //------------------------------------------------------------------------------ 152 153 private uint toDec(dchar c) { 154 uint code = c; 155 if (code >= 0x61) code -= 0x57; 156 if (code >= 0x41) code -= 0x37; 157 if (code >= 0x30) code -= 0x30; 158 return code; 159 } 160 161 private uint[] maxsize = [0u, 255, 65535, 4228250625]; 162 45 163 /******************************************************************************* 46 164 ******************************************************************************/ 47 T unescape(T)(T str) { 48 static assert(isString!(T), "Only unicode strings allowed"); 49 50 T result; 165 //TODO: speed optimalization 166 T unescape(T)(T input) { 167 // static assert(isString!(T), "Only unicode strings allowed"); 168 169 uint pos; 170 Matcher m; 171 T result; 172 T seq; 173 174 while(!input.eos(pos)) { 175 m = scanEscapeSequence(input, pos); 176 if (cast(bool)m) { 177 result ~= input.get(pos); 178 seq = input.get(m.position - pos); 179 180 switch (seq[1]) { 181 //NOTE: is below interpretation of escape characters same as in DMD? 182 case 'x': //2 hex digits 183 result ~= cast(StorageElementType!(T))(toDec(seq[2])*16 + toDec(seq[3])); 184 break; 185 case '0', '1', '2', '3', '4', '5', '6', '7' : //1 to 3 octal digits 186 uint code; 187 188 if (seq.length == 4) 189 code = toDec(seq[1])*64 + toDec(seq[2])*8 +toDec(seq[3]); 190 else 191 if (seq.length == 3) 192 code = toDec(seq[1])*8 +toDec(seq[2]); 193 else 194 if (seq.length == 2) 195 code = toDec(seq[1]); 196 197 if (code > maxsize[StorageElementType!(T).sizeof]) throw new UnescapeException("Octal representation out of character range!"); 198 result ~= cast(StorageElementType!(T))code; 199 break; 200 case 'u': //4 hex digits 201 result ~= cast(StorageElementType!(T))(toDec(seq[2])*16 + toDec(seq[3])); 202 result ~= cast(StorageElementType!(T))(toDec(seq[4])*16 + toDec(seq[5])); 203 break; 204 case 'U': //8 hex digits 205 result ~= cast(StorageElementType!(T))(toDec(seq[2])*16 + toDec(seq[3])); 206 result ~= cast(StorageElementType!(T))(toDec(seq[4])*16 + toDec(seq[5])); 207 result ~= cast(StorageElementType!(T))(toDec(seq[6])*16 + toDec(seq[7])); 208 result ~= cast(StorageElementType!(T))(toDec(seq[8])*16 + toDec(seq[9])); 209 break; 210 case '&': //named character 211 result ~= SequenceSet!(StorageType!(T)).namedchar.matching(m); 212 break; 213 default: //regular esc char 214 result ~= SequenceSet!(StorageType!(T)).escchar.matching(m); 215 break; 216 } 217 218 pos = 0; 219 continue; 220 } 221 222 if (m.status == Matcher.syntax_error || (m.status == Matcher.missing_input && m.position > pos)) 223 throw new UnescapeException("Unknown escape sequence!"); //TODO: lepsze komunikaty o bÅÄdach (ogólnie) 224 ++pos; 225 } 226 227 result ~= input.get(pos); 228 229 return result; 230 } 231 232 //------------------------------------------------------------------------------ 233 234 T unescapeOld(T)(T input) { 235 //PoniÅŒsze jest 6,22 razy szybsze niÅŒ nowa implementacja 236 T result; 51 237 bool isEscape=false; 52 238 53 foreach(c; str) {239 foreach(c; input) { 54 240 if (isEscape==true) { 55 241 switch (c) { … … 64 250 case 't' : result ~= '\t'; break; 65 251 case 'v' : result ~= '\v'; break; 66 default: throw new UnescapeException("Illegal escape character"); 252 case '\\' : result ~= '\\'; break; 253 default: throw new UnescapeException("Illegal escape character: \\" ~ c); 67 254 } 68 255 isEscape=false; … … 79 266 return result; 80 267 } 268 269 //------------------------------------------------------------------------------ 270 271 unittest { testCase.repeat(1).execute("unescape basic characters", { 272 assert(unescape("\\\\"[]) == "\\"); 273 assert(unescape("\\\""[]) == "\""); 274 assert(unescape("\\?"[]) == "\?"); 275 assert(unescape("\\a"[]) == "\a"); 276 assert(unescape("\\b"[]) == "\b"); 277 assert(unescape("\\f"[]) == "\f"); 278 assert(unescape("\\n"[]) == "\n"); 279 assert(unescape("\\r"[]) == "\r"); 280 assert(unescape("\\t"[]) == "\t"); 281 assert(unescape("\\v"[]) == "\v"); 282 283 assert(unescape(r"\\\\\\\\ abc \\t\\n\\t \\t"[]) == r"\\\\ abc \t\n\t \t"); 284 });} 285 286 //------------------------------------------------------------------------------ 287 288 unittest { testCase.repeat(1).execute("unescape stream wrapper", { 289 DummyStorage!(string) storage; 290 291 //storage.input = "\\\\"; assert(unescape(storage).output == "\\"); 292 assert(unescape("\\\""[]) == "\""); 293 assert(unescape("\\?"[]) == "\?"); 294 assert(unescape("\\a"[]) == "\a"); 295 assert(unescape("\\b"[]) == "\b"); 296 assert(unescape("\\f"[]) == "\f"); 297 assert(unescape("\\n"[]) == "\n"); 298 assert(unescape("\\r"[]) == "\r"); 299 assert(unescape("\\t"[]) == "\t"); 300 assert(unescape("\\v"[]) == "\v"); 301 302 assert(unescape(r"\\\\\\\\ abc \\t\\n\\t \\t"[]) == r"\\\\ abc \t\n\t \t"); 303 });} 304 305 //------------------------------------------------------------------------------ 306 307 unittest { testCase.repeat(1).execute("unescape basic characters old implementation", { 308 assert(unescapeOld("\\\\"[]) == "\\"); 309 assert(unescapeOld("\\\""[]) == "\""); 310 assert(unescapeOld("\\?"[]) == "\?"); 311 assert(unescapeOld("\\a"[]) == "\a"); 312 assert(unescapeOld("\\b"[]) == "\b"); 313 assert(unescapeOld("\\f"[]) == "\f"); 314 assert(unescapeOld("\\n"[]) == "\n"); 315 assert(unescapeOld("\\r"[]) == "\r"); 316 assert(unescapeOld("\\t"[]) == "\t"); 317 assert(unescapeOld("\\v"[]) == "\v"); 318 319 assert(unescapeOld(r"\\\\\\\\ abc \\t\\n\\t \\t"[]) == r"\\\\ abc \t\n\t \t"); 320 });} 321 322 //------------------------------------------------------------------------------ 323 324 unittest { testCase.execute("unescape extended characters", { 325 // 2 characters hexadecimal test (\x) 326 assert(unescape(r"\x41"[]) == "A"[]); 327 assert(unescape(r"\x41\x42\x43"[]) == "ABC"[]); 328 329 // 1-3 characters octal test (\ooo) 330 assert(unescape(r"\101"[]) == "A"[]); 331 assert(unescape(r"\101\102\103"[]) == "ABC"[]); 332 //Unknown escape sequence 333 assert(checkException!(UnescapeException)({unescape(r"\999"[]);})); 334 //Out of char range 335 assert(checkException!(UnescapeException)({unescape(r"\777"[]);})); 336 assert(unescape(r"\377"[]) == "\xff"); 337 338 //4 hex digits 339 assert(unescape(r"\u4142"[]) == "AB"[]); 340 assert(unescape(r"\uC582"[]) == "Å"[]); 341 342 //8 hex digits 343 assert(unescape(r"\U41424344"[]) == "ABCD"[]); 344 345 //named chars 346 assert(unescape(r"\""[]) == "\""); 347 assert(unescape(r"\©"[]) == "\©"); 348 assert(unescape(r"\Λ"[]) == "\Λ"); 349 assert(unescape(r"\♥"[]) == "\♥"); 350 });} 351 352 //------------------------------------------------------------------------------ 353 354 unittest { testCase.execute("escape/unescape characters", { 355 string input; 356 357 input = r"\\\\ abc \t\n\t \t"; assert(unescape(escape(input)) == input); 358 input = r"\\d\te\\f"; assert(unescape(escape(input))==input); 359 input = r"\\g\r\t\nhi"; assert(unescape(escape(input))==input); 360 input = r"\\jk;lkds[]\tl"; assert(unescape(escape(input))==input); 361 input = r"\fmno"; assert(unescape(escape(input))==input); 362 input = r"\r\npqr"; assert(unescape(escape(input))==input); 363 input = r"\\stu"; assert(unescape(escape(input))==input); 364 input = r"\\vwq"; assert(unescape(escape(input))==input); 365 input = r"\\xyz"; assert(unescape(escape(input))==input); 366 });} 367 368 369 //------------------------------------------------------------------------------ 370 371 unittest { 372 testSuite.finish; 373 } trunk/doost/util/DUnit.d
r32 r37 42 42 public: 43 43 this(uint rwidth, Align aligning, string form="%s", uint border = 1) { 44 m_rwidth = rwidth; 44 45 m_cwidth = rwidth; 45 46 m_aligning = aligning; … … 83 84 private: 84 85 uint m_cwidth; 86 uint m_rwidth; 85 87 Align m_aligning; 86 88 uint m_border; … … 187 189 if (auto elem = cast(CellElem)e) { 188 190 ccount++; 189 if (elem.m_ cwidth == -1) {191 if (elem.m_rwidth == -1) { 190 192 if (dyncol !is null) throw new Exception("Only one column can have dynamic width"); 191 193 dyncol = elem; 192 } else defwidth+=elem.m_ cwidth;194 } else defwidth+=elem.m_rwidth; 193 195 } 194 196 } … … 237 239 238 240 //------------------------------------------------------------------------------ 241 242 ulong rdtsc() { 243 asm 244 { 245 naked; 246 rdtsc; 247 ret; 248 } 249 } 239 250 240 251 struct TraceInfo { … … 280 291 m_testname = testname; 281 292 m_passed = false; 282 m_elapsedtime = real.nan;293 m_elapsedtime = 0; 283 294 284 295 int no; … … 290 301 m_number = m_owner.m_tccounter; 291 302 try { 292 d_time starttime = getUTCtime();303 long starttime = rdtsc; 293 304 for(uint i = 0; i<m_repeat; i++) { 294 305 if (m_setup !is null) m_setup(); … … 296 307 if (m_teardown !is null) m_teardown(); 297 308 } 298 m_elapsedtime = (cast(real)(getUTCtime() - starttime))/1000;309 m_elapsedtime = rdtsc - starttime; 299 310 result = "OK"; 300 311 m_passed = true; … … 306 317 m_owner.m_tcfailed~=this; 307 318 no = 0; 319 m_elapsedtime = 0; 308 320 } 309 321 } else result = "DISABLED"; … … 317 329 318 330 //BUG: przy sprawdzaniu nan is oraz !is powinno dziaÅaÄ 319 if (!isNaN(m_elapsedtime))m_owner.m_elapsedtime+=m_elapsedtime;331 m_owner.m_elapsedtime+=m_elapsedtime; 320 332 } 321 333 … … 378 390 bool m_dotraces; 379 391 380 realm_elapsedtime;392 long m_elapsedtime; 381 393 uint m_number; 382 394 TestSuite m_owner; … … 449 461 450 462 void begin(string suitename) { 463 451 464 m_suitename = suitename; 465 m_firstingroup=true; 466 m_elapsedtime=0; 467 m_curgroup = null; 468 m_testgroups = null; 469 m_curcase = null; 470 m_testcases = null; 471 m_tcfailed = null; 452 472 m_tccounter = 0; 453 473 m_tcfcounter = 0; 454 m_tcfailed = null;455 m_elapsedtime=0;456 474 457 475 renderer.render(hl); … … 490 508 renderer.render(hl); 491 509 renderer.render(simple); 492 renderer.render(etime, "Statistics :", "Total ti me:", m_elapsedtime);510 renderer.render(etime, "Statistics :", "Total ticks :", m_elapsedtime); 493 511 renderer.render(stat, " - all :", m_tccounter); 494 512 renderer.render(stat, " - passed :", tcpcounter, cast(double)(tcpcounter*100)/m_tccounter); … … 499 517 renderer.render(empty); 500 518 519 m_setup = null; 520 m_teardown = null; 521 m_dotiming = false; 522 m_dotraces = false; 523 m_reqtraces = false; 524 m_repeat = 1; 501 525 } 502 526 … … 545 569 title = [Sep, Cell(-1, Align.Center), Sep]; 546 570 tc = [Sep, Cell(5, Align.Right, "%-s", 0), Cell(-1, Align.Left), Cell(7, Align.Right), Sep]; 547 tc_tim = [Sep, Cell(5, Align.Right, "%-s", 0), Cell(-1, Align.Left), Cell(7, Align.Right), Sep, Cell( 8, Align.Right), Sep, Cell(8, Align.Right, "%6.2f"), Sep];571 tc_tim = [Sep, Cell(5, Align.Right, "%-s", 0), Cell(-1, Align.Left), Cell(7, Align.Right), Sep, Cell(7, Align.Right), Sep, Cell(10, Align.Right, "%d"), Sep]; 548 572 simple = [Sep, Cell(-1, Align.Left), Sep]; 549 etime = [Sep, Cell(15, Align.Right), Cell(-1, Align.Right), Cell(1 0, Align.Left, "%6.4f s"), Sep];573 etime = [Sep, Cell(15, Align.Right), Cell(-1, Align.Right), Cell(15, Align.Right, "%d"), Sep]; 550 574 stat = [Sep, Cell(15, Align.Right), Cell(6, Align.Left), Cell(-1, Align.Left, "(%6.2f %%)"), Sep]; 551 575 fail = [Sep, Cell(5, Align.Right, "%d."), Cell(-1, Align.Left), Sep]; … … 609 633 TestGroup m_curgroup; 610 634 TestGroup[] m_testgroups; 611 realm_elapsedtime=0;635 long m_elapsedtime=0; 612 636 613 637 uint m_tccounter, m_tcfcounter; trunk/doost/util/serializer/Serializer.d
r32 r37 18 18 import doost.api.Common; 19 19 import doost.core.Traits; 20 import doost.storage.Storage; 20 21 import doost.util.serializer.Registry; 21 22 … … 88 89 89 90 enum Mode {LOAD, DUMP} 90 alias elementType!(STORAGE)[] STORAGETYPE; 91 alias StorageElementType!(STORAGE) ELEMENTTYPE; 92 alias StorageType!(STORAGE) STORAGETYPE; 91 93 92 94 mixin CONCRETEARCHIVE!(Archive); … … 104 106 this() { 105 107 m_archive = new Archive; 106 init(m_archive); 108 static if (is(typeof(init(Archive)) == bool)) { 109 init(m_archive); 110 } 107 111 } 108 112 … … 143 147 144 148 archive.mode = Mode.DUMP; 145 archive.storage = STORAGE.init;146 149 147 150 start(archive); … … 169 172 VALUE load(VALUE)(STORAGE storage, Archive archive = null) { 170 173 //TODO: static asserts in serializer --> check if all template functions exists in Archive 171 172 174 if (archive is null) archive = m_archive.dup_info; 173 175 else archive = archive.dup_info; … … 285 287 "'. Types like void*, union, enum are not serializable without additional information"); 286 288 } 287 //TODO: Unions - they are possibl eserializable, but probably only through289 //TODO: Unions - they are possibly serializable, but probably only through 288 290 //loadUdt/dumpUdt 289 291 } … … 371 373 } 372 374 } else { 373 //FIXME:374 375 static assert(false, "UDT '" ~ VALUE.stringof ~ "' is not serializable."); 375 376 } trunk/doost/util/serializer/archive/JsonArchive.d
r34 r37 39 39 import doost.util.serializer.Registry; 40 40 import doost.text.Escaper; 41 import doost.text.Tokenizer; 42 43 /******************************************************************************* 44 ******************************************************************************/ 45 static string generator(string name, string[] arr) { 46 assert(arr.length % 2 == 0, "For each pattern default must be given."); 47 string result = "static struct " ~ name ~ " {\n"; 48 49 string reset = " static public void reset() {\n"; 50 51 string dupl = " public typeof(*this) dup() {\n"; 52 dupl~= " typeof(*this) result;\n"; 53 54 for(int i=0; i<arr.length; i+=2 ) { 55 result~=" static public string " ~ arr[i] ~ " = `" ~ arr[i+1] ~ "`;\n"; 56 reset~= " " ~ arr[i] ~ " = `" ~ arr[i+1] ~ "`;\n"; 57 dupl~= " result." ~ arr[i] ~ " = " ~ arr[i] ~ ".dup;\n"; 58 } 59 60 result~="\n"; 61 reset~=" }\n\n"; 62 dupl~=" return result; \n"; 63 dupl~= " }\n\n"; 64 65 result~= reset ~ dupl ~ "}\n"; 66 return result; 67 } 41 import doost.text.Scanner; 68 42 69 43 //------------------------------------------------------------------------------ 70 44 71 //TODO: czy na pewno wystawiaÄ na zewnÄ 72 trz typy proste? po co je zmieniaÄ?? 73 mixin(generator("Pattern(T : long)", ["pattern", r"[\+|-]?\d\d*"])); 74 mixin(generator("Pattern(T : int)", ["pattern", r"[\+|-]?\d\d*"])); 75 mixin(generator("Pattern(T : short)", ["pattern", r"[\+|-]?\d\d*"])); 76 mixin(generator("Pattern(T : byte)", ["pattern", r"[\+|-]?\d\d*"])); 77 mixin(generator("Pattern(T : ulong)", ["pattern", r"\d\d*"])); 78 mixin(generator("Pattern(T : uint)", ["pattern", r"\d\d*"])); 79 mixin(generator("Pattern(T : ushort)", ["pattern", r"\d\d*"])); 80 mixin(generator("Pattern(T : ubyte)", ["pattern", r"\d\d*"])); 81 82 mixin(generator("Pattern(T : real)", ["pattern", r"nan|[\+|-]?\d\d*(\.\d\d*)?"])); 83 mixin(generator("Pattern(T : double)", ["pattern", r"nan|[\+|-]?\d\d*(\.\d\d*)?"])); 84 mixin(generator("Pattern(T : float)", ["pattern", r"nan|[\+|-]?\d\d*(\.\d\d*)?"])); 85 86 mixin(generator("Pattern(T : char)", ["pattern", r"."])); 87 mixin(generator("Pattern(T : wchar)", ["pattern", r"."])); 88 mixin(generator("Pattern(T : dchar)", ["pattern", r"."])); 89 mixin(generator("Pattern(T : bool)", ["positive", "true", "negative", "false"])); 90 91 //For other types: 92 mixin(generator("Pattern(T)", ["pattern", ""])); 93 94 // mixin(generator("Skip", [ 95 // "skip", " \t\r\n", 96 // "space", " ", 97 // "newline", "\n", 98 // "indent", " " 99 // ])); 100 101 static struct Skip { 102 103 static public string space = " "; 104 static public string newline = "\n"; 105 static public string indent = " "; 106 107 static public string skip() { 108 return m_skip; 109 } 110 111 static public void skip(string s) { 112 m_skip = s; 113 } 114 115 static public CharClass!(char) skip_cc() { 116 if (m_skip_cc.empty) return m_skip_cc.whitespace; 117 return m_skip_cc; 118 } 119 120 static private CharClass!(char) m_skip_cc; 121 static public string m_skip = " \t\r\n"; 122 } 123 124 125 mixin(generator("Array", ["begin", "[", "separator", ",", "end", "]"])); 126 mixin(generator("String", ["delim1", "\"", "delim2", "'"])); 127 mixin(generator("Udt", [ 128 "ver", "versionUdt", 129 "begin", "{", 130 "kvseparator", ":", 131 "separator", ",", 132 "end", "}" 133 ])); 134 135 mixin(generator("Reference", ["p_null", "null", "p_ref", "$", "p_pointer", r"*", "s_null", "null", "s_ref", "$", "s_pointer", "*"])); 45 private static struct Skip { 46 static STORAGETYPE space = " "; 47 static STORAGETYPE newline = "\n"; 48 static STORAGETYPE indent = " "; 49 static auto skip = CharClass!(ELEMENTTYPE).whitespace; 50 } 51 52 private static struct Bool { 53 static STORAGETYPE positive = "true"; 54 static STORAGETYPE negative = "false"; 55 } 56 57 private static struct String { 58 static auto delimiter = SequenceSet!(STORAGETYPE).strdelim; 59 static auto escdesc = &scanEscapeSequence!(STORAGE); 60 static auto allchars = CharClass!(ELEMENTTYPE).alphanum; 61 static auto midchars = CharClass!(ELEMENTTYPE).digit; 62 static ELEMENTTYPE sdelimiter = '"'; 63 static ELEMENTTYPE cdelimiter = '\''; 64 } 65 66 private static struct Region { 67 static auto begin = SequenceSet!(STORAGETYPE).openingbrackets; 68 static auto end = SequenceSet!(STORAGETYPE).closingbrackets; 69 } 70 71 private static struct Reference { 72 static STORAGETYPE defnull = "null"; 73 static ELEMENTTYPE defref = '$'; 74 static ELEMENTTYPE pointer = '*'; 75 } 76 77 private static struct Array { 78 static ELEMENTTYPE begin = '['; 79 static ELEMENTTYPE separator = ','; 80 static ELEMENTTYPE end = ']'; 81 } 82 83 private static struct Udt { 84 static STORAGETYPE ver = "versionUdt"; 85 static ELEMENTTYPE begin = '{'; 86 static ELEMENTTYPE kvseparator = ':'; 87 static ELEMENTTYPE separator = ','; 88 static ELEMENTTYPE end = '}'; 89 } 136 90 137 91 //-------------------------------------------------------------------------- … … 142 96 uint indent = 0; 143 97 144 // zawartoÅÄ[nazwa pola]145 STORAGETYPE[STORAGETYPE] memberStructFields; //fields of specific class with values;98 //fields of specific class with values: content[name of fields] 99 STORAGETYPE[STORAGETYPE] memberStructFields; 146 100 147 101 Archive dup_infoext() { … … 159 113 static class TypeDescription(T) : Registration { 160 114 mixin TypeDescriptionBase!(T) DEFAULT; 161 public Pattern!(T) def;162 115 163 116 public typeof(this) dup_info() { 164 117 typeof(this) result = DEFAULT.dup_info; 165 result.def = def.dup;166 118 return result; 167 119 } … … 203 155 **************************************************************************/ 204 156 bool loadString(VALUE)(ref VALUE value, ARCHIVE archive) { 205 skip(archive.storage, Skip.skip_cc); 206 207 //FIXME: 208 CharClass!(char) delim; 209 delim.add(String.delim1[0]); 210 delim.add(String.delim2[0]); 211 212 auto pos = startsWithString(archive.storage, delim); 213 if (!pos) throw new ParsingException("Expected string/char in input, but it wasn't found."); 214 215 value = munch(archive.storage, pos); 216 217 if (value.length>1 && (value[0] == String.delim1[0] || value[0] == String.delim2[0] )) { 218 value = value[1..$-1]; 219 value = unescape(value); 220 } 157 skip(archive.storage, Skip.skip, uint.max); 158 159 auto m = scanString!(STORAGE)(archive.storage, String.delimiter, String.escdesc, String.allchars, String.midchars); 160 if (!cast(bool)m) 161 throw new ParsingException("Expected string or char in input, but it wasn't found."); 162 163 value = munch(archive.storage, m); 164 165 auto delim = munch(value, String.delimiter); 166 auto len = delim.length; 167 168 if (len>0) value = value[0..$-len]; 169 170 value = unescape(value); 221 171 222 172 return true; … … 226 176 **************************************************************************/ 227 177 bool dumpString(VALUE)(ref VALUE value, ARCHIVE archive) { 228 archive.storage.put( to!(STORAGETYPE)(String.delim1)~178 archive.storage.put( String.sdelimiter ~ 229 179 to!(STORAGETYPE)(escape(value)) ~ 230 to!(STORAGETYPE)(String.delim1));231 return true; 232 } 233 234 /*************************************************************************** 235 **************************************************************************/ 236 Match Position startsWithBool(ref STORAGE input) {237 Match Positionmp;238 239 mp = s tarts(input, Pattern!(bool).positive); if (mp) return mp;240 mp = s tarts(input, Pattern!(bool).negative); if (mp) return mp;241 242 return mismatch;180 String.sdelimiter); 181 return true; 182 } 183 184 /*************************************************************************** 185 **************************************************************************/ 186 Matcher scanWithBool(ref STORAGE input) { 187 Matcher mp; 188 189 mp = scan(input, Bool.positive); if (cast(bool)mp) return mp; 190 mp = scan(input, Bool.negative); if (cast(bool)mp) return mp; 191 192 return Matcher(0, Matcher.mismatch); 243 193 } 244 194 … … 250 200 **************************************************************************/ 251 201 bool loadBool(VALUE)(ref VALUE value, ARCHIVE archive) { 252 skip(archive.storage, Skip.skip _cc);202 skip(archive.storage, Skip.skip, uint.max); 253 203 STORAGETYPE literal; 254 204 255 if (auto mp = archive.storage.startsWithBool()) { 205 auto mp = archive.storage.scanWithBool(); 206 if (cast(bool)mp) { 256 207 literal = munch(archive.storage, mp); 257 208 } else throw new ParsingException("Unknown bool literal."); … … 269 220 **************************************************************************/ 270 221 bool dumpBool(VALUE)(ref VALUE value, ARCHIVE archive) { 271 archive.storage.put((value == true) ? Pattern!(bool).positive272 : Pattern!(bool).negative);222 archive.storage.put((value == true) ? Bool.positive 223 : Bool.negative); 273 224 return true; 274 225 } … … 277 228 **************************************************************************/ 278 229 bool loadNumber(VALUE)(ref VALUE value, ARCHIVE archive) { 279 skip(archive.storage, Skip.skip _cc);280 auto pos = s tartsWithNumber(archive.storage);281 if (! pos) throw new ParsingException("Expected number in source, but it wasn't found.");230 skip(archive.storage, Skip.skip, uint.max); 231 auto pos = scanNumber(archive.storage); 232 if (!cast(bool)pos) throw new ParsingException("Expected number in source, but it wasn't found."); 282 233 283 234 value = to!(VALUE)(munch(archive.storage, pos)); … … 307 258 **************************************************************************/ 308 259 bool dumpChar(VALUE)(ref VALUE value, ARCHIVE archive) { 309 archive.storage.put( String.delim2 ~ value ~ String.delim2);310 return true; 311 } 312 313 /*************************************************************************** 314 **************************************************************************/ 315 bool loadElement(VALUE )(ref VALUE value, stringesep, ARCHIVE archive) {260 archive.storage.put("" ~ String.cdelimiter ~ value ~ String.cdelimiter); 261 return true; 262 } 263 264 /*************************************************************************** 265 **************************************************************************/ 266 bool loadElement(VALUE, SEP)(ref VALUE value, SEP esep, ARCHIVE archive) { 316 267 if (archive.mismatch) throw new ParsingException("Missing elements separator."); 317 268 bool matched = traverse(value, archive); 318 269 if (!matched) return false; 319 270 320 skip(archive.storage, Skip.skip _cc);321 archive.mismatch = !skip(archive.storage, new RegExp(esep));322 return true; 323 } 324 325 /*************************************************************************** 326 **************************************************************************/ 327 bool dumpElement(VALUE )(ref VALUE value, stringsep, ARCHIVE archive) {271 skip(archive.storage, Skip.skip, uint.max); 272 archive.mismatch = !skip(archive.storage, esep); 273 return true; 274 } 275 276 /*************************************************************************** 277 **************************************************************************/ 278 bool dumpElement(VALUE, SEP)(ref VALUE value, SEP sep, ARCHIVE archive) { 328 279 archive.storage.put(archive.rest); 329 280 bool res = traverse(value, archive); … … 335 286 **************************************************************************/ 336 287 bool loadArray(VALUE)(ref VALUE value, ARCHIVE archive) { 337 skip(archive.storage, Skip.skip _cc);288 skip(archive.storage, Skip.skip, uint.max); 338 289 339 290 if (!skip(archive.storage, Array.begin)) … … 344 295 archive.mismatch = false; 345 296 do { 346 skip(archive.storage, Skip.skip _cc);297 skip(archive.storage, Skip.skip, uint.max); 347 298 if (skip(archive.storage, Array.end)) break; 348 299 loadElement(elem, Array.separator, archive); … … 369 320 /*************************************************************************** 370 321 **************************************************************************/ 371 bool loadAssociativeElement(KEY, VALUE )(ref KEY key, ref VALUE value, string kvsep, stringesep, ARCHIVE archive) {322 bool loadAssociativeElement(KEY, VALUE, KVSEP, SEP)(ref KEY key, ref VALUE value, KVSEP kvsep, SEP esep, ARCHIVE archive) { 372 323 if (archive.mismatch) throw new ParsingException("Missing associative elements separator."); 373 324 bool matched = traverse(key, archive); 374 325 if(!matched) return false; 375 326 376 skip(archive.storage, Skip.skip _cc);327 skip(archive.storage, Skip.skip, uint.max); 377 328 if (!skip(archive.storage, kvsep)) 378 329 throw new ParsingException("Missing associative array literal key-value separator."); … … 380 331 traverse(value, archive); 381 332 382 skip(archive.storage, Skip.skip_cc); 383 if (!skip(archive.storage, esep)) 384 archive.mismatch = true; 333 skip(archive.storage, Skip.skip, uint.max); 334 if (!skip(archive.storage, esep)) archive.mismatch = true; 385 335 386 336 return matched; … … 389 339 /*************************************************************************** 390 340 **************************************************************************/ 391 bool dumpAssociativeElement(KEY, VALUE )(ref KEY key, ref VALUE value, string kvsep, stringesep, ARCHIVE archive) {341 bool dumpAssociativeElement(KEY, VALUE, KVSEP, SEP)(ref KEY key, ref VALUE value, KVSEP kvsep, SEP esep, ARCHIVE archive) { 392 342 archive.storage.put(archive.rest); 393 343 traverse(key, archive); … … 404 354 alias typeof(VALUE.init.keys[0]) KeyType; 405 355 406 skip(archive.storage, Skip.skip _cc);356 skip(archive.storage, Skip.skip, uint.max); 407 357 if (!skip(archive.storage, Udt.begin)) 408 358 throw new ParsingException("Missing associative array literal begining delimiter."); … … 414 364 archive.mismatch = false; 415 365 do { 416 skip(archive.storage, Skip.skip _cc);366 skip(archive.storage, Skip.skip, uint.max); 417 367 if (skip(archive.storage, Udt.end)) break; 418 loadAssociativeElement(key, val, Udt.kvsepar
