|
1 | 1 | /*! sprintf.js | Copyright (c) 2007-2013 Alexandru Marasteanu <hello at alexei dot ro> | 3 clause BSD license */ |
2 | 2 |
|
3 | 3 | (function(ctx){ |
4 | | -varsprintf=function(){ |
5 | | -if(!sprintf.cache.hasOwnProperty(arguments[0])){ |
6 | | -sprintf.cache[arguments[0]]=sprintf.parse(arguments[0]); |
| 4 | +varre={ |
| 5 | +not_string:/[^s]/, |
| 6 | +number:/[def]/, |
| 7 | +text:/^[^\x25]+/, |
| 8 | +modulo:/^\x25{2}/, |
| 9 | +placeholder:/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/, |
| 10 | +key:/^([a-z_][a-z_\d]*)/i, |
| 11 | +key_access:/^\.([a-z_][a-z_\d]*)/i, |
| 12 | +index_access:/^\[(\d+)\]/ |
| 13 | +} |
| 14 | + |
| 15 | +functionsprintf(){ |
| 16 | +varkey=arguments[0],cache=sprintf.cache |
| 17 | +if(!(cache[key]&&cache.hasOwnProperty(key))){ |
| 18 | +cache[key]=sprintf.parse(key) |
7 | 19 | } |
8 | | -returnsprintf.format.call(null,sprintf.cache[arguments[0]],arguments); |
9 | | -}; |
| 20 | +returnsprintf.format.call(null,cache[key],arguments) |
| 21 | +} |
10 | 22 |
|
11 | 23 | sprintf.format=function(parse_tree,argv){ |
12 | | -varcursor=1,tree_length=parse_tree.length,node_type='',arg,output=[],i,k,match,pad,pad_character,pad_length; |
| 24 | +varcursor=1,tree_length=parse_tree.length,node_type="",arg,output=[],i,k,match,pad,pad_character,pad_length |
13 | 25 | for(i=0;i<tree_length;i++){ |
14 | | -node_type=get_type(parse_tree[i]); |
15 | | -if(node_type==='string'){ |
16 | | -output.push(parse_tree[i]); |
| 26 | +node_type=get_type(parse_tree[i]) |
| 27 | +if(node_type==="string"){ |
| 28 | +output[output.length]=parse_tree[i] |
17 | 29 | } |
18 | | -elseif(node_type==='array'){ |
19 | | -match=parse_tree[i];// convenience purposes only |
| 30 | +elseif(node_type==="array"){ |
| 31 | +match=parse_tree[i]// convenience purposes only |
20 | 32 | if(match[2]){// keyword argument |
21 | | -arg=argv[cursor]; |
| 33 | +arg=argv[cursor] |
22 | 34 | for(k=0;k<match[2].length;k++){ |
23 | 35 | if(!arg.hasOwnProperty(match[2][k])){ |
24 | | -thrownewError(sprintf('[sprintf] property"%s" does not exist',match[2][k])); |
| 36 | +thrownewError(sprintf("[sprintf] property'%s' does not exist",match[2][k])) |
25 | 37 | } |
26 | | -arg=arg[match[2][k]]; |
| 38 | +arg=arg[match[2][k]] |
27 | 39 | } |
28 | 40 | } |
29 | 41 | elseif(match[1]){// positional argument (explicit) |
30 | | -arg=argv[match[1]]; |
| 42 | +arg=argv[match[1]] |
31 | 43 | } |
32 | 44 | else{// positional argument (implicit) |
33 | | -arg=argv[cursor++]; |
| 45 | +arg=argv[cursor++] |
34 | 46 | } |
35 | 47 |
|
36 | | -if(/[^s]/.test(match[8])&&(get_type(arg)!='number')){ |
37 | | -thrownewTypeError(sprintf('[sprintf] expecting number but found %s',get_type(arg))); |
| 48 | +if(re.not_string.test(match[8])&&(get_type(arg)!="number")){ |
| 49 | +thrownewTypeError(sprintf("[sprintf] expecting number but found %s",get_type(arg))) |
38 | 50 | } |
39 | 51 | switch(match[8]){ |
40 | | -case'b':arg=arg.toString(2);break; |
41 | | -case'c':arg=String.fromCharCode(arg);break; |
42 | | -case'd':arg=parseInt(arg,10);break; |
43 | | -case'e':arg=match[7] ?arg.toExponential(match[7]) :arg.toExponential();break; |
44 | | -case'f':arg=match[7] ?parseFloat(arg).toFixed(match[7]) :parseFloat(arg);break; |
45 | | -case'o':arg=arg.toString(8);break; |
46 | | -case's':arg=((arg=String(arg))&&match[7] ?arg.substring(0,match[7]) :arg);break; |
47 | | -case'u':arg=arg>>>0;break; |
48 | | -case'x':arg=arg.toString(16);break; |
49 | | -case'X':arg=arg.toString(16).toUpperCase();break; |
| 52 | +case"b": |
| 53 | +arg=arg.toString(2) |
| 54 | +break |
| 55 | +case"c": |
| 56 | +arg=String.fromCharCode(arg) |
| 57 | +break |
| 58 | +case"d": |
| 59 | +arg=parseInt(arg,10) |
| 60 | +break |
| 61 | +case"e": |
| 62 | +arg=match[7] ?arg.toExponential(match[7]) :arg.toExponential() |
| 63 | +break |
| 64 | +case"f": |
| 65 | +arg=match[7] ?parseFloat(arg).toFixed(match[7]) :parseFloat(arg) |
| 66 | +break |
| 67 | +case"o": |
| 68 | +arg=arg.toString(8) |
| 69 | +break |
| 70 | +case"s": |
| 71 | +arg=((arg=String(arg))&&match[7] ?arg.substring(0,match[7]) :arg) |
| 72 | +break |
| 73 | +case"u": |
| 74 | +arg=arg>>>0 |
| 75 | +break |
| 76 | +case"x": |
| 77 | +arg=arg.toString(16) |
| 78 | +break |
| 79 | +case"X": |
| 80 | +arg=arg.toString(16).toUpperCase() |
| 81 | +break |
50 | 82 | } |
51 | | -arg=(/[def]/.test(match[8])&&match[3]&&arg>=0 ?'+'+arg :arg); |
52 | | -pad_character=match[4] ?match[4]=='0' ?'0' :match[4].charAt(1) :' '; |
53 | | -pad_length=match[6]-String(arg).length; |
54 | | -pad=match[6] ?str_repeat(pad_character,pad_length) :''; |
55 | | -output.push(match[5] ?arg+pad :pad+arg); |
| 83 | +arg=(re.number.test(match[8])&&match[3]&&arg>=0 ?"+"+arg :arg) |
| 84 | +pad_character=match[4] ?match[4]=="0" ?"0" :match[4].charAt(1) :" " |
| 85 | +pad_length=match[6]-String(arg).length |
| 86 | +pad=match[6] ?str_repeat(pad_character,pad_length) :"" |
| 87 | +output[output.length]=match[5] ?arg+pad :pad+arg |
56 | 88 | } |
57 | 89 | } |
58 | | -returnoutput.join(''); |
59 | | -}; |
| 90 | +returnoutput.join("") |
| 91 | +} |
60 | 92 |
|
61 | | -sprintf.cache={}; |
| 93 | +sprintf.cache={} |
62 | 94 |
|
63 | 95 | sprintf.parse=function(fmt){ |
64 | | -var_fmt=fmt,match=[],parse_tree=[],arg_names=0; |
| 96 | +var_fmt=fmt,match=[],parse_tree=[],arg_names=0 |
65 | 97 | while(_fmt){ |
66 | | -if((match=/^[^\x25]+/.exec(_fmt))!==null){ |
67 | | -parse_tree.push(match[0]); |
| 98 | +if((match=re.text.exec(_fmt))!==null){ |
| 99 | +parse_tree[parse_tree.length]=match[0] |
68 | 100 | } |
69 | | -elseif((match=/^\x25{2}/.exec(_fmt))!==null){ |
70 | | -parse_tree.push('%'); |
| 101 | +elseif((match=re.modulo.exec(_fmt))!==null){ |
| 102 | +parse_tree[parse_tree.length]="%" |
71 | 103 | } |
72 | | -elseif((match=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt))!==null){ |
| 104 | +elseif((match=re.placeholder.exec(_fmt))!==null){ |
73 | 105 | if(match[2]){ |
74 | | -arg_names|=1; |
75 | | -varfield_list=[],replacement_field=match[2],field_match=[]; |
76 | | -if((field_match=/^([a-z_][a-z_\d]*)/i.exec(replacement_field))!==null){ |
77 | | -field_list.push(field_match[1]); |
78 | | -while((replacement_field=replacement_field.substring(field_match[0].length))!==''){ |
79 | | -if((field_match=/^\.([a-z_][a-z_\d]*)/i.exec(replacement_field))!==null){ |
80 | | -field_list.push(field_match[1]); |
| 106 | +arg_names|=1 |
| 107 | +varfield_list=[],replacement_field=match[2],field_match=[] |
| 108 | +if((field_match=re.key.exec(replacement_field))!==null){ |
| 109 | +field_list[field_list.length]=field_match[1] |
| 110 | +while((replacement_field=replacement_field.substring(field_match[0].length))!==""){ |
| 111 | +if((field_match=re.key_access.exec(replacement_field))!==null){ |
| 112 | +field_list[field_list.length]=field_match[1] |
81 | 113 | } |
82 | | -elseif((field_match=/^\[(\d+)\]/.exec(replacement_field))!==null){ |
83 | | -field_list.push(field_match[1]); |
| 114 | +elseif((field_match=re.index_access.exec(replacement_field))!==null){ |
| 115 | +field_list[field_list.length]=field_match[1] |
84 | 116 | } |
85 | 117 | else{ |
86 | | -thrownewSyntaxError('[sprintf] failed to parse named argument key'); |
| 118 | +thrownewSyntaxError("[sprintf] failed to parse named argument key") |
87 | 119 | } |
88 | 120 | } |
89 | 121 | } |
90 | 122 | else{ |
91 | | -thrownewSyntaxError('[sprintf] failed to parse named argument key'); |
| 123 | +thrownewSyntaxError("[sprintf] failed to parse named argument key") |
92 | 124 | } |
93 | | -match[2]=field_list; |
| 125 | +match[2]=field_list |
94 | 126 | } |
95 | 127 | else{ |
96 | | -arg_names|=2; |
| 128 | +arg_names|=2 |
97 | 129 | } |
98 | 130 | if(arg_names===3){ |
99 | | -thrownewError('[sprintf] mixing positional and named placeholders is not (yet) supported'); |
| 131 | +thrownewError("[sprintf] mixing positional and named placeholders is not (yet) supported") |
100 | 132 | } |
101 | | -parse_tree.push(match); |
| 133 | +parse_tree[parse_tree.length]=match |
102 | 134 | } |
103 | 135 | else{ |
104 | | -thrownewSyntaxError('[sprintf] unexpected placeholder'); |
| 136 | +thrownewSyntaxError("[sprintf] unexpected placeholder") |
105 | 137 | } |
106 | | -_fmt=_fmt.substring(match[0].length); |
| 138 | +_fmt=_fmt.substring(match[0].length) |
107 | 139 | } |
108 | | -returnparse_tree; |
109 | | -}; |
| 140 | +returnparse_tree |
| 141 | +} |
110 | 142 |
|
111 | 143 | varvsprintf=function(fmt,argv,_argv){ |
112 | | -_argv=(argv||[]).slice(0); |
113 | | -_argv.splice(0,0,fmt); |
114 | | -returnsprintf.apply(null,_argv); |
115 | | -}; |
| 144 | +_argv=(argv||[]).slice(0) |
| 145 | +_argv.splice(0,0,fmt) |
| 146 | +returnsprintf.apply(null,_argv) |
| 147 | +} |
116 | 148 |
|
117 | 149 | /** |
118 | 150 | * helpers |
119 | 151 | */ |
120 | 152 | functionget_type(variable){ |
121 | | -returnObject.prototype.toString.call(variable).slice(8,-1).toLowerCase(); |
| 153 | +returnObject.prototype.toString.call(variable).slice(8,-1).toLowerCase() |
122 | 154 | } |
123 | 155 |
|
124 | 156 | functionstr_repeat(input,multiplier){ |
|
128 | 160 | /** |
129 | 161 | * export to either browser or node.js |
130 | 162 | */ |
131 | | -ctx.sprintf=sprintf; |
132 | | -ctx.vsprintf=vsprintf; |
133 | | -})(typeofexports!="undefined" ?exports :window); |
| 163 | +ctx.sprintf=sprintf |
| 164 | +ctx.vsprintf=vsprintf |
| 165 | +})(typeofexports!="undefined" ?exports :window) |