Changeset 28
- Timestamp:
- 01/21/08 17:09:38 (1 year ago)
- Files:
-
- trunk/bin/obj (added)
- trunk/doc/text (added)
- trunk/doc/util (added)
- trunk/doost/api (added)
- trunk/doost/api/Common.d (added)
- trunk/doost/core/Any.d (modified) (6 diffs)
- trunk/doost/core/Traits.d (added)
- trunk/doost/text (added)
- trunk/doost/text/Escaper.d (added)
- trunk/doost/util/DUnit.d (added)
- trunk/doost/util/config/CommandLineStorage.d (modified) (4 diffs)
- trunk/doost/util/config/Converter.d (modified) (13 diffs)
- trunk/doost/util/config/Option.d (modified) (1 diff)
- trunk/doost/util/config/ProgramOptions.d (modified) (1 diff)
- trunk/doost/util/config/Utils.d (modified) (1 diff)
- trunk/doost/util/config/Value.d (modified) (12 diffs)
- trunk/doost/util/serializer (added)
- trunk/doost/util/serializer/Registry.d (added)
- trunk/doost/util/serializer/Serializer.d (added)
- trunk/doost/util/serializer/archive (added)
- trunk/doost/util/serializer/archive/TextArchive.d (added)
- trunk/examples/text (added)
- trunk/examples/text/FunctionTest.d (added)
- trunk/examples/text/text.cbp (added)
- trunk/examples/util/config/FunctionTest.d (modified) (61 diffs)
- trunk/examples/util/config/RegEx.d (modified) (4 diffs)
- trunk/examples/util/config/util_config.cbp (modified) (8 diffs)
- trunk/examples/util/config/util_config.depend (added)
- trunk/examples/util/config/util_config_build_log.html (added)
- trunk/examples/util/serializer (added)
- trunk/examples/util/serializer/FunctionTest.d (added)
- trunk/examples/util/serializer/util_serializer.cbp (added)
- trunk/std2 (added)
- trunk/std2/README.txt (added)
- trunk/std2/conv.d (added)
- trunk/std2/string.d (added)
- trunk/std2/traits.d (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/doost/core/Any.d
r20 r28 18 18 module doost.core.Any; 19 19 20 import doost.util. TestHelper;20 import doost.util.DUnit; 21 21 22 22 // ----------------------------------------------------------------------------- … … 208 208 209 209 import std.stdio; 210 211 import doost.util.TestHelper; 210 import doost.util.DUnit; 211 212 //------------------------------------------------------------------------------ 212 213 213 214 unittest { 214 215 startSuite("Any"); 215 class Test { 216 char[] toString() { 217 return "Test class".dup; 218 } 219 void doTest() {}; 220 } 221 216 } 217 218 //------------------------------------------------------------------------------ 219 220 class Test { 221 char[] toString() { 222 return "Test class".dup; 223 } 224 void doTest() {} 225 } 226 227 //------------------------------------------------------------------------------ 228 229 unittest { testcase("Any - assigning", { 222 230 bool assigned=false; 223 231 auto t=new Test; … … 226 234 auto z = Any(); 227 235 228 //------------------------------------------------------------------------------229 230 startTest("Assigning");231 236 v=5; 232 237 assert(v.as!(int) == 5); … … 245 250 v=ba; 246 251 assert(v.as!(byte[]) == [cast(byte)(5),16,78,90]); 247 248 finishTest; 249 250 //------------------------------------------------------------------------------ 251 252 startTest("Comparing"); 252 });} 253 254 //------------------------------------------------------------------------------ 255 256 unittest { testcase("Any - comparing", { 257 auto v = Any(); 258 auto z = Any(); 253 259 254 260 v=5; z=5; … … 257 263 v="Ala"[]; z="Ola"[]; 258 264 assert(v != z); 259 260 finishTest; 261 262 //------------------------------------------------------------------------------ 263 264 startTest("toString"); 265 265 });} 266 267 //------------------------------------------------------------------------------ 268 269 unittest { testcase("Any - toString()", { 270 auto v = Any(); 266 271 v=5; 267 272 assert(v.toString == "5"); … … 269 274 v=new Test; 270 275 assert(v.toString == "Test class"); 271 272 273 finishTest; 274 275 //------------------------------------------------------------------------------ 276 276 });} 277 278 //------------------------------------------------------------------------------ 279 280 unittest { 277 281 finishSuite; 278 282 } trunk/doost/util/config/CommandLineStorage.d
r22 r28 21 21 import std.stdio; 22 22 import std.path; 23 import std2.conv; 23 24 24 25 import doost.core.Any; … … 429 430 m_trailing = name; 430 431 } else { 431 maxCount= std.conv.toUint(cnt);432 maxCount=to!(uint)(cnt); 432 433 while (maxCount>0) {m_names~=name; maxCount--; }; 433 434 } … … 692 693 is(typeof(p) : CommandLineOptions), 693 694 "Type " ~ typeof(p).stringof ~ " is not allowed."); 694 assert(p !is null );695 assert(p !is null, "Option value can not be null!"); 695 696 } 696 697 } … … 798 799 auto path = m_desc.matchClass!(SelfPath)(OptionCharacteristic.Single); 799 800 801 //writefln(self); 800 802 if (file !is null) opts~=ParsedOption(file.key, getBaseName(self), file); 801 803 if (dir !is null) opts~=ParsedOption(dir.key, getDirName(self), dir); trunk/doost/util/config/Converter.d
r22 r28 18 18 module doost.util.config.Converter; 19 19 20 import std.conv;21 20 import std.string; 22 21 import std.stdio; … … 24 23 import std.format; 25 24 25 public import std2.conv; 26 26 public import doost.core.Any; 27 27 import doost.util.config.Exception; 28 28 import doost.util.config.Utils; 29 30 //------------------------------------------------------------------------------ 31 32 /******************************************************************************* 33 Template which converts string to given type. It handles all standard types. 34 35 Params: s = string value of type 36 Returns: type created from string 37 ******************************************************************************/ 38 T stringToType(T)(char[] s) { 39 static if (is (T == char[])) return s; 40 else 41 static if (is (T == int)) return toInt(s); 42 else 43 static if (is (T == uint)) return toUint(s); 44 else 45 static if (is (T == long)) return toLong(s); 46 else 47 static if (is (T == ulong)) return toUlong(s); 48 else 49 static if (is (T == short)) return toShort(s); 50 else 51 static if (is (T == ushort)) return toUshort(s); 52 else 53 static if (is (T == byte)) return toByte(s); 54 else 55 static if (is (T == ubyte)) return toUbyte(s); 56 else 57 static if (is (T == float)) return toFloat(s); 58 else 59 static if (is (T == double)) return toDouble(s); 60 else 61 static if (is (T == real)) return toReal(s); 62 else static assert(false, "Unknown method to convert string to type " ~ T.stringof ~ "."); 63 } 29 import doost.util.config.Value; 30 import doost.text.Escaper; 64 31 65 32 //------------------------------------------------------------------------------ … … 95 62 96 63 /******************************************************************************* 64 ******************************************************************************/ 65 void checkPattern(char[] str, char[] pattern) { 66 if (pattern !is null) { 67 auto re = std.regexp.search(str, pattern); 68 if (re is null) throw new InvalidOptionValueException(str, pattern); 69 if (re.match(0) != str) 70 throw new InvalidOptionValueException(str, pattern); 71 } 72 } 73 74 //------------------------------------------------------------------------------ 75 76 /******************************************************************************* 97 77 The target type is specified via a parameter which has the type of 98 78 pointer to the desired type. This is workaround for compilers without … … 100 80 101 81 Params: xs = name to parse 102 pattern = regular expression pattern 103 ******************************************************************************/ 104 T parseText(T)(char[] xs, char[] pattern) { 105 if (xs is null) throw new InvalidOptionValueException; 82 ******************************************************************************/ 83 T parseValue(T)(TypedValue!(T) owner, char[] xs) { 106 84 char[] s=xs.dup; 107 108 if (pattern !is null) { 109 auto re = std.regexp.search(s, pattern); 110 if (re is null) throw new InvalidOptionValueException(s, pattern); 111 if (re.match(0) != s) 112 throw new InvalidOptionValueException(s, pattern); 113 } 114 115 return stringToType!(T)(s); 85 checkPattern(s, owner.pattern); 86 return to!(T)(s); 116 87 } 117 88 … … 123 94 Params: value = value to convert 124 95 ******************************************************************************/ 125 char[] stringizeValue(T)( Any value) {96 char[] stringizeValue(T)(TypedValue!(T) owner, Any value) { 126 97 static if (isAtomicType!(T)) { 127 98 return toString(value.as!(T)); … … 153 124 154 125 Params: xs = name to parse 155 pattern = regular expression pattern 156 sep = characters used to separate elements of list 157 skip = characters to skip from parsed source 126 Returns: array of parsed elements 158 127 *******************************************************************************/ 159 T[] parseText(T : T[])(char[] xs, char[] pattern, char[] sep, char[] skip) { 128 T[] parseValue(T : T[])(TypedValue!(T[]) owner, char[] xs) { 129 pragma(msg, T.stringof); 160 130 T[] tv; 161 131 162 132 char[] list = strip(xs); 133 134 //TODO: na najwyÅŒszym poziomie powinny byÄ teÅŒ dopuszczalen "" oraz '' 135 //po to aby moÅŒna byÅo Åatwo podaÄ tablicÄ z linii komend (moÅŒe zaimplementowaÄ 136 //to w CommandLineStorage?) 137 //TODO: znaki otwierajÄ 138 ce i zamykajÄ 139 ce teÅŒ powinny byÄ parametrem, a nie 140 //zahardkodowane 163 141 if (list.length>1) { 164 142 if (list[0] == '[' && list[$-1] == ']') { … … 168 146 } 169 147 170 char[][] tokens = tokenizer(list, sep, skip); 148 //0. strip opening element 149 //0.2 strip z poczÄ 150 tku i koÅca znaki, które majÄ 151 byÄ pomijane na tym poziomie 152 //0.5 JeÅŒeli element jest teÅŒ tablicÄ 153 (tabl. asocjacyjnÄ 154 , to przekaÅŒ wynik 155 //do dalszej konssumpcji, jeÅŒeli nie to wyciÄ 156 gnij wszystkie znaki do separatora, 157 //i przekaÅŒ je do parsowania) 158 //1. consumeElement(owner.elementSemantic, ref xs) 159 //2. get char: moÅŒe byÄ albo separator albo element koÅcowy, albo znak pomijalny albo bÅÄ 160 d 161 //3. JeÅŒeli nie koniec to powtórz dla nastÄpnego elementu 162 //4. tylko kolekcje dziaÅajÄ 163 w ten sposób, ÅŒe konsumujÄ 164 tokeny; jeÅŒeli 165 //elementem jest juÅŒ atomiczny typ, to jest on przekazywany w caÅoÅci 166 //do parsowania; static if (assoc || array) 167 //czy w takim razie pattern powinien byÄ dopuszczalny dla kolekcji? nie! 168 169 //Wszystkie mogÄ 170 pobieraÄ znaki z poczÄ 171 tkowego stringu, ale trzeba bÄdzie wÅÄ 172 czyÄ 173 //std.conv z D2.0 oraz std.string --> munch (pomijanie biaÅych znaków) 174 175 176 char[][] tokens = tokenizer(list, owner.separator, owner.skip); 171 177 foreach(t; tokens) { 172 tv ~= parseText!(T)(strip(t), pattern); 178 //TODO: tak na prawdÄ lista w liÅcie juÅŒ nie bÄdzie obsÅugiwana, bo 179 //jest zÅa sygnatura argumentów. MoÅŒe tu powinno byÄ teÅŒ tworzone ValueSemantic? 180 //dla typów podrzÄdnych? 181 tv ~= parseValue!(T)(owner.elementSemantic, strip(t)); 173 182 } 174 183 … … 183 192 Params: v = value of array 184 193 ******************************************************************************/ 185 char[] stringizeValue(T : T[])(Any v) {194 char[] stringizeValue(T : T[])(TypedValue!(T[]) owner, Any v) { 186 195 assert(v !is null); 187 196 char[] result; … … 190 199 191 200 for(uint i = 0; i < list.length - 1; i++) { 192 result~=stringizeValue!(T)(Any(list[i])); 201 //FIXME: below must be taken from owner 202 result~=stringizeValue!(T)(owner.elementSemantic, Any(list[i])); 193 203 result~=", "; 194 204 } 195 205 196 if (list.length > 0) result ~= stringizeValue!(T)(Any(list[list.length-1])); 206 //FIXME: below must be taken from owner 207 if (list.length > 0) result ~= stringizeValue!(T)(owner.elementSemantic, Any(list[list.length-1])); 197 208 198 209 return result; … … 207 218 208 219 Params: xs = name to parse 209 pattern = regular expression pattern 210 ******************************************************************************/ 211 T parseText(T : bool)(char[] xs, char[] pattern) { 220 ******************************************************************************/ 221 //TODO: test dla tablic bool'ów. caÅoÅÄ parsowania powinna mieÄ miejsce w tym, 222 //pliku tak aby, moÅŒna byÅo wywoÅywaÄ obsÅugÄ tablic. Tak wiÄc zero token, 223 //teÅŒ powinno byÄ obsÅugiwane tutaj. Tak naprawdÄ do parsera powinno byÄ 224 //przekazywane value semantic?? 225 T parseValue(T : bool)(TypedValue!(bool) owner, char[] xs) { 212 226 char[] s=tolower(xs.dup); 213 214 if (pattern is null) 215 pattern = "on|yes|1|true"; 216 227 char[] ppattern = owner.pattern; 228 229 //TODO: przenieÅÄ to wyÅŒej do klasy ValueSemantic? MoÅŒe wszystkie parseValue 230 //tam przenieÅÄ? Wtedy tylko jeden argument xs..., albo przekazywaÄ valuesemantic 231 //TODO: moÅŒliwoÅÄ ustawienia value semantic dla elementów listy oraz dla klucza/wartoÅci 232 //tablic asocjacyjnych 233 if (ppattern == "") 234 ppattern = "on|yes|1|true"; 235 236 //TODO: niech boolSwitch bÄdzie rzeczywiÅcie switchem tzn. dodanie przeÅÄ 237 cznika moÅŒe wyÅÄ 238 czaÄ, jeÅŒeli defaultValue = true 217 239 if (s.length == 0) return true; 218 240 219 auto re = std.regexp.search(s, p attern);241 auto re = std.regexp.search(s, ppattern); 220 242 if (re !is null) { 221 243 if (re.match(0) == s) return true; … … 224 246 return false; 225 247 } 248 249 //TODO: w przypadku list w opisie powinno byÄ nie arg, ale list 250 //TODO: przerobiÄ boolSwitcha na prawdziwego switcha, który przeÅÄ 251 cza default value na innÄ 252 wartoÅÄ 253 //TODO: dodatkowy parser/styl dla opcji 3 wartoÅciowych no, default, given 254 //TODO: positional options definition: 2*shapes, 3*names, 1*path, path 255 //TODO: jeÅŒeli plik w ConfigFileStorage nie istnieje to zostanie automatycznie utworzony 226 256 227 257 //------------------------------------------------------------------------------ … … 233 263 234 264 Params: xs = name to parse 235 pattern = regular expression pattern 236 ******************************************************************************/ 237 T parseText(T : char[])(char[] xs, char[] pattern) { 238 if (xs is null) throw new InvalidOptionValueException; 239 265 ******************************************************************************/ 266 //TODO: ta funkcja powinna obsÅugiwaÄ wszystkie typy char[], wchar[] i dchar[] 267 T parseValue(T : char[])(TypedValue!(char[]) owner, char[] xs) { 240 268 char[] s=xs.dup; 241 269 bool skipEscapes=true; 242 if ((s != "") && ((s[0] == '\'' && s[$-1] == '\'') || (s[0] == '"' && s[$-1] == '"'))) {270 if ((s.length>1) && ((s[0] == '\'' && s[$-1] == '\'') || (s[0] == '"' && s[$-1] == '"'))) { 243 271 s = s[1..$-1]; 244 272 skipEscapes=false; 245 273 } 246 274 247 if (pattern !is null) { 248 std.regexp.RegExp re = std.regexp.search(s, pattern); 249 if (re is null) 250 throw new InvalidOptionValueException(s, pattern); 251 if (re.match(0) != s) 252 throw new InvalidOptionValueException(s, pattern); 253 } 275 checkPattern(s, owner.pattern); 254 276 255 277 char[] result; 256 278 //When there was no '' or "" characters escape characters are not replaced 257 279 if (!skipEscapes) { 258 bool isEscape=false; 259 foreach(c; s) { 260 if (isEscape==true) { 261 result~=fromEscape(c); 262 isEscape=false; 263 continue; 264 } 265 if (c == '\\') { 266 isEscape=true; 267 continue; 268 } 269 result~=c; 270 } 280 result = unescape(s); 271 281 } else result = s; 272 282 … … 280 290 281 291 Params: v = value of string 282 ******************************************************************************/ 283 char[] stringizeValue(T: char[])(Any v) { 292 Returns: stringized value 293 ******************************************************************************/ 294 char[] stringizeValue(T : char[])(TypedValue!(char[]) owner, Any v) { 284 295 assert(v !is null); 285 char[] result; 286 foreach(c; v.as!(char[])) { 287 result~=toEscape(c); 288 } 296 char[] result = escape(v.as!(char[])); 289 297 return "\"" ~ result ~ "\""; 290 298 } trunk/doost/util/config/Option.d
r22 r28 303 303 result.m_description = m_description is null ? null : m_description.dup; 304 304 result.m_semantic = m_semantic is null ? null : m_semantic.dup; 305 result.m_characteristics = m_characteristics; 305 306 } 306 307 trunk/doost/util/config/ProgramOptions.d
r22 r28 1127 1127 1128 1128 try { 1129 //writefln(name, " <-> ", strVal); 1129 1130 desc.semantic.parse(aval, strVal); 1130 1131 if (desc.characteristics & OptionCharacteristic.Keyed) m_collected[name]=true; trunk/doost/util/config/Utils.d
r20 r28 101 101 /******************************************************************************* 102 102 ******************************************************************************/ 103 char fromEscape(char c) {104 char result;105 switch (c) {106 case '\'' : result='\''; break;107 case '\"' : result='\"'; break;108 case '?' : result='\?'; break;109 case '\\' : result='\\'; break;110 case 'a' : result='\a'; break;111 case 'b' : result='\b'; break;112 case 'f' : result='\f'; break;113 case 'n' : result='\n'; break;114 case 'r' : result='\r'; break;115 case 't' : result='\t'; break;116 case 'v' : result='\v'; break;117 default: throw new EscapeCharacterException(c);118 }119 return result;120 }121 122 //------------------------------------------------------------------------------123 124 /*******************************************************************************125 ******************************************************************************/126 char[] toEscape(char c) {127 char[] result;128 switch (c) {129 case '\'' : result="\\'"; break;130 case '\"' : result="\\\""; break;131 case '\?' : result="\\?"; break;132 case '\\' : result="\\\\"; break;133 case '\a' : result="\\a"; break;134 case '\b' : result="\\b"; break;135 case '\f' : result="\\f"; break;136 case '\n' : result="\\n"; break;137 case '\r' : result="\\r"; break;138 case '\t' : result="\\t"; break;139 case '\v' : result="\\v"; break;140 default: result = [c];141 }142 return result;143 }144 145 /*******************************************************************************146 ******************************************************************************/147 103 char[] loadFileContents(char[] file) { 148 104 return cast(char[])read(file); trunk/doost/util/config/Value.d
r22 r28 41 41 } 42 42 43 //------------------------------------------------------------------------------ 44 45 /******************************************************************************* 46 Evaluates to type 47 ******************************************************************************/ 48 template arrayElementType(T) { 49 static if( is( T U : U[] ) ) 50 alias U arrayElementType; 51 else 52 static assert(false); 53 } 54 43 55 /******************************************************************************* 44 56 Evaluates to true if given type is array, but excluding char[], wchar[] … … 69 81 70 82 /******************************************************************************* 83 Evaluates to true if type of T is known (parsers and stringizers are 84 available) 85 ******************************************************************************/ 86 template isKnownType(T) { 87 static if (isCommonArray!(T) || isAtomicType!(T) || is(T == char[]) || is(T == wchar[]) || is(T == dchar[])) { 88 const isKnownType=true; 89 } else { 90 const isKnownType=false; 91 } 92 } 93 94 //------------------------------------------------------------------------------ 95 96 /******************************************************************************* 71 97 Interface which specifies how the option's value is to be parsed 72 98 and converted into D types. … … 227 253 Class which handles value of a specific type. 228 254 ******************************************************************************/ 229 class TypedValue(T , alias PARSER = parseText, alias STRINGIZER = stringizeValue) : ValueSemantic {255 class TypedValue(T) : ValueSemantic { 230 256 public: 231 257 /*************************************************************************** … … 237 263 m_pattern=pattern; 238 264 m_composing=false; 265 266 267 //FIXME: Would be very nice to have __traits(compile) 268 //to make better guesses for user defined type 269 //m_parser and m_stringizer should be null only if there is no match 270 //for templates 271 272 static if(!isKnownType!(T)) { 273 m_parser = null; 274 m_stringizer = null; 275 } else { 276 m_parser = &parseValue!(T); 277 m_stringizer = &stringizeValue!(T); 278 } 279 280 281 static if(isCommonArray!(T)) { 282 pragma(msg, "common array: " ~ T.stringof); 283 static if(isKnownType!(arrayElementType!(T))) { 284 m_elementSemantic = new TypedValue!(arrayElementType!(T)); 285 } 286 } else 287 static if(is(T == char[]) || is(T == wchar[]) || is(T == dchar[])) { 288 pragma(msg, "text type: " ~ T.stringof); 289 } else 290 static if(isAtomicType!(T)) { 291 pragma(msg, "atomic type: " ~ T.stringof); 292 } else 293 static if(is (T == bool)) { 294 pragma(msg, "bool: " ~ T.stringof); 295 m_pattern = "on|yes|1|true"; 296 } else { 297 } 298 239 299 } 240 300 … … 272 332 273 333 /*************************************************************************** 334 Returns: pattern for value 335 **************************************************************************/ 336 char[] pattern() { 337 return m_pattern; 338 } 339 340 /*************************************************************************** 274 341 Returns true if option can be composed. If it is true, option can appear 275 342 many times in source and will be composed into array. … … 301 368 302 369 /*************************************************************************** 303 Creates an instance of the 'validator' class and calls 304 its operator() to perform the actual conversion. 305 **************************************************************************/ 306 override void parse(Any value, char[] token) { 370 See: ValueSemantic 371 **************************************************************************/ 372 override void parse(Any value, char[] token) 373 in { 374 assert(m_parser); 375 } 376 body { 307 377 T result; 308 378 309 379 static if (isCommonArray!(T)) { 380 //TODO: sprawdzenie czy jest composing, jeÅŒeli nie to throw 310 381 if (!value.empty) result = value.as!(T); 311 result ~= PARSER!(T)(token, m_pattern, m_sep, m_skip);382 result ~= m_parser(this, token); 312 383 } else { 313 384 if (!value.empty) throw new MultipleOccurrencesException("multiple_occurrences"); 314 result = PARSER!(T)(token, m_pattern); 385 //FIXME: jest róŌnica pomiÄdzy null i ""; co poniÅŒej powinno byÄ? 386 if (!isZeroTokens && token is null) throw new InvalidOptionValueException; 387 388 result = m_parser(this, token); 315 389 } 316 390 … … 324 398 Returns: string value of argument 325 399 **************************************************************************/ 326 override char[] stringize(Any value) { 327 return STRINGIZER!(T)(value); 400 override char[] stringize(Any value) 401 in { 402 assert(m_stringizer); 403 } 404 body { 405 return m_stringizer(this, value); 328 406 } 329 407 … … 361 439 } 362 440 441 /*************************************************************************** 442 **************************************************************************/ 443 TypedValue parser(T function(TypedValue, char[]) parser) { 444 m_parser = parser; 445 return this; 446 } 447 448 /*************************************************************************** 449 **************************************************************************/ 450 T function(TypedValue, char[]) parser() { 451 return m_parser; 452 } 453 454 /*************************************************************************** 455 **************************************************************************/ 456 TypedValue stringizer(char[] function(TypedValue, Any) stringizer) { 457 m_stringizer = stringizer; 458 return this; 459 } 460 461 /*************************************************************************** 462 **************************************************************************/ 463 char[] function(TypedValue, Any) stringizer() { 464 return m_stringizer; 465 } 466 363 467 static if (isCommonArray!(T)) { 364 468 /*************************************************************************** … … 385 489 386 490 /*************************************************************************** 491 Getter 492 Returns: separator 493 **************************************************************************/ 494 char[] separator() { 495 return m_sep; 496 } 497 498 /*************************************************************************** 387 499 Setter 388 500 Params: skip = which characters should be skipped, when list is parsed … … 395 507 } 396 508 509 /*************************************************************************** 510 Returns: skip characters 511 **************************************************************************/ 512 char[] skip() { 513 return m_skip; 514 } 515 516 /*************************************************************************** 517 Params: sem = semantic of array elements 518 **************************************************************************/ 519 TypedValue elementSemantic(TypedValue!(arrayElementType!(T)) sem) { 520 m_elementSemantic = sem; 521 return this; 522 } 523 524 /*************************************************************************** 525 Returns: semantic of array elements 526 **************************************************************************/ 527 TypedValue!(arrayElementType!(T)) elementSemantic() { 528 return m_elementSemantic; 529 } 530 531 397 532 } else { 398 533 … … 413 548 char[] m_default_value_as_text, m_pattern; 414 549 bool m_composing, m_zero_tokens; 550 T function(TypedValue, char[]) m_parser; 551 char[] function(TypedValue, Any) m_stringizer; 415 552 416 553 static if (isCommonArray!(T)) { 554 TypedValue!(arrayElementType!(T)) m_elementSemantic; 417 555 char[] m_sep = ",;"; 418 556 char[] m_skip = " \t\r"; … … 427 565 method to create ValueSemantic instance for a specific type. 428 566 ******************************************************************************/ 429 TypedValue!(T , PARSER, STRINGIZER) define(T, alias PARSER = parseText, alias STRINGIZER = stringizeValue)(char[] pattern=null) {430 return new TypedValue!(T , PARSER)(pattern);567 TypedValue!(T) define(T)(char[] pattern=null) { 568 return new TypedValue!(T)(pattern); 431 569 } 432 570 trunk/examples/util/config/FunctionTest.d
r22 r28 22 22 import std.string; 23 23 24 import doost.util. TestHelper;24 import doost.util.DUnit; 25 25 26 26 import doost.util.config.ProgramOptions; //Always … … 33 33 //description and for user defined 34 34 //formatters 35 36 import doost.util.config.Value; 35 37 version(ddbi_v62) { 36 38 import dbi.Database; … … 54 56 //------------------------------------------------------------------------------ 55 57 56 T parseText(T : myVal)(char[] xs, char[] pattern) { 57 if (xs is null) throw new InvalidOptionValueException; 58 myVal parseMyValue(TypedValue!(myVal) owner, char[] xs) { 58 59 char[] s = xs.dup; 59 60 60 61 int val; 61 62 try { 62 val= stringToType!(int)(s);63 val=to!(int)(s); 63 64 } catch (Exception) { 64 65 throw new InvalidOptionValueException(s); … … 67 68 } 68 69 70 //------------------------------------------------------------------------------ 71 69 72 unittest { 70 71 //------------------------------------------------------------------------------72 73 startSuite("ProgramOptions"); 73 74 RegularOptions ro, ro1, ro2, cmd, cmd1, fil, fil1, env, env1; 75 CommandLineOptions spc; 76 ProgramOptions po; 77 char[][] args, args1; 78 char[] str1, str2, str3; 79 void[] buffer, buffer1; 80 char[] real_desc, expc_desc; 81 char[][] opts1, opts2, opts3; 82 int counter; 83 84 //------------------------------------------------------------------------------ 85 86 startTest("Opt.Description - Standard & General Opt."); 87 88 cmd = new RegularOptions("Command line"); 89 cmd.options() 74 } 75 76 //------------------------------------------------------------------------------ 77 78 unittest { testcase("Opt.Description - regular options", { 79 RegularOptions ro; 80 81 ro = new RegularOptions("Command line"); 82 ro.options() 90 83 ("help,h", "produce help message") 91 84 ("doTheTest,d", "maketest") … … 97 90 ("title,t", define!(char[]).defaultValue("title"), "set title of window") 98 91 ("include,i", define!(char[][]).composing.defaultValue(["default1"[], "default2"]), "include paths") 99 ("myVal", define!(myVal , parseText), "include paths")92 ("myVal", define!(myVal).parser(&parseMyValue), "include paths") 100 93 ("firstname", define!(char[][]).composing, "firstname") 101 94 ("secondname", define!(char[][]).composing, "secondname") … … 110 103 (",J", define!(char[][]), "import paths") 111 104 ; 112 113 finishTest; 114 115 //------------------------------------------------------------------------------ 116 117 startTest("Opt.Description - Groups adding"); 105 });} 106 107 //------------------------------------------------------------------------------ 108 109 unittest { testcase("Opt.Description - adding groups", { 110 RegularOptions ro, ro1, ro2; 111 string real_desc, expc_desc; 112 118 113 119 114 ro = new RegularOptions("First group"); … … 186 181 //writefln("\n", real_desc); 187 182 assert(removechars(real_desc, " \t\n\r") == removechars(expc_desc, " \t\n\r")); 188 189 finishTest; 190 191 //------------------------------------------------------------------------------ 192 193 startTest("CL Opt.Description - Special CL Options"); 194 195 spc = new CommandLineOptions; 183 });} 184 185 //------------------------------------------------------------------------------ 186 187 unittest { testcase("CL Opt.Description - special CL options", { 188 auto spc = new CommandLineOptions; 196 189 spc.options() 197 190 ("selfpath", new SelfPath) … … 201 194 ; 202 195 203 finishTest; 204 205 //------------------------------------------------------------------------------ 206 207 startTest("CL Opt.Description - Options sanity"); 208 209 assert(checkAssertError({ 210 cmd = new RegularOptions; 211 cmd.options() 196 });} 197 198 //------------------------------------------------------------------------------ 199 200 unittest { testcase("CL Opt.Description - options sanity", { 201 RegularOptions ro; 202 CommandLineOptions clo; 203 204 assert(checkAssert({ 205 ro = new RegularOptions; 206 ro.options() 212 207 ("title,t", define!(char[]), "window title") 213 208 ("process,t", define!(uint), "process number") … … 215 210 })); 216 211 217 assert(checkAssert Error({218 cmd= new RegularOptions;219 cmd.options()212 assert(checkAssert({ 213 ro = new RegularOptions; 214 ro.options() 220 215 ("title", define!(char[]), "window title") 221 216 ("title,t", define!(uint), "process number") … … 223 218 })); 224 219 225 assert(checkAssert Error({226 cmd= new RegularOptions;227 cmd.options()220 assert(checkAssert({ 221 ro = new RegularOptions; 222 ro.options() 228 223 ("title", define!(char[]), "window title") 229 224 ("title,t", define!(uint), "process number") … … 231 226 })); 232 227 233 assert(checkAssert Error({234 cmd= new RegularOptions;235 cmd.options()228 assert(checkAssert({ 229 ro = new RegularOptions; 230 ro.options() 236 231 (".*", define!(char[]), "all other options") 237 232 (".*", define!(char[]), "other other options") … … 239 234 })); 240 235 241 assert(checkAssert Error({242 spc= new CommandLineOptions;243 spc.options()236 assert(checkAssert({ 237 clo = new CommandLineOptions; 238 clo.options() 244 239 ("selfpath", new SelfPath) 245 240 ("selfpath", new SelfPath) … … 247 242 })); 248 243 249 finishTest; 250 251 252 //------------------------------------------------------------------------------ 253 startTest("CL Storage - lists"); 244 });} 245 246 //------------------------------------------------------------------------------ 247 248 unittest { testcase("CL Storage - lists", { 249 char[][] args; 250 RegularOptions ro; 251 ProgramOptions po; 254 252 255 253 args = ["bin", "--help", "--include", "'a';'b';'c'"]; 256 254 257 cmd= new RegularOptions("Command line");258 cmd.options()255 ro = new RegularOptions("Command line"); 256 ro.options() 259 257 ("help,h", "produce help message") 260 258 ("include,i", define!(char[][]).composing.defaultValue(["default1"[], "default2"]), "include paths") … … 265 263 266 264 po = (new ProgramOptions).next( 267 new CommandLineStorage(args, cmd)265 new CommandLineStorage(args, ro) 268 266 ); 269 267 … … 276 274 277 275 args = ["bin", "--include", "a;b;c", "--firstname=Anita , 'Ewa Krystyna', Paulina", 278 "--secondname", "'Korwin\ tMikke'", "-n[Aarti, Bono, Bruce]"];276 "--secondname", "'Korwin\\tMikke'", "-n[Aarti, Bono, Bruce]"]; 279 277 po.storage!(CommandLineStorage).args(args); 280 278 … … 287 285 288 286 po.disconnect;
