Changeset 28

Show
Ignore:
Timestamp:
01/21/08 17:09:38 (1 year ago)
Author:
aarti_pl
Message:

new modules:
- serializer
- DUnit
- Escaper
- Traits

- few updates to ProgramOptions. There will be more updates to use internally Serializer
- uses std2 port by Bill Baxter

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/doost/core/Any.d

    r20 r28  
    1818module doost.core.Any; 
    1919 
    20 import doost.util.TestHelper
     20import doost.util.DUnit
    2121 
    2222// ----------------------------------------------------------------------------- 
     
    208208 
    209209import std.stdio; 
    210  
    211 import doost.util.TestHelper; 
     210import doost.util.DUnit; 
     211 
     212//------------------------------------------------------------------------------ 
    212213 
    213214unittest { 
    214215    startSuite("Any"); 
    215     class Test { 
    216         char[] toString() { 
    217             return "Test class".dup; 
    218         } 
    219         void doTest() {}; 
    220     } 
    221  
     216
     217 
     218//------------------------------------------------------------------------------ 
     219 
     220class Test { 
     221    char[] toString() { 
     222        return "Test class".dup; 
     223    } 
     224    void doTest() {} 
     225
     226 
     227//------------------------------------------------------------------------------ 
     228 
     229unittest { testcase("Any - assigning", { 
    222230    bool assigned=false; 
    223231    auto t=new Test; 
     
    226234    auto z = Any(); 
    227235 
    228 //------------------------------------------------------------------------------ 
    229  
    230     startTest("Assigning"); 
    231236    v=5; 
    232237    assert(v.as!(int) == 5); 
     
    245250    v=ba; 
    246251    assert(v.as!(byte[]) == [cast(byte)(5),16,78,90]); 
    247  
    248     finishTest; 
    249  
    250 //------------------------------------------------------------------------------ 
    251  
    252     startTest("Comparing"); 
     252});} 
     253 
     254//------------------------------------------------------------------------------ 
     255 
     256unittest { testcase("Any - comparing", { 
     257    auto v = Any(); 
     258    auto z = Any(); 
    253259 
    254260    v=5; z=5; 
     
    257263    v="Ala"[]; z="Ola"[]; 
    258264    assert(v != z); 
    259  
    260     finishTest; 
    261  
    262 //------------------------------------------------------------------------------ 
    263  
    264     startTest("toString"); 
    265  
     265});} 
     266 
     267//------------------------------------------------------------------------------ 
     268 
     269unittest { testcase("Any - toString()", { 
     270    auto v = Any(); 
    266271    v=5; 
    267272    assert(v.toString == "5"); 
     
    269274    v=new Test; 
    270275    assert(v.toString == "Test class"); 
    271  
    272  
    273     finishTest; 
    274  
    275 //------------------------------------------------------------------------------ 
    276  
     276});} 
     277 
     278//------------------------------------------------------------------------------ 
     279 
     280unittest { 
    277281    finishSuite; 
    278282} 
  • trunk/doost/util/config/CommandLineStorage.d

    r22 r28  
    2121import std.stdio; 
    2222import std.path; 
     23import std2.conv; 
    2324 
    2425import doost.core.Any; 
     
    429430                m_trailing = name; 
    430431            } else { 
    431                 maxCount=std.conv.toUint(cnt); 
     432                maxCount=to!(uint)(cnt); 
    432433                while (maxCount>0) {m_names~=name; maxCount--; }; 
    433434            } 
     
    692693                            is(typeof(p) : CommandLineOptions), 
    693694                            "Type " ~ typeof(p).stringof ~ " is not allowed."); 
    694             assert(p !is null); 
     695            assert(p !is null, "Option value can not be null!"); 
    695696        } 
    696697    } 
     
    798799            auto path = m_desc.matchClass!(SelfPath)(OptionCharacteristic.Single); 
    799800 
     801            //writefln(self); 
    800802            if (file !is null) opts~=ParsedOption(file.key, getBaseName(self), file); 
    801803            if (dir !is null) opts~=ParsedOption(dir.key, getDirName(self), dir); 
  • trunk/doost/util/config/Converter.d

    r22 r28  
    1818module doost.util.config.Converter; 
    1919 
    20 import std.conv; 
    2120import std.string; 
    2221import std.stdio; 
     
    2423import std.format; 
    2524 
     25public import std2.conv; 
    2626public import doost.core.Any; 
    2727import doost.util.config.Exception; 
    2828import 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 
     29import doost.util.config.Value; 
     30import doost.text.Escaper; 
    6431 
    6532//------------------------------------------------------------------------------ 
     
    9562 
    9663/******************************************************************************* 
     64 ******************************************************************************/ 
     65void 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/******************************************************************************* 
    9777    The target type is specified via a parameter which has the type of 
    9878    pointer to the desired type. This is workaround for compilers without 
     
    10080 
    10181    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 ******************************************************************************/ 
     83T parseValue(T)(TypedValue!(T) owner, char[] xs) { 
    10684    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); 
    11687} 
    11788 
     
    12394    Params: value = value to convert 
    12495 ******************************************************************************/ 
    125 char[] stringizeValue(T)(Any value) { 
     96char[] stringizeValue(T)(TypedValue!(T) owner, Any value) { 
    12697    static if (isAtomicType!(T)) { 
    12798        return toString(value.as!(T)); 
     
    153124 
    154125    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 
    158127*******************************************************************************/ 
    159 T[] parseText(T : T[])(char[] xs, char[] pattern, char[] sep, char[] skip) { 
     128T[] parseValue(T : T[])(TypedValue!(T[]) owner, char[] xs) { 
     129    pragma(msg, T.stringof); 
    160130    T[] tv; 
    161131 
    162132    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Ä 
     138ce i zamykajÄ 
     139ce teÅŒ powinny być parametrem, a nie 
     140    //zahardkodowane 
    163141    if (list.length>1) { 
    164142        if (list[0] == '[' && list[$-1] == ']') { 
     
    168146    } 
    169147 
    170     char[][] tokens = tokenizer(list, sep, skip); 
     148    //0. strip opening element 
     149    //0.2 strip z poczÄ 
     150tku 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Ä 
     156gnij 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
     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Ä 
     171tkowego stringu, ale trzeba będzie włĠ
     172czyć 
     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); 
    171177    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)); 
    173182    } 
    174183 
     
    183192    Params: v = value of array 
    184193 ******************************************************************************/ 
    185 char[] stringizeValue(T: T[])(Any v) { 
     194char[] stringizeValue(T : T[])(TypedValue!(T[]) owner, Any v) { 
    186195    assert(v !is null); 
    187196    char[] result; 
     
    190199 
    191200    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])); 
    193203        result~=", "; 
    194204    } 
    195205 
    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])); 
    197208 
    198209    return result; 
     
    207218 
    208219    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?? 
     225T parseValue(T : bool)(TypedValue!(bool) owner, char[] xs) { 
    212226    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łĠ
     237cznika moÅŒe wyłĠ
     238czać, jeÅŒeli defaultValue = true 
    217239    if (s.length == 0) return true; 
    218240 
    219     auto re = std.regexp.search(s, pattern); 
     241    auto re = std.regexp.search(s, ppattern); 
    220242    if (re !is null) { 
    221243        if (re.match(0) == s) return true; 
     
    224246    return false; 
    225247} 
     248 
     249//TODO: w przypadku list w opisie powinno być nie arg, ale list 
     250//TODO: przerobić boolSwitcha na prawdziwego switcha, który przełĠ
     251cza 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 
    226256 
    227257//------------------------------------------------------------------------------ 
     
    233263 
    234264    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[] 
     267T parseValue(T : char[])(TypedValue!(char[]) owner, char[] xs) { 
    240268    char[] s=xs.dup; 
    241269    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] == '"'))) { 
    243271        s = s[1..$-1]; 
    244272        skipEscapes=false; 
    245273    } 
    246274 
    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); 
    254276 
    255277    char[] result; 
    256278    //When there was no '' or "" characters escape characters are not replaced 
    257279    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); 
    271281    } else result = s; 
    272282 
     
    280290 
    281291    Params: v = value of string 
    282  ******************************************************************************/ 
    283 char[] stringizeValue(T: char[])(Any v) { 
     292    Returns: stringized value 
     293 ******************************************************************************/ 
     294char[] stringizeValue(T : char[])(TypedValue!(char[]) owner, Any v) { 
    284295    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[])); 
    289297    return "\"" ~ result ~ "\""; 
    290298} 
  • trunk/doost/util/config/Option.d

    r22 r28  
    303303        result.m_description = m_description is null ? null : m_description.dup; 
    304304        result.m_semantic = m_semantic is null ? null : m_semantic.dup; 
     305        result.m_characteristics = m_characteristics; 
    305306    } 
    306307 
  • trunk/doost/util/config/ProgramOptions.d

    r22 r28  
    11271127 
    11281128        try { 
     1129            //writefln(name, "  <->  ", strVal); 
    11291130            desc.semantic.parse(aval, strVal); 
    11301131            if (desc.characteristics & OptionCharacteristic.Keyed) m_collected[name]=true; 
  • trunk/doost/util/config/Utils.d

    r20 r28  
    101101/******************************************************************************* 
    102102 ******************************************************************************/ 
    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  ******************************************************************************/ 
    147103char[] loadFileContents(char[] file) { 
    148104    return cast(char[])read(file); 
  • trunk/doost/util/config/Value.d

    r22 r28  
    4141} 
    4242 
     43//------------------------------------------------------------------------------ 
     44 
     45/******************************************************************************* 
     46    Evaluates to type 
     47 ******************************************************************************/ 
     48template arrayElementType(T) { 
     49    static if( is( T U : U[] ) ) 
     50        alias U arrayElementType; 
     51    else 
     52        static assert(false); 
     53} 
     54 
    4355/******************************************************************************* 
    4456    Evaluates to true if given type is array, but excluding char[], wchar[] 
     
    6981 
    7082/******************************************************************************* 
     83    Evaluates to true if type of T is known (parsers and stringizers are 
     84    available) 
     85 ******************************************************************************/ 
     86template 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/******************************************************************************* 
    7197    Interface which specifies how the option's value is to be parsed 
    7298    and converted into D types. 
     
    227253    Class which handles value of a specific type. 
    228254 ******************************************************************************/ 
    229 class TypedValue(T, alias PARSER = parseText, alias STRINGIZER = stringizeValue) : ValueSemantic { 
     255class TypedValue(T) : ValueSemantic { 
    230256public: 
    231257    /*************************************************************************** 
     
    237263        m_pattern=pattern; 
    238264        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 
    239299    } 
    240300 
     
    272332 
    273333    /*************************************************************************** 
     334        Returns: pattern for value 
     335     **************************************************************************/ 
     336    char[] pattern() { 
     337        return m_pattern; 
     338    } 
     339 
     340    /*************************************************************************** 
    274341        Returns true if option can be composed. If it is true, option can appear 
    275342        many times in source and will be composed into array. 
     
    301368 
    302369    /*************************************************************************** 
    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 { 
    307377        T result; 
    308378 
    309379        static if (isCommonArray!(T)) { 
     380            //TODO: sprawdzenie czy jest composing, jeÅŒeli nie to throw 
    310381            if (!value.empty) result = value.as!(T); 
    311             result ~= PARSER!(T)(token, m_pattern, m_sep, m_skip); 
     382            result ~= m_parser(this, token); 
    312383        } else { 
    313384            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); 
    315389        } 
    316390 
     
    324398        Returns: string value of argument 
    325399     **************************************************************************/ 
    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); 
    328406    } 
    329407 
     
    361439    } 
    362440 
     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 
    363467static if (isCommonArray!(T)) { 
    364468    /*************************************************************************** 
     
    385489 
    386490    /*************************************************************************** 
     491        Getter 
     492        Returns: separator 
     493     **************************************************************************/ 
     494    char[] separator() { 
     495        return m_sep; 
     496    } 
     497 
     498    /*************************************************************************** 
    387499        Setter 
    388500        Params: skip = which characters should be skipped, when list is parsed 
     
    395507    } 
    396508 
     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 
    397532} else { 
    398533 
     
    413548    char[] m_default_value_as_text, m_pattern; 
    414549    bool m_composing, m_zero_tokens; 
     550    T function(TypedValue, char[]) m_parser; 
     551    char[] function(TypedValue, Any) m_stringizer; 
    415552 
    416553static if (isCommonArray!(T)) { 
     554    TypedValue!(arrayElementType!(T)) m_elementSemantic; 
    417555    char[] m_sep = ",;"; 
    418556    char[] m_skip = " \t\r"; 
     
    427565    method to create ValueSemantic instance for a specific type. 
    428566 ******************************************************************************/ 
    429 TypedValue!(T, PARSER, STRINGIZER) define(T, alias PARSER = parseText, alias STRINGIZER = stringizeValue)(char[] pattern=null) { 
    430     return new TypedValue!(T, PARSER)(pattern); 
     567TypedValue!(T) define(T)(char[] pattern=null) { 
     568    return new TypedValue!(T)(pattern); 
    431569} 
    432570 
  • trunk/examples/util/config/FunctionTest.d

    r22 r28  
    2222import std.string; 
    2323 
    24 import doost.util.TestHelper
     24import doost.util.DUnit
    2525 
    2626import doost.util.config.ProgramOptions;        //Always 
     
    3333                                                //description and for user defined 
    3434                                                //formatters 
     35 
     36import doost.util.config.Value; 
    3537version(ddbi_v62) { 
    3638    import dbi.Database; 
     
    5456//------------------------------------------------------------------------------ 
    5557 
    56 T parseText(T : myVal)(char[] xs, char[] pattern) { 
    57     if (xs is null) throw new InvalidOptionValueException; 
     58myVal parseMyValue(TypedValue!(myVal) owner, char[] xs) { 
    5859    char[] s = xs.dup; 
    5960 
    6061    int val; 
    6162    try { 
    62         val=stringToType!(int)(s); 
     63        val=to!(int)(s); 
    6364    } catch (Exception) { 
    6465        throw new InvalidOptionValueException(s); 
     
    6768} 
    6869 
     70//------------------------------------------------------------------------------ 
     71 
    6972unittest { 
    70  
    71 //------------------------------------------------------------------------------ 
    7273    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 
     78unittest { testcase("Opt.Description - regular options", { 
     79    RegularOptions ro; 
     80 
     81    ro = new RegularOptions("Command line"); 
     82    ro.options() 
    9083        ("help,h", "produce help message") 
    9184        ("doTheTest,d", "maketest") 
     
    9790        ("title,t", define!(char[]).defaultValue("title"), "set title of window") 
    9891        ("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") 
    10093        ("firstname", define!(char[][]).composing, "firstname") 
    10194        ("secondname", define!(char[][]).composing, "secondname") 
     
    110103        (",J", define!(char[][]), "import paths") 
    111104    ; 
    112  
    113     finishTest; 
    114  
    115 //------------------------------------------------------------------------------ 
    116  
    117     startTest("Opt.Description - Groups adding"); 
     105});} 
     106 
     107//------------------------------------------------------------------------------ 
     108 
     109unittest { testcase("Opt.Description - adding groups", { 
     110    RegularOptions ro, ro1, ro2; 
     111    string real_desc, expc_desc; 
     112 
    118113 
    119114    ro = new RegularOptions("First group"); 
     
    186181    //writefln("\n", real_desc); 
    187182    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 
     187unittest { testcase("CL Opt.Description - special CL options", { 
     188    auto spc = new CommandLineOptions; 
    196189    spc.options() 
    197190        ("selfpath", new SelfPath) 
     
    201194    ; 
    202195 
    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 
     200unittest { testcase("CL Opt.Description - options sanity", { 
     201    RegularOptions ro; 
     202    CommandLineOptions clo; 
     203 
     204    assert(checkAssert({ 
     205        ro = new RegularOptions; 
     206        ro.options() 
    212207            ("title,t", define!(char[]), "window title") 
    213208            ("process,t", define!(uint), "process number") 
     
    215210    })); 
    216211 
    217     assert(checkAssertError({ 
    218         cmd = new RegularOptions; 
    219         cmd.options() 
     212    assert(checkAssert({ 
     213        ro = new RegularOptions; 
     214        ro.options() 
    220215            ("title", define!(char[]), "window title") 
    221216            ("title,t", define!(uint), "process number") 
     
    223218    })); 
    224219 
    225     assert(checkAssertError({ 
    226         cmd = new RegularOptions; 
    227         cmd.options() 
     220    assert(checkAssert({ 
     221        ro = new RegularOptions; 
     222        ro.options() 
    228223            ("title", define!(char[]), "window title") 
    229224            ("title,t", define!(uint), "process number") 
     
    231226    })); 
    232227 
    233     assert(checkAssertError({ 
    234         cmd = new RegularOptions; 
    235         cmd.options() 
     228    assert(checkAssert({ 
     229        ro = new RegularOptions; 
     230        ro.options() 
    236231            (".*", define!(char[]), "all other options") 
    237232            (".*", define!(char[]), "other other options") 
     
    239234    })); 
    240235 
    241     assert(checkAssertError({ 
    242         spc = new CommandLineOptions; 
    243         spc.options() 
     236    assert(checkAssert({ 
     237        clo = new CommandLineOptions; 
     238        clo.options() 
    244239            ("selfpath", new SelfPath) 
    245240            ("selfpath", new SelfPath) 
     
    247242    })); 
    248243 
    249     finishTest; 
    250  
    251  
    252 //------------------------------------------------------------------------------ 
    253     startTest("CL Storage - lists"); 
     244});} 
     245 
     246//------------------------------------------------------------------------------ 
     247 
     248unittest { testcase("CL Storage - lists", { 
     249    char[][] args; 
     250    RegularOptions ro; 
     251    ProgramOptions po; 
    254252 
    255253    args = ["bin", "--help", "--include", "'a';'b';'c'"]; 
    256254 
    257     cmd = new RegularOptions("Command line"); 
    258     cmd.options() 
     255    ro = new RegularOptions("Command line"); 
     256    ro.options() 
    259257        ("help,h", "produce help message") 
    260258        ("include,i", define!(char[][]).composing.defaultValue(["default1"[], "default2"]), "include paths") 
     
    265263 
    266264    po = (new ProgramOptions).next( 
    267             new CommandLineStorage(args, cmd
     265            new CommandLineStorage(args, ro
    268266         ); 
    269267 
     
    276274 
    277275    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]"]; 
    279277    po.storage!(CommandLineStorage).args(args); 
    280278 
     
    287285 
    288286    po.disconnect;