+var cbi_strings = { path: {}, label: {} };
+
+function Int(x) {
+ return (/^-?\d+$/.test(x) ? +x : NaN);
+}
+
+function Dec(x) {
+ return (/^-?\d+(?:\.\d+)?$/.test(x) ? +x : NaN);
+}
+
+function IPv4(x) {
+ if (!x.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))
+ return null;
+
+ if (RegExp.$1 > 255 || RegExp.$2 > 255 || RegExp.$3 > 255 || RegExp.$4 > 255)
+ return null;
+
+ return [ +RegExp.$1, +RegExp.$2, +RegExp.$3, +RegExp.$4 ];
+}
+
+function IPv6(x) {
+ if (x.match(/^([a-fA-F0-9:]+):(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/)) {
+ var v6 = RegExp.$1, v4 = IPv4(RegExp.$2);
+
+ if (!v4)
+ return null;
+
+ x = v6 + ':' + (v4[0] * 256 + v4[1]).toString(16)
+ + ':' + (v4[2] * 256 + v4[3]).toString(16);
+ }
+
+ if (!x.match(/^[a-fA-F0-9:]+$/))
+ return null;
+
+ var prefix_suffix = x.split(/::/);
+
+ if (prefix_suffix.length > 2)
+ return null;
+
+ var prefix = (prefix_suffix[0] || '0').split(/:/);
+ var suffix = prefix_suffix.length > 1 ? (prefix_suffix[1] || '0').split(/:/) : [];
+
+ if (suffix.length ? (prefix.length + suffix.length > 7) : (prefix.length > 8))
+ return null;
+
+ var i, word;
+ var words = [];
+
+ for (i = 0, word = parseInt(prefix[0], 16); i < prefix.length; word = parseInt(prefix[++i], 16))
+ if (prefix[i].length <= 4 && !isNaN(word) && word <= 0xFFFF)
+ words.push(word);
+ else
+ return null;
+
+ for (i = 0; i < (8 - prefix.length - suffix.length); i++)
+ words.push(0);
+
+ for (i = 0, word = parseInt(suffix[0], 16); i < suffix.length; word = parseInt(suffix[++i], 16))
+ if (suffix[i].length <= 4 && !isNaN(word) && word <= 0xFFFF)
+ words.push(word);
+ else
+ return null;
+
+ return words;
+}