Initial commit
[yaffs-website] / node_modules / sprintf-js / src / sprintf.js
1 (function(window) {
2     var re = {
3         not_string: /[^s]/,
4         number: /[diefg]/,
5         json: /[j]/,
6         not_json: /[^j]/,
7         text: /^[^\x25]+/,
8         modulo: /^\x25{2}/,
9         placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijosuxX])/,
10         key: /^([a-z_][a-z_\d]*)/i,
11         key_access: /^\.([a-z_][a-z_\d]*)/i,
12         index_access: /^\[(\d+)\]/,
13         sign: /^[\+\-]/
14     }
15
16     function sprintf() {
17         var key = arguments[0], cache = sprintf.cache
18         if (!(cache[key] && cache.hasOwnProperty(key))) {
19             cache[key] = sprintf.parse(key)
20         }
21         return sprintf.format.call(null, cache[key], arguments)
22     }
23
24     sprintf.format = function(parse_tree, argv) {
25         var cursor = 1, tree_length = parse_tree.length, node_type = "", arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ""
26         for (i = 0; i < tree_length; i++) {
27             node_type = get_type(parse_tree[i])
28             if (node_type === "string") {
29                 output[output.length] = parse_tree[i]
30             }
31             else if (node_type === "array") {
32                 match = parse_tree[i] // convenience purposes only
33                 if (match[2]) { // keyword argument
34                     arg = argv[cursor]
35                     for (k = 0; k < match[2].length; k++) {
36                         if (!arg.hasOwnProperty(match[2][k])) {
37                             throw new Error(sprintf("[sprintf] property '%s' does not exist", match[2][k]))
38                         }
39                         arg = arg[match[2][k]]
40                     }
41                 }
42                 else if (match[1]) { // positional argument (explicit)
43                     arg = argv[match[1]]
44                 }
45                 else { // positional argument (implicit)
46                     arg = argv[cursor++]
47                 }
48
49                 if (get_type(arg) == "function") {
50                     arg = arg()
51                 }
52
53                 if (re.not_string.test(match[8]) && re.not_json.test(match[8]) && (get_type(arg) != "number" && isNaN(arg))) {
54                     throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg)))
55                 }
56
57                 if (re.number.test(match[8])) {
58                     is_positive = arg >= 0
59                 }
60
61                 switch (match[8]) {
62                     case "b":
63                         arg = arg.toString(2)
64                     break
65                     case "c":
66                         arg = String.fromCharCode(arg)
67                     break
68                     case "d":
69                     case "i":
70                         arg = parseInt(arg, 10)
71                     break
72                     case "j":
73                         arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0)
74                     break
75                     case "e":
76                         arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential()
77                     break
78                     case "f":
79                         arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg)
80                     break
81                     case "g":
82                         arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg)
83                     break
84                     case "o":
85                         arg = arg.toString(8)
86                     break
87                     case "s":
88                         arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg)
89                     break
90                     case "u":
91                         arg = arg >>> 0
92                     break
93                     case "x":
94                         arg = arg.toString(16)
95                     break
96                     case "X":
97                         arg = arg.toString(16).toUpperCase()
98                     break
99                 }
100                 if (re.json.test(match[8])) {
101                     output[output.length] = arg
102                 }
103                 else {
104                     if (re.number.test(match[8]) && (!is_positive || match[3])) {
105                         sign = is_positive ? "+" : "-"
106                         arg = arg.toString().replace(re.sign, "")
107                     }
108                     else {
109                         sign = ""
110                     }
111                     pad_character = match[4] ? match[4] === "0" ? "0" : match[4].charAt(1) : " "
112                     pad_length = match[6] - (sign + arg).length
113                     pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : "") : ""
114                     output[output.length] = match[5] ? sign + arg + pad : (pad_character === "0" ? sign + pad + arg : pad + sign + arg)
115                 }
116             }
117         }
118         return output.join("")
119     }
120
121     sprintf.cache = {}
122
123     sprintf.parse = function(fmt) {
124         var _fmt = fmt, match = [], parse_tree = [], arg_names = 0
125         while (_fmt) {
126             if ((match = re.text.exec(_fmt)) !== null) {
127                 parse_tree[parse_tree.length] = match[0]
128             }
129             else if ((match = re.modulo.exec(_fmt)) !== null) {
130                 parse_tree[parse_tree.length] = "%"
131             }
132             else if ((match = re.placeholder.exec(_fmt)) !== null) {
133                 if (match[2]) {
134                     arg_names |= 1
135                     var field_list = [], replacement_field = match[2], field_match = []
136                     if ((field_match = re.key.exec(replacement_field)) !== null) {
137                         field_list[field_list.length] = field_match[1]
138                         while ((replacement_field = replacement_field.substring(field_match[0].length)) !== "") {
139                             if ((field_match = re.key_access.exec(replacement_field)) !== null) {
140                                 field_list[field_list.length] = field_match[1]
141                             }
142                             else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
143                                 field_list[field_list.length] = field_match[1]
144                             }
145                             else {
146                                 throw new SyntaxError("[sprintf] failed to parse named argument key")
147                             }
148                         }
149                     }
150                     else {
151                         throw new SyntaxError("[sprintf] failed to parse named argument key")
152                     }
153                     match[2] = field_list
154                 }
155                 else {
156                     arg_names |= 2
157                 }
158                 if (arg_names === 3) {
159                     throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported")
160                 }
161                 parse_tree[parse_tree.length] = match
162             }
163             else {
164                 throw new SyntaxError("[sprintf] unexpected placeholder")
165             }
166             _fmt = _fmt.substring(match[0].length)
167         }
168         return parse_tree
169     }
170
171     var vsprintf = function(fmt, argv, _argv) {
172         _argv = (argv || []).slice(0)
173         _argv.splice(0, 0, fmt)
174         return sprintf.apply(null, _argv)
175     }
176
177     /**
178      * helpers
179      */
180     function get_type(variable) {
181         return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()
182     }
183
184     function str_repeat(input, multiplier) {
185         return Array(multiplier + 1).join(input)
186     }
187
188     /**
189      * export to either browser or node.js
190      */
191     if (typeof exports !== "undefined") {
192         exports.sprintf = sprintf
193         exports.vsprintf = vsprintf
194     }
195     else {
196         window.sprintf = sprintf
197         window.vsprintf = vsprintf
198
199         if (typeof define === "function" && define.amd) {
200             define(function() {
201                 return {
202                     sprintf: sprintf,
203                     vsprintf: vsprintf
204                 }
205             })
206         }
207     }
208 })(typeof window === "undefined" ? this : window);