aboutsummaryrefslogtreecommitdiff
path: root/includes/js/dojox/string
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/string')
-rw-r--r--includes/js/dojox/string/Builder.js101
-rw-r--r--includes/js/dojox/string/README39
-rw-r--r--includes/js/dojox/string/sprintf.js406
-rw-r--r--includes/js/dojox/string/tests/Builder.js91
-rw-r--r--includes/js/dojox/string/tests/BuilderPerf.html403
-rw-r--r--includes/js/dojox/string/tests/PerfFun.html260
-rw-r--r--includes/js/dojox/string/tests/lipsum.js133
-rw-r--r--includes/js/dojox/string/tests/notes.txt153
-rw-r--r--includes/js/dojox/string/tests/peller.html78
-rw-r--r--includes/js/dojox/string/tests/runTests.html9
-rw-r--r--includes/js/dojox/string/tests/sprintf.js277
-rw-r--r--includes/js/dojox/string/tests/string.js10
-rw-r--r--includes/js/dojox/string/tokenize.js42
13 files changed, 2002 insertions, 0 deletions
diff --git a/includes/js/dojox/string/Builder.js b/includes/js/dojox/string/Builder.js
new file mode 100644
index 0000000..02082ec
--- /dev/null
+++ b/includes/js/dojox/string/Builder.js
@@ -0,0 +1,101 @@
+if(!dojo._hasResource["dojox.string.Builder"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.string.Builder"] = true;
+dojo.provide("dojox.string.Builder");
+
+(function(){
+ dojox.string.Builder = function(/*String?*/str){
+ // summary:
+ // A fast buffer for creating large strings
+ // str: The initial string to seed the buffer with
+ this.b = dojo.isIE ? [] : "";
+ if(str){ this.append(str); }
+ };
+
+ var m = {
+ append: function(/*String*/s){
+ // summary: Append all arguments to the end of the buffer
+ return this.appendArray(dojo._toArray(arguments)); // dojox.string.Builder
+ },
+ concat: function(/*String*/s){
+ return this.append(s);
+ },
+ appendArray: function(/*Array*/strings) {
+ this.b = String.prototype.concat.apply(this.b, strings);
+ return this;
+ },
+ clear: function(){
+ // summary: Remove all characters from the buffer
+ this._clear();
+ this.length = 0;
+ return this;
+ },
+ replace: function(oldStr,newStr){
+ // summary: Replace instances of one string with another in the buffer
+ var s = this.toString();
+ s = s.replace(oldStr,newStr);
+ this._reset(s);
+ this.length = s.length;
+ return this;
+ },
+ remove: function(start, len){
+ // summary: Remove len characters starting at index start
+ if(len == 0){ return this; }
+ var s = this.toString();
+ this.clear();
+ if(start > 0){
+ this.append(s.substring(0, start));
+ }
+ if(start+len < s.length){
+ this.append(s.substring(start+len));
+ }
+ return this;
+ },
+ insert: function(index, str){
+ // summary: Insert string str starting at index
+ var s = this.toString();
+ this.clear();
+ if(index == 0){
+ this.append(str);
+ this.append(s);
+ return this;
+ }else{
+ this.append(s.substring(0, index));
+ this.append(str);
+ this.append(s.substring(index));
+ }
+ return this;
+ },
+ toString: function(){
+ return this.b;
+ },
+ _clear: function(){
+ this.b = "";
+ },
+ _reset: function(s){
+ this.b = s;
+ }
+ }; // will hold methods for Builder
+
+ if(dojo.isIE){
+ dojo.mixin(m, {
+ toString: function(){
+ // Summary: Get the buffer as a string
+ return this.b.join("");
+ },
+ appendArray: function(strings){
+ this.b = this.b.concat(strings);
+ return this;
+ },
+ _clear: function(){
+ this.b = [];
+ },
+ _reset: function(s){
+ this.b = [ s ];
+ }
+ });
+ }
+
+ dojo.extend(dojox.string.Builder, m);
+})();
+
+}
diff --git a/includes/js/dojox/string/README b/includes/js/dojox/string/README
new file mode 100644
index 0000000..68b673c
--- /dev/null
+++ b/includes/js/dojox/string/README
@@ -0,0 +1,39 @@
+-------------------------------------------------------------------------------
+DojoX String Utilities
+-------------------------------------------------------------------------------
+Version 0.9
+Release date: 05/08/2007
+-------------------------------------------------------------------------------
+Project state:
+dojox.string.Builder: stable
+dojox.string.sprintf: beta
+dojox.string.tokenize: beta
+-------------------------------------------------------------------------------
+Project authors
+ Ben Lowery
+ Tom Trenka (ttrenka@gmail.com)
+ Neil Roberts
+-------------------------------------------------------------------------------
+Project description
+
+The DojoX String utilties project is a placeholder for miscellaneous string
+utility functions. At the time of writing, only the Builder object has been
+added; but we anticipate other string utilities may end up living here as well.
+-------------------------------------------------------------------------------
+Dependencies:
+
+Dojo Core (package loader).
+-------------------------------------------------------------------------------
+Documentation
+
+See the Dojo Toolkit API docs (http://dojotookit.org/api), dojo.string.Builder.
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/string/*
+
+Install into the following directory structure:
+/dojox/string/
+
+...which should be at the same level as your Dojo checkout.
diff --git a/includes/js/dojox/string/sprintf.js b/includes/js/dojox/string/sprintf.js
new file mode 100644
index 0000000..dbed5b6
--- /dev/null
+++ b/includes/js/dojox/string/sprintf.js
@@ -0,0 +1,406 @@
+if(!dojo._hasResource["dojox.string.sprintf"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.string.sprintf"] = true;
+dojo.provide("dojox.string.sprintf");
+
+dojo.require("dojox.string.tokenize");
+
+dojox.string.sprintf = function(/*String*/ format, /*mixed...*/ filler){
+ for(var args = [], i = 1; i < arguments.length; i++){
+ args.push(arguments[i]);
+ }
+ var formatter = new dojox.string.sprintf.Formatter(format);
+ return formatter.format.apply(formatter, args);
+}
+
+dojox.string.sprintf.Formatter = function(/*String*/ format){
+ var tokens = [];
+ this._mapped = false;
+ this._format = format;
+ this._tokens = dojox.string.tokenize(format, this._re, this._parseDelim, this);
+}
+dojo.extend(dojox.string.sprintf.Formatter, {
+ _re: /\%(?:\(([\w_]+)\)|([1-9]\d*)\$)?([0 +\-\#]*)(\*|\d+)?(\.)?(\*|\d+)?[hlL]?([\%scdeEfFgGiouxX])/g,
+ _parseDelim: function(mapping, intmapping, flags, minWidth, period, precision, specifier){
+ if(mapping){
+ this._mapped = true;
+ }
+ return {
+ mapping: mapping,
+ intmapping: intmapping,
+ flags: flags,
+ _minWidth: minWidth, // May be dependent on parameters
+ period: period,
+ _precision: precision, // May be dependent on parameters
+ specifier: specifier
+ };
+ },
+ _specifiers: {
+ b: {
+ base: 2,
+ isInt: true
+ },
+ o: {
+ base: 8,
+ isInt: true
+ },
+ x: {
+ base: 16,
+ isInt: true
+ },
+ X: {
+ extend: ["x"],
+ toUpper: true
+ },
+ d: {
+ base: 10,
+ isInt: true
+ },
+ i: {
+ extend: ["d"]
+ },
+ u: {
+ extend: ["d"],
+ isUnsigned: true
+ },
+ c: {
+ setArg: function(token){
+ if(!isNaN(token.arg)){
+ var num = parseInt(token.arg);
+ if(num < 0 || num > 127){
+ throw new Error("invalid character code passed to %c in sprintf");
+ }
+ token.arg = isNaN(num) ? "" + num : String.fromCharCode(num);
+ }
+ }
+ },
+ s: {
+ setMaxWidth: function(token){
+ token.maxWidth = (token.period == ".") ? token.precision : -1;
+ }
+ },
+ e: {
+ isDouble: true,
+ doubleNotation: "e"
+ },
+ E: {
+ extend: ["e"],
+ toUpper: true
+ },
+ f: {
+ isDouble: true,
+ doubleNotation: "f"
+ },
+ F: {
+ extend: ["f"]
+ },
+ g: {
+ isDouble: true,
+ doubleNotation: "g"
+ },
+ G: {
+ extend: ["g"],
+ toUpper: true
+ }
+ },
+ format: function(/*mixed...*/ filler){
+ if(this._mapped && typeof filler != "object"){
+ throw new Error("format requires a mapping");
+ }
+
+ var str = "";
+ var position = 0;
+ for(var i = 0, token; i < this._tokens.length; i++){
+ token = this._tokens[i];
+ if(typeof token == "string"){
+ str += token;
+ }else{
+ if(this._mapped){
+ if(typeof filler[token.mapping] == "undefined"){
+ throw new Error("missing key " + token.mapping);
+ }
+ token.arg = filler[token.mapping];
+ }else{
+ if(token.intmapping){
+ var position = parseInt(token.intmapping) - 1;
+ }
+ if(position >= arguments.length){
+ throw new Error("got " + arguments.length + " printf arguments, insufficient for '" + this._format + "'");
+ }
+ token.arg = arguments[position++];
+ }
+
+ if(!token.compiled){
+ token.compiled = true;
+ token.sign = "";
+ token.zeroPad = false;
+ token.rightJustify = false;
+ token.alternative = false;
+
+ var flags = {};
+ for(var fi = token.flags.length; fi--;){
+ var flag = token.flags.charAt(fi);
+ flags[flag] = true;
+ switch(flag){
+ case " ":
+ token.sign = " ";
+ break;
+ case "+":
+ token.sign = "+";
+ break;
+ case "0":
+ token.zeroPad = (flags["-"]) ? false : true;
+ break;
+ case "-":
+ token.rightJustify = true;
+ token.zeroPad = false;
+ break;
+ case "\#":
+ token.alternative = true;
+ break;
+ default:
+ throw Error("bad formatting flag '" + token.flags.charAt(fi) + "'");
+ }
+ }
+
+ token.minWidth = (token._minWidth) ? parseInt(token._minWidth) : 0;
+ token.maxWidth = -1;
+ token.toUpper = false;
+ token.isUnsigned = false;
+ token.isInt = false;
+ token.isDouble = false;
+ token.precision = 1;
+ if(token.period == '.'){
+ if(token._precision){
+ token.precision = parseInt(token._precision);
+ }else{
+ token.precision = 0;
+ }
+ }
+
+ var mixins = this._specifiers[token.specifier];
+ if(typeof mixins == "undefined"){
+ throw new Error("unexpected specifier '" + token.specifier + "'");
+ }
+ if(mixins.extend){
+ dojo.mixin(mixins, this._specifiers[mixins.extend]);
+ delete mixins.extend;
+ }
+ dojo.mixin(token, mixins);
+ }
+
+ if(typeof token.setArg == "function"){
+ token.setArg(token);
+ }
+
+ if(typeof token.setMaxWidth == "function"){
+ token.setMaxWidth(token);
+ }
+
+ if(token._minWidth == "*"){
+ if(this._mapped){
+ throw new Error("* width not supported in mapped formats");
+ }
+ token.minWidth = parseInt(arguments[position++]);
+ if(isNaN(token.minWidth)){
+ throw new Error("the argument for * width at position " + position + " is not a number in " + this._format);
+ }
+ // negative width means rightJustify
+ if (token.minWidth < 0) {
+ token.rightJustify = true;
+ token.minWidth = -token.minWidth;
+ }
+ }
+
+ if(token._precision == "*" && token.period == "."){
+ if(this._mapped){
+ throw new Error("* precision not supported in mapped formats");
+ }
+ token.precision = parseInt(arguments[position++]);
+ if(isNaN(token.precision)){
+ throw Error("the argument for * precision at position " + position + " is not a number in " + this._format);
+ }
+ // negative precision means unspecified
+ if (token.precision < 0) {
+ token.precision = 1;
+ token.period = '';
+ }
+ }
+
+ if(token.isInt){
+ // a specified precision means no zero padding
+ if(token.period == '.'){
+ token.zeroPad = false;
+ }
+ this.formatInt(token);
+ }else if(token.isDouble){
+ if(token.period != '.'){
+ token.precision = 6;
+ }
+ this.formatDouble(token);
+ }
+ this.fitField(token);
+
+ str += "" + token.arg;
+ }
+ }
+
+ return str;
+ },
+ _zeros10: '0000000000',
+ _spaces10: ' ',
+ formatInt: function(token) {
+ var i = parseInt(token.arg);
+ if(!isFinite(i)){ // isNaN(f) || f == Number.POSITIVE_INFINITY || f == Number.NEGATIVE_INFINITY)
+ // allow this only if arg is number
+ if(typeof token.arg != "number"){
+ throw new Error("format argument '" + token.arg + "' not an integer; parseInt returned " + i);
+ }
+ //return '' + i;
+ i = 0;
+ }
+
+ // if not base 10, make negatives be positive
+ // otherwise, (-10).toString(16) is '-a' instead of 'fffffff6'
+ if(i < 0 && (token.isUnsigned || token.base != 10)){
+ i = 0xffffffff + i + 1;
+ }
+
+ if(i < 0){
+ token.arg = (- i).toString(token.base);
+ this.zeroPad(token);
+ token.arg = "-" + token.arg;
+ }else{
+ token.arg = i.toString(token.base);
+ // need to make sure that argument 0 with precision==0 is formatted as ''
+ if(!i && !token.precision){
+ token.arg = "";
+ }else{
+ this.zeroPad(token);
+ }
+ if(token.sign){
+ token.arg = token.sign + token.arg;
+ }
+ }
+ if(token.base == 16){
+ if(token.alternative){
+ token.arg = '0x' + token.arg;
+ }
+ toke.art = token.toUpper ? token.arg.toUpperCase() : token.arg.toLowerCase();
+ }
+ if(token.base == 8){
+ if(token.alternative && token.arg.charAt(0) != '0'){
+ token.arg = '0' + token.arg;
+ }
+ }
+ },
+ formatDouble: function(token) {
+ var f = parseFloat(token.arg);
+ if(!isFinite(f)){ // isNaN(f) || f == Number.POSITIVE_INFINITY || f == Number.NEGATIVE_INFINITY)
+ // allow this only if arg is number
+ if(typeof token.arg != "number"){
+ throw new Error("format argument '" + token.arg + "' not a float; parseFloat returned " + f);
+ }
+ // C99 says that for 'f':
+ // infinity -> '[-]inf' or '[-]infinity' ('[-]INF' or '[-]INFINITY' for 'F')
+ // NaN -> a string starting with 'nan' ('NAN' for 'F')
+ // this is not commonly implemented though.
+ //return '' + f;
+ f = 0;
+ }
+
+ switch(token.doubleNotation) {
+ case 'e': {
+ token.arg = f.toExponential(token.precision);
+ break;
+ }
+ case 'f': {
+ token.arg = f.toFixed(token.precision);
+ break;
+ }
+ case 'g': {
+ // C says use 'e' notation if exponent is < -4 or is >= prec
+ // ECMAScript for toPrecision says use exponential notation if exponent is >= prec,
+ // though step 17 of toPrecision indicates a test for < -6 to force exponential.
+ if(Math.abs(f) < 0.0001){
+ //print("forcing exponential notation for f=" + f);
+ token.arg = f.toExponential(token.precision > 0 ? token.precision - 1 : token.precision);
+ }else{
+ token.arg = f.toPrecision(token.precision);
+ }
+
+ // In C, unlike 'f', 'gG' removes trailing 0s from fractional part, unless alternative format flag ("#").
+ // But ECMAScript formats toPrecision as 0.00100000. So remove trailing 0s.
+ if(!token.alternative){
+ //print("replacing trailing 0 in '" + s + "'");
+ token.arg = token.arg.replace(/(\..*[^0])0*/, "$1");
+ // if fractional part is entirely 0, remove it and decimal point
+ token.arg = token.arg.replace(/\.0*e/, 'e').replace(/\.0$/,'');
+ }
+ break;
+ }
+ default: throw new Error("unexpected double notation '" + token.doubleNotation + "'");
+ }
+
+ // C says that exponent must have at least two digits.
+ // But ECMAScript does not; toExponential results in things like "1.000000e-8" and "1.000000e+8".
+ // Note that s.replace(/e([\+\-])(\d)/, "e$10$2") won't work because of the "$10" instead of "$1".
+ // And replace(re, func) isn't supported on IE50 or Safari1.
+ token.arg = token.arg.replace(/e\+(\d)$/, "e+0$1").replace(/e\-(\d)$/, "e-0$1");
+
+ // Ensure a '0' before the period.
+ // Opera implements (0.001).toString() as '0.001', but (0.001).toFixed(1) is '.001'
+ if(dojo.isOpera){
+ token.arg = token.arg.replace(/^\./, '0.');
+ }
+
+ // if alt, ensure a decimal point
+ if(token.alternative){
+ token.arg = token.arg.replace(/^(\d+)$/,"$1.");
+ token.arg = token.arg.replace(/^(\d+)e/,"$1.e");
+ }
+
+ if(f >= 0 && token.sign){
+ token.arg = token.sign + token.arg;
+ }
+
+ token.arg = token.toUpper ? token.arg.toUpperCase() : token.arg.toLowerCase();
+ },
+ zeroPad: function(token, /*Int*/ length) {
+ length = (arguments.length == 2) ? length : token.precision;
+ if(typeof token.arg != "string"){
+ token.arg = "" + token.arg;
+ }
+
+ var tenless = length - 10;
+ while(token.arg.length < tenless){
+ token.arg = (token.rightJustify) ? token.arg + this._zeros10 : this._zeros10 + token.arg;
+ }
+ var pad = length - token.arg.length;
+ token.arg = (token.rightJustify) ? token.arg + this._zeros10.substring(0, pad) : this._zeros10.substring(0, pad) + token.arg;
+ },
+ fitField: function(token) {
+ if(token.maxWidth >= 0 && token.arg.length > token.maxWidth){
+ return token.arg.substring(0, token.maxWidth);
+ }
+ if(token.zeroPad){
+ this.zeroPad(token, token.minWidth);
+ return;
+ }
+ this.spacePad(token);
+ },
+ spacePad: function(token, /*Int*/ length) {
+ length = (arguments.length == 2) ? length : token.minWidth;
+ if(typeof token.arg != 'string'){
+ token.arg = '' + token.arg;
+ }
+
+ var tenless = length - 10;
+ while(token.arg.length < tenless){
+ token.arg = (token.rightJustify) ? token.arg + this._spaces10 : this._spaces10 + token.arg;
+ }
+ var pad = length - token.arg.length;
+ token.arg = (token.rightJustify) ? token.arg + this._spaces10.substring(0, pad) : this._spaces10.substring(0, pad) + token.arg;
+ }
+});
+
+}
diff --git a/includes/js/dojox/string/tests/Builder.js b/includes/js/dojox/string/tests/Builder.js
new file mode 100644
index 0000000..fc51291
--- /dev/null
+++ b/includes/js/dojox/string/tests/Builder.js
@@ -0,0 +1,91 @@
+if(!dojo._hasResource["dojox.string.tests.Builder"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.string.tests.Builder"] = true;
+dojo.provide("dojox.string.tests.Builder");
+
+dojo.require("dojox.string.Builder");
+
+tests.register("dojox.string.tests.Builder", [
+ {
+ name: "Append",
+ runTest: function(t) {
+ var b = new dojox.string.Builder();
+ b.append("foo");
+ t.is("foo", b.toString());
+ b.append("bar", "baz");
+ t.is("foobarbaz", b.toString());
+ b.append("ben").append("zoo");
+ t.is("foobarbazbenzoo", b.toString());
+ b.append(5);
+ t.is("foobarbazbenzoo5", b.toString());
+ }
+ },
+ {
+ name: "Construction",
+ runTest: function(t){
+ var b = new dojox.string.Builder();
+ t.is("", b.toString());
+ b = new dojox.string.Builder("foo");
+ t.is("foo", b.toString());
+ }
+ },
+ {
+ name: "Replace",
+ runTest: function(t){
+ var b = new dojox.string.Builder("foobar");
+ t.is("foobar", b.toString());
+ b.replace("foo", "baz");
+ t.is("bazbar", b.toString());
+ b.replace("baz", "ben");
+ t.is("benbar", b.toString());
+ b.replace("foo", "moo");
+ t.is("benbar", b.toString());
+ b.replace("enba", "o");
+ t.is("bor", b.toString());
+ b.replace("o", "a").replace("b", "f");
+ t.is("far", b.toString());
+ }
+ },
+ {
+ name: "Insert",
+ runTest: function(t){
+ var b = new dojox.string.Builder();
+ //insert at 0 is prepend
+ b.insert(0, "foo");
+ t.is("foo", b.toString());
+ b.insert(0, "more");
+ t.is("morefoo", b.toString());
+
+ //insert positions stuff after the 4th character
+ b.insert(4, "fun");
+ t.is("morefunfoo", b.toString());
+
+ //insert at len of string is push_back
+ b.insert(10, "awesome");
+ t.is("morefunfooawesome", b.toString());
+
+ //insert past len of string is push_back
+ b.insert(100, "bad");
+ t.is("morefunfooawesomebad", b.toString());
+
+ b = new dojox.string.Builder();
+ b.insert(0, "foo").insert(3, "bar").insert(3, "zoo");
+ t.is("foozoobar", b.toString());
+ }
+ },
+ {
+ name: "Remove",
+ runTest: function(t){
+ var b = new dojox.string.Builder("foobarbaz");
+ b.remove(3,3);
+ t.is("foobaz", b.toString());
+ b.remove(0,3);
+ t.is("baz", b.toString());
+ b.remove(2, 100);
+ t.is("ba", b.toString());
+ b.remove(0,0);
+ t.is("ba", b.toString())
+ }
+ }
+]);
+
+}
diff --git a/includes/js/dojox/string/tests/BuilderPerf.html b/includes/js/dojox/string/tests/BuilderPerf.html
new file mode 100644
index 0000000..4280caa
--- /dev/null
+++ b/includes/js/dojox/string/tests/BuilderPerf.html
@@ -0,0 +1,403 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Builder Perf Tests</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"></script>
+ <script type="text/javascript" src="../Builder.js"></script>
+ <script type="text/javascript" src="lipsum.js"></script>
+ <script type="text/javascript">
+
+ dojo.addOnLoad(function(){
+ dojo.byId("run").disabled="";
+ dojo.connect(dojo.byId("run"),
+ "onclick",
+ function(evt) {
+ setTimeout(function() {
+ var words = parseInt(dojo.byId("numWords").value) || 10;
+ var iters = parseInt(dojo.byId("numIters").value) || 1000;
+ var dict = eval(dojo.byId("dict").value);
+ buildAndRunSet(words, dict, iters);
+ }, 0);
+ });
+ });
+
+ function element(tag, textOrChildOrArray) {
+ var e = document.createElement(tag);
+ function append(n) {
+ if(dojo.isString(n)){
+ n = document.createTextNode(n);
+ }
+ e.appendChild(n);
+ }
+ if(dojo.isArray(textOrChildOrArray)) {
+ dojo.forEach(textOrChildOrArray, append);
+ }else{
+ append(textOrChildOrArray);
+ }
+ return e;
+ }
+
+ function log(t) {
+ dojo.byId("mess").innerHTML = t;
+ console.log(t);
+ }
+
+ function reportRun(results){
+ var runs = results.runs
+ var report = element("dl",
+ element("dt",
+ "Run with " + results.words + " words, " +
+ results.iterations + " iterations, for loop overhead of " +
+ results.overhead + ", average phrase of " +
+ results.wordSize + " characters"));
+
+ runs.sort(function(a,b) { return a.time - b.time; });
+ dojo.forEach(runs, function(r) {
+ report.appendChild(element("dd", r.time + " - " + r.name));
+ });
+
+ dojo.body().appendChild(report);
+ }
+
+ function runTest(test, iterations, expected) {
+ var i;
+ if(expected != test()) throw new Error("Test failed expecting " + expected + ", got " + test());
+ var start = new Date().getTime(), end;
+ for(i=0; i < iterations; i++){
+ test();
+ }
+ end = new Date().getTime();
+ return end-start;
+ }
+
+ function runSet(set, iterations){
+
+ function averagePhraseLen(words) {
+ var sizes = dojo.map(words, function(w) { return w.length; });
+ var total = 0;
+ dojo.forEach(sizes, function(s) { total += s; });
+ return total / sizes.length;
+ }
+
+ var tests = set.tests.concat(); //copy tests
+ var resultSet = {};
+ resultSet.words = set.words.length;
+ resultSet.overhead = runTest(set.overhead, iterations);
+ resultSet.iterations = iterations;
+ resultSet.wordSize = averagePhraseLen(set.words);
+ var runs = [];
+
+ function _run() {
+ var t = tests.pop();
+ try {
+ log("Running " + t.name);
+ if(t) runs.push({ name: t.name, time: runTest(t.test, iterations, set.expected)});
+ } catch(e) {
+ console.error("Error running " + t.name);
+ console.error(e);
+ }
+ if(tests.length > 0) {
+ setTimeout(_run, 0);
+ }
+ else {
+ log("Done!");
+ resultSet.runs = runs;
+ reportRun(resultSet);
+ dojo.publish("perf/run/done");
+ }
+ }
+ setTimeout(_run, 25);
+ }
+
+ function buildTestSet(numWords, dict) {
+ var words = [], i, dl = dict.length;
+ for(i = numWords; i > 0; i-=dl) {
+ if(i >= dl) { words = words.concat(dict); }
+ else { words = words.concat(dict.slice(-i)); }
+ }
+ if(words.length != numWords) throw new Error("wrong number of words, got " + words.length + ", expected " + numWords);
+
+ var expected = words.join("");
+
+ var _builder = new dojox.string.Builder();
+
+ return {
+ tests: [
+ {
+ name: "concatFor",
+ test: function() {
+ var s = "";
+ for(var i = 0; i < words.length; i++) {
+ s = s.concat(words[i]);
+ }
+ return s;
+ }
+ },
+ /*
+ {
+ name: "concatForAlias",
+ test: function() {
+ var s = "", w = words, l = w.length;
+ for(var i = 0; i < l; i++) {
+ s = s.concat(w[i]);
+ }
+ return s;
+ }
+ },
+ {
+ name: "concatForEach",
+ test: function() {
+ var s = "";
+ dojo.forEach(words, function(w) {
+ s = s.concat(w);
+ });
+ return s;
+ }
+ },
+ */
+ {
+ name: "concatOnce",
+ test: function() {
+ var s = "";
+ s = String.prototype.concat.apply(s, words);
+ return s;
+ }
+ },
+ {
+ name: "builderFor",
+ test: function() {
+ var b = new dojox.string.Builder();
+ for(var i = 0; i < words.length; i++) {
+ b.append(words[i]);
+ }
+ return b.toString();
+ }
+ },
+ /*
+ {
+ name: "builderForEach",
+ test: function() {
+ var b = new dojox.string.Builder();
+ dojo.forEach(words, function(w) {
+ b.append(w);
+ });
+ return b.toString();
+ }
+ },
+ */
+ {
+ name: "builderReusedFor",
+ test: function() {
+ _builder.clear();
+ for(var i = 0; i < words.length; i++) {
+ _builder.append(words[i]);
+ }
+ return _builder.toString();
+ }
+ },
+ {
+ name: "builderOnce",
+ test: function() {
+ var b = new dojox.string.Builder();
+ b.appendArray(words);
+ return b.toString();
+ }
+ },
+ {
+ name: "builderReusedOnce",
+ test: function() {
+ _builder.clear();
+ _builder.appendArray(words);
+ return _builder.toString();
+ }
+ },
+ {
+ name: "plusFor",
+ test: function() {
+ var s = "";
+ for(var i = 0; i < words.length; i++) {
+ s += words[i];
+ }
+ return s;
+ }
+ },
+ /*
+ {
+ name: "plusForAlias",
+ test: function() {
+ var s = "", w = words, l = w.length;
+ for(var i = 0; i < l; i++) {
+ s += w[i];
+ }
+ return s;
+ }
+ },
+ {
+ name: "plusForEach",
+ test: function() {
+ var s = "";
+ dojo.forEach(words, function(w) { s += w; });
+ return s;
+ }
+ },*/
+ {
+ name: "joinOnce",
+ test: function() {
+ return words.join("");
+ }
+ },
+ {
+ name: "joinFor",
+ test: function() {
+ var a = [];
+ for(var i = 0; i < words.length; i++) {
+ a.push(words[i]);
+ }
+ return a.join("");
+ }
+ }/*,
+ {
+ name: "joinForAlias",
+ test: function() {
+ var a = [], w = words, l = w.length;
+ for(var i = 0; i <l; i++) {
+ a.push(w[i]);
+ }
+ return a.join("");
+ }
+ },
+ {
+ name: "joinForEach",
+ test: function() {
+ var a = [];
+ dojo.forEach(words, function(w) { a.push(w); });
+ return a.join("");
+ }
+ }
+ */
+ ],
+ words: words,
+ expected: expected,
+ overhead: function() {
+ var w = words;
+ var l = w.length;
+ for(var i=0; i < l; i++) {
+ ident(w[i]);
+ }
+ }
+ };
+ }
+
+ function buildAndRunSet(words, dict, times) {
+ runSet(buildTestSet(words, dict), times);
+ }
+
+ function runSuite() {
+ var suite = [
+ {
+ words: 2,
+ times: 10000
+ },
+ {
+ words: 4,
+ times: 10000
+ },
+ {
+ words: 8,
+ times: 10000
+ },
+ {
+ words: 16,
+ times: 10000
+ },
+ {
+ words: 32,
+ times: 10000
+ },
+ {
+ words: 64,
+ times: 10000
+ },
+ {
+ words: 128,
+ times: 1000
+ },
+ {
+ words: 256,
+ times: 1000
+ },
+ {
+ words: 512,
+ times: 1000
+ },
+ {
+ words: 1024,
+ times: 1000
+ },
+ {
+ words: 2048,
+ times: 1000
+ },
+ {
+ words: 4096,
+ times: 100
+ },
+ {
+ words: 8192,
+ times: 100
+ }
+ ];
+
+ var totalSuite = dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsum; return n; });
+ totalSuite = totalSuite.concat(dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsumLong; return n; }));
+ console.log(totalSuite);
+
+ var handle = dojo.subscribe("perf/run/done", _run);
+ dojo.subscribe("perf/run/done", function(){ console.log("perf run done"); });
+
+ function _run() {
+ var t = totalSuite.shift();
+ if(t) buildAndRunSet(t.words, t.dict, t.times);
+ if(totalSuite.length == 0) dojo.unsubscribe(handle);
+ }
+
+ _run();
+ }
+
+ function ident(i) { return i; }
+ </script>
+ <style type="text/css">
+ html {
+ font-family: Lucida Grande, Tahoma;
+ }
+ div { margin-bottom: 1em; }
+ #results {
+ border: 1px solid #999;
+ border-collapse: collapse;
+ }
+ #results caption {
+ font-size: medium;
+ font-weight: bold;
+ }
+ #results td, #results th {
+ text-align: right;
+ width: 10em;
+ font-size: small;
+ white-space: nowrap;
+ }
+ #wordsCol { background: yellow; }
+ td.max { color: red; font-weight: bold; }
+ td.min { color: green; font-weight: bold; }
+ </style>
+ </head>
+ <body>
+ <table>
+ <tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr>
+ <tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr>
+ <tr><td><label for="dict">Dictionary</label></td><td><input type="text" id="dict" value="lipsum"></td></tr>
+ <tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr>
+ </table>
+ <div id="mess"></div>
+ </body>
+</html>
diff --git a/includes/js/dojox/string/tests/PerfFun.html b/includes/js/dojox/string/tests/PerfFun.html
new file mode 100644
index 0000000..a1dd968
--- /dev/null
+++ b/includes/js/dojox/string/tests/PerfFun.html
@@ -0,0 +1,260 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Perf Tests</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+ <script type="text/javascript" src="lipsum.js"></script>
+ <script type="text/javascript">
+ dojo.addOnLoad(function(){
+ dojo.byId("run").disabled="";
+ dojo.connect(dojo.byId("run"),
+ "onclick",
+ function(evt) {
+ setTimeout(function() {
+ var words = parseInt(dojo.byId("numWords").value) || 10;
+ var iters = parseInt(dojo.byId("numIters").value) || 1000;
+ buildAndRunSet(words, iters);
+ }, 0);
+ });
+ });
+
+ function element(tag, textOrChild) {
+ var e = document.createElement(tag);
+ if(dojo.isArray(textOrChild)) dojo.forEach(textOrChild, function(c) { e.appendChild(c); });
+ if(dojo.isString(textOrChild)) e.appendChild(document.createTextNode(textOrChild));
+ else e.appendChild(textOrChild);
+ return e;
+ }
+
+ function log(t) {
+ dojo.byId("mess").innerHTML = t;
+ }
+
+ function reportRun(results){
+ var runs = results.runs
+ var report = element("dl",
+ element("dt",
+ "Run with " + results.words + " words, " +
+ results.iterations + " iterations and overhead of " +
+ results.overhead));
+
+ runs.sort(function(a,b) { return a.time - b.time; });
+ dojo.forEach(runs, function(r) {
+ report.appendChild(element("dd", r.time + " - " + r.name));
+ });
+
+ dojo.body().appendChild(report);
+ }
+
+ function runTest(test, iterations, expected) {
+ var i;
+ if(expected != test()) throw new Error("Test failed expecting " + expected + ", got " + test());
+ var start = new Date().getTime(), end;
+ for(i=0; i < iterations; i++){
+ test();
+ }
+ end = new Date().getTime();
+ return end-start;
+ }
+
+ function runSet(set, iterations){
+
+ var tests = set.tests.concat(); //copy tests
+ var resultSet = {};
+ resultSet.words = set.words.length;
+ resultSet.overhead = runTest(function(){}, iterations);
+ resultSet.iterations = iterations;
+ var runs = [];
+
+ function _run() {
+ var t = tests.pop();
+ try {
+ log("Running " + t.name);
+ if(t) runs.push({ name: t.name, time: runTest(t.test, iterations, set.expected)});
+ } catch(e) {
+ console.error("Error running " + t.name);
+ console.error(e);
+ }
+ if(tests.length > 0) {
+ setTimeout(_run, 0);
+ }
+ else {
+ log("Done!");
+ resultSet.runs = runs;
+ reportRun(resultSet);
+ }
+ }
+ setTimeout(_run, 0);
+ }
+
+ function buildTestSet(numWords) {
+ var words = [], i, wordsInLipsum = lipsum.length;
+ for(i = numWords; i > 0; i-=wordsInLipsum) {
+ if(i >= wordsInLipsum) { words = words.concat(lipsum); }
+ else { words = words.concat(lipsum.slice(-i)); }
+ }
+ if(words.length != numWords) throw new Error("wrong number of words, got " + words.length + ", expected " + numWords);
+
+ var expected = words.join("");
+
+ //console.log(words);
+
+ return {
+ tests: [
+ {
+ name: "dojoForEach",
+ test: function() {
+ var s = "";
+ dojo.forEach(words, function(w) { s+=w; });
+ return s;
+ }
+ },
+ {
+ name: "nativeForEach",
+ test: function() {
+ var s = "";
+ words.forEach(function(w) { s += w; });
+ return s;
+ }
+ },
+ {
+ name: "forLoop",
+ test: function() {
+ var s="",w=words; l=w.length;
+ for(var i = 0; i < l; i++) {
+ s += w[i];
+ }
+ return s;
+ }
+ },
+ {
+ name: "forLoopCallingInlineFunction",
+ test: function() {
+ var s="",w=words; l=w.length;
+ function fn(w) { s += w; };
+ for(var i = 0; i < l; i++) {
+ fn(w[i]);
+ }
+ return s;
+ }
+ },
+ {
+ name: "forLoopCallingExternalFunction",
+ test: function() {
+ g_s="",w=words; l=w.length;
+ for(var i = 0; i < l; i++) {
+ externalAppend(w[i]);
+ }
+ return g_s;
+ }
+ },
+ {
+ name: "forLoopWithInCheck",
+ test: function() {
+ var s="",w=words; l=w.length;
+ for(var i = 0; i < l; i++) {
+ if(i in w) s += w[i];
+ }
+ return s;
+ }
+ },
+ {
+ name: "emptyFor",
+ test: function() {
+ var w = words; l = w.length;
+ for(var i = 0; i < l; i++) empty(w[i]);
+ return expected;
+ }
+ },
+ {
+ name: "emptyForEach",
+ test: function() {
+ dojo.forEach(words, empty);
+ return expected;
+ }
+ } ,
+ {
+ name: "identFor",
+ test: function() {
+ var w = words; l = w.length;
+ for(var i = 0; i < l; i++) ident(w[i]);
+ return expected;
+ }
+ },
+ {
+ name: "identForEach",
+ test: function() {
+ dojo.forEach(words, ident);
+ return expected;
+ }
+ },
+ {
+ name: "addUsingFor",
+ test: function() {
+ var x=0;
+ for(var i=0;i<1000;i++){x=x+a[i];}
+ return expected; // fake
+ }
+ },
+ {
+ name: "addUsingForEach",
+ test: function() {
+ var x=0;
+ dojo.forEach(a, function(v,i){x=x+a[i];});
+ return expected; // fake
+ }
+ }
+ ],
+ words: words,
+ expected: expected
+ };
+ }
+
+ function buildAndRunSet(words, times) {
+ runSet(buildTestSet(words), times);
+ }
+
+ function ident(w) { return w; }
+ function empty() { }
+
+ var g_s = "";
+ function externalAppend(w){ g_s += w; }
+
+ var a = new Array(1000);
+ for(var i=0; i<1000;i++){a[i]=i;}
+
+ </script>
+ <style type="text/css">
+ html {
+ font-family: Lucida Grande, Tahoma;
+ }
+ div { margin-bottom: 1em; }
+ #results {
+ border: 1px solid #999;
+ border-collapse: collapse;
+ }
+ #results caption {
+ font-size: medium;
+ font-weight: bold;
+ }
+ #results td, #results th {
+ text-align: right;
+ width: 10em;
+ font-size: small;
+ white-space: nowrap;
+ }
+ #wordsCol { background: yellow; }
+ td.max { color: red; font-weight: bold; }
+ td.min { color: green; font-weight: bold; }
+ </style>
+ </head>
+ <body>
+ <table>
+ <tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr>
+ <tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr>
+ <tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr>
+ </table>
+ <div id="mess"></div>
+ </body>
+</html>
diff --git a/includes/js/dojox/string/tests/lipsum.js b/includes/js/dojox/string/tests/lipsum.js
new file mode 100644
index 0000000..ea62a25
--- /dev/null
+++ b/includes/js/dojox/string/tests/lipsum.js
@@ -0,0 +1,133 @@
+var lipsum = ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetuer",
+"adipiscing", "elit.", "Suspendisse", "nisi.", "Pellentesque", "facilisis",
+"pretium", "nulla.", "Sed", "semper", "accumsan", "quam.", "Donec",
+"vulputate", "auctor", "neque.", "Aenean", "arcu", "pede,", "consequat",
+"eget,", "molestie", "sed,", "bibendum", "quis,", "ante.", "Praesent", "sit",
+"amet", "odio", "ut", "ipsum", "suscipit", "faucibus.", "Vestibulum",
+"accumsan,", "nunc", "non", "adipiscing", "hendrerit,", "lorem", "arcu",
+"dignissim", "mi,", "vel", "blandit", "urna", "velit", "dictum", "leo.",
+"Aliquam", "ornare", "massa", "quis", "lacus.", "Cum", "sociis", "natoque",
+"penatibus", "et", "magnis", "dis", "parturient", "montes,", "nascetur",
+"ridiculus", "mus.", "Vivamus", "sit", "amet", "ligula.", "Pellentesque",
+"vitae", "nunc", "sed", "mauris", "consequat", "condimentum.Lorem", "ipsum",
+"dolor", "sit", "amet,", "consectetuer", "adipiscing", "elit.", "Donec", "in",
+"lectus", "eu", "magna", "consectetuer", "pellentesque.", "Donec", "ante.",
+"Integer", "ut", "turpis.", "Sed", "tincidunt", "consectetuer", "purus.",
+"Cras", "lacus.", "Nunc", "et", "lacus.", "Ut", "aliquet", "urna", "ut",
+"urna.", "Etiam", "vel", "urna.", "Nunc", "id", "diam.", "Fusce", "at",
+"purus", "id", "velit", "molestie", "pretium.Aenean", "vel", "sapien", "et",
+"justo", "ornare", "cursus.", "Donec", "facilisis.", "Vestibulum", "feugiat",
+"magna", "in", "nulla.", "Curabitur", "orci.", "Vestibulum", "molestie",
+"aliquet", "est.", "Sed", "eget", "erat", "non", "sem", "laoreet",
+"pellentesque.", "Cras", "at", "odio", "nec", "leo", "egestas", "blandit.",
+"Nullam", "at", "dui.", "Duis", "felis", "lacus,", "blandit", "non,",
+"consequat", "ut,", "fringilla", "at,", "est.", "Etiam", "blandit", "porta",
+"tellus.", "Etiam", "purus", "turpis,", "molestie", "ut,", "tristique",
+"eget,", "elementum", "sit", "amet,", "orci.", "Pellentesque", "condimentum",
+"ultrices", "neque.", "Duis", "dignissim.", "Curabitur", "condimentum",
+"arcu", "id", "sapien.Nunc", "diam", "eros,", "pellentesque", "non,",
+"lobortis", "et,", "venenatis", "eu,", "felis.", "Vestibulum", "vel", "dolor",
+"quis", "nunc", "semper", "consectetuer.", "Nullam", "mollis.", "Aenean",
+"molestie", "cursus", "mi.", "Mauris", "ante.", "In", "hac", "habitasse",
+"platea", "dictumst.", "Nunc", "sem", "dui,", "fermentum", "ac,", "luctus",
+"a,", "imperdiet", "in,", "neque.", "Cras", "mattis", "pretium", "metus.",
+"Praesent", "ligula", "mi,", "imperdiet", "eu,", "rutrum", "volutpat,",
+"blandit", "id,", "lectus.", "Duis", "sed", "mauris", "id", "lacus",
+"lacinia", "rhoncus.", "Vivamus", "ultricies", "sem", "a", "nisi",
+"fermentum", "pretium.", "Cras", "sagittis", "tempus", "velit.", "Mauris",
+"eget", "quam.", "Sed", "facilisis", "tincidunt", "tellus.", "Vestibulum",
+"rhoncus", "venenatis", "felis.", "Aliquam", "erat", "volutpat.Proin", "et",
+"orci", "at", "libero", "faucibus", "iaculis.", "Nam", "id", "purus.", "Ut",
+"aliquet,", "turpis", "id", "volutpat", "gravida,", "felis", "urna",
+"viverra", "justo,", "id", "semper", "nulla", "ligula", "id", "libero.",
+"Sed", "fringilla.", "Fusce", "vel", "lorem", "ut", "tortor", "porta",
+"tincidunt.", "Nunc", "arcu.", "Class", "aptent", "taciti", "sociosqu", "ad",
+"litora", "torquent", "per", "coubia", "ostra,", "per", "iceptos",
+"hymeaeos.", "Doec", "ullamcorper", "ate", "vel", "felis.", "Mauris", "quis",
+"dolor.", "Vestibulum", "ulla", "felis,", "laoreet", "ut,", "placerat", "at,",
+"malesuada", "et,", "lacus.", "Suspedisse", "eget", "mi", "id", "dui",
+"porttitor", "porttitor.", "Quisque", "elemetum.", "Sed", "tortor.", "Etiam",
+"malesuada.", "Cum", "sociis", "atoque", "peatibus", "et", "magis", "dis",
+"parturiet", "motes,", "ascetur", "ridiculus", "mus.Suspedisse", "euismod",
+"sagittis", "eros.", "uc", "sollicitudi.", "Doec", "ac", "turpis.", "Mauris",
+"feugiat", "isl", "vel", "ate.", "am", "isi.", "Etiam", "auctor", "elemetum",
+"diam.", "uc", "ut", "elit", "auctor", "ibh", "orare", "viverra.", "Iteger",
+"vulputate.", "Duis", "dictum", "justo", "sagittis", "tortor.", "Suspedisse",
+"placerat.", "am", "faucibus", "eros", "eget", "odio.", "Proi", "et",
+"lectus.", "uc", "massa", "ligula,", "vulputate", "eu,", "mattis", "ac,",
+"euismod", "ec,", "isl.", "ullam", "sit", "amet", "turpis", "eu", "ura",
+"elemetum", "auctor.", "Pelletesque", "lobortis", "orare", "justo.",
+"Suspedisse", "metus", "felis,", "iterdum", "ac,", "placerat", "at,",
+"frigilla", "mollis,", "erat.", "ullam", "sed", "odio", "eu", "mi", "egestas",
+"scelerisque.", "Pelletesque", "habitat", "morbi", "tristique", "seectus",
+"et", "etus", "et", "malesuada", "fames", "ac", "turpis", "egestas.", "Cras",
+"purus", "leo,", "aliquam", "eget,", "accumsa", "volutpat,", "eleifed",
+"vel,", "eros.", "I", "ultricies", "mattis", "turpis.Curabitur", "volutpat",
+"aliquam", "lorem.", "Sed", "at", "risus.", "Quisque", "tristique.",
+"Suspedisse", "mollis.", "I", "tellus", "quam,", "viverra", "eget,", "mollis",
+"vitae,", "bibedum", "sit", "amet,", "eim.", "Pelletesque", "frigilla",
+"tortor", "ac", "orci.", "Phasellus", "commodo", "porttitor", "elit.",
+"Maeceas", "ate", "orci,", "vehicula", "ticidut,", "lobortis", "eu,",
+"vehicula", "id,", "lorem.", "Quisque", "sapie", "ura,", "iaculis",
+"laoreet,", "digissim", "ac,", "adipiscig", "vitae,", "elit.", "ulla",
+"fermetum,", "leo", "ec", "posuere", "tempor,", "isi", "diam", "cursus",
+"arcu,", "at", "egestas", "ibh", "maga", "i", "odio.", "Mauris", "o", "diam",
+"sed", "dolor", "ultricies", "egestas.", "Aliquam", "erat", "volutpat.",
+"Quisque", "rhocus.", "ulla", "vitae", "arcu", "o", "pede", "scelerisque",
+"luctus.", "Pelletesque", "pretium", "massa.", "Fusce", "i", "leo", "eget",
+"eros", "fermetum", "ticidut.", "ulla", "velit", "risus,", "malesuada",
+"sed,", "auctor", "faucibus,", "porta", "sed,", "lacus.", "Aeea", "at",
+"eque.Doec", "o", "maga.", "Suspedisse", "cosequat", "orci", "sit", "amet",
+"velit.", "Ut", "est.", "Iteger", "sollicitudi,", "libero", "vitae",
+"gravida", "imperdiet,", "sem", "lorem", "tristique", "odio,", "sed",
+"pulviar", "tortor", "arcu", "vel", "mi.", "Aliquam", "erat", "volutpat.",
+"Vivamus", "tellus.", "Cras", "semper.", "Cras", "dictum", "dictum", "eros.",
+"Praeset", "et", "ulla", "i", "ulla", "ultricies", "auctor.", "Aeea",
+"tortor", "odio,", "ticidut", "sit", "amet,", "vestibulum", "id,", "covallis",
+"vel,", "pede.", "Vivamus", "volutpat", "elit", "i", "orci.", "Praeset",
+"arcu", "justo,", "adipiscig", "ac,", "commodo", "quis,", "scelerisque",
+"ac,", "libero.", "I", "odio", "ate,", "rutrum", "eu,", "aliquam", "vitae,",
+"ullamcorper", "et,", "sapie.", "Ut", "augue", "purus,", "pelletesque", "ut,",
+"auctor", "sit", "amet,", "laoreet", "eget,", "lectus.", "Vestibulum", "ate",
+"ipsum", "primis", "i", "faucibus", "orci", "luctus", "et", "ultrices",
+"posuere", "cubilia", "Curae;", "I", "orare,", "dui", "ac", "cosequat",
+"posuere,", "justo", "odio", "fermetum", "sem,", "eget", "covallis", "lacus",
+"quam", "o", "dui.", "Etiam", "mattis", "lacus", "cosectetuer", "pede",
+"veeatis", "eleifed.", "Cras", "quis", "tortor.uc", "libero", "erat,",
+"ultricies", "eget,", "ticidut", "sed,", "placerat", "eu,", "sapie.", "Cras",
+"posuere,", "pede", "ec", "dictum", "egestas,", "tortor", "orci", "faucibus",
+"lorem,", "eget", "iterdum", "mauris", "velit", "dapibus", "velit.", "ulla",
+"digissim", "imperdiet", "sapie.", "Ut", "tempus", "tellus.", "Pelletesque",
+"adipiscig", "varius", "tortor.", "Doec", "ligula", "dolor,", "pulviar",
+"ut,", "rutrum", "ac,", "dictum", "eget,", "diam.", "Sed", "at", "justo.",
+"Etiam", "orare", "scelerisque", "erat.", "am", "arcu.", "Iteger", "i",
+"orci.", "Fusce", "cosectetuer,", "isi", "o", "iterdum", "bladit,", "velit",
+"turpis", "codimetum", "tellus,", "i", "ullamcorper", "turpis", "leo", "at",
+"tellus.", "Doec", "velit.", "Phasellus", "augue.", "Doec", "et", "dui",
+"quis", "tortor", "fermetum", "eleifed.", "ulla", "facilisi.", "am",
+"veeatis", "suscipit", "ate.", "Aeea", "volutpat.", "Pelletesque",
+"ultricies", "accumsa", "orci.", "Pelletesque", "tellus", "diam,", "frigilla",
+"eu,", "cursus", "at,", "porta", "eget,", "justo.am", "dui.", "Suspedisse",
+"poteti.", "Vestibulum", "porttitor,", "purus", "a", "ullamcorper",
+"placerat,", "justo", "libero", "digissim", "augue,", "quis", "pelletesque",
+"ura", "tortor", "a", "orci.", "Duis", "eim.", "Aeea", "auctor,", "augue",
+"sed", "facilisis", "vulputate,", "ipsum", "lacus", "vestibulum", "metus,",
+"eu", "egestas", "felis", "diam", "a", "mauris.", "ulla", "imperdiet", "elit",
+"vel", "lectus.", "Ut", "ac", "ibh", "vel", "pede", "gravida", "hedrerit.",
+"Sed", "pelletesque,", "odio", "et", "eleifed", "cosequat,", "ulla", "ligula",
+"pretium", "ura,", "vel", "ultricies", "eros", "orci", "ut", "pede.", "Doec",
+"cosequat", "orare", "maga.", "Pelletesque", "ulla", "eim,", "bladit",
+"eget,", "sollicitudi", "ticidut,", "posuere", "vel,", "dolor.", "Phasellus",
+"facilisis", "arcu", "ut", "isi.", "Vivamus", "varius.", "Curabitur",
+"hedrerit,", "ligula", "sit", "amet", "molestie", "facilisis,", "ligula",
+"libero", "ultricies", "ulla,", "at", "bibedum", "libero", "dolor", "ticidut",
+"ibh.", "Doec", "pede", "tellus,", "pharetra", "pelletesque,", "euismod",
+"eget,", "placerat", "ut,", "dolor.Aeea", "mauris.", "Pelletesque", "sed",
+"ligula.", "Quisque", "faucibus", "tristique", "eque.", "Maeceas", "tempus",
+"auctor", "uc.", "Etiam", "et", "justo.", "Praeset", "ultrices", "odio", "id",
+"arcu", "aliquam", "pretium.", "Sed", "pulviar", "purus", "eu", "lorem.",
+"Suspedisse", "poteti.", "Aeea", "lacus.", "Vestibulum", "sit", "amet", "isi",
+"sed", "justo", "bibedum", "ticidut.", "Aliquam", "semper", "vestibulum",
+"quam.", "Sed."];
+
+var lipsumLong = ["sed justo bibedum ticidut. Aliquam semper vestibulum quam. Sed. Lorem ipsum dolor sit amet, consecte...", "facilisis pretium nulla. Sed semper accumsan quam. Donec vulputate auctor", "neque. Aenean arcu pede, consequat eget, molestie sed, bibendum quis,", "ante. Praesent sit amet odio ut ipsum suscipit faucibus. Vestibulum", "accumsan, nunc non adipiscing hendrerit, lorem arcu dignissim mi, vel", "blandit urna velit dictum leo. Aliquam ornare massa quis lacus.", "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur", "ridiculus mus. Vivamus sit amet ligula. Pellentesque vitae nunc sed", "mauris consequat condimentum.Lorem ipsum dolor sit amet, consectetuer adipiscing elit.", "Donec in lectus eu magna consectetuer pellentesque. Donec ante. Integer", "ut turpis. Sed tincidunt consectetuer purus. Cras lacus. Nunc et", "lacus. Ut aliquet urna ut urna. Etiam vel urna. Nunc", "id diam. Fusce at purus id velit molestie pretium.Aenean vel", "sapien et justo ornare cursus. Donec facilisis. Vestibulum feugiat magna", "in nulla. Curabitur orci. Vestibulum molestie aliquet est. Sed eget", "erat non sem laoreet pellentesque. Cras at odio nec leo", "egestas blandit. Nullam at dui. Duis felis lacus, blandit non,", "consequat ut, fringilla at, est. Etiam blandit porta tellus. Etiam", "purus turpis, molestie ut, tristique eget, elementum sit amet, orci.", "Pellentesque condimentum ultrices neque. Duis dignissim. Curabitur condimentum arcu id", "sapien.Nunc diam eros, pellentesque non, lobortis et, venenatis eu, felis.", "Vestibulum vel dolor quis nunc semper consectetuer. Nullam mollis. Aenean", "molestie cursus mi. Mauris ante. In hac habitasse platea dictumst.", "Nunc sem dui, fermentum ac, luctus a, imperdiet in, neque.", "Cras mattis pretium metus. Praesent ligula mi, imperdiet eu, rutrum", "volutpat, blandit id, lectus. Duis sed mauris id lacus lacinia", "rhoncus. Vivamus ultricies sem a nisi fermentum pretium. Cras sagittis", "tempus velit. Mauris eget quam. Sed facilisis tincidunt tellus. Vestibulum", "rhoncus venenatis felis. Aliquam erat volutpat.Proin et orci at libero", "faucibus iaculis. Nam id purus. Ut aliquet, turpis id volutpat", "gravida, felis urna viverra justo, id semper nulla ligula id", "libero. Sed fringilla. Fusce vel lorem ut tortor porta tincidunt.", "Nunc arcu. Class aptent taciti sociosqu ad litora torquent per", "coubia ostra, per iceptos hymeaeos. Doec ullamcorper ate vel felis.", "Mauris quis dolor. Vestibulum ulla felis, laoreet ut, placerat at,", "malesuada et, lacus. Suspedisse eget mi id dui porttitor porttitor.", "Quisque elemetum. Sed tortor. Etiam malesuada. Cum sociis atoque peatibus", "et magis dis parturiet motes, ascetur ridiculus mus.Suspedisse euismod sagittis", "eros. uc sollicitudi. Doec ac turpis. Mauris feugiat isl vel", "ate. am isi. Etiam auctor elemetum diam. uc ut elit", "auctor ibh orare viverra. Iteger vulputate. Duis dictum justo sagittis", "tortor. Suspedisse placerat. am faucibus eros eget odio. Proi et", "lectus. uc massa ligula, vulputate eu, mattis ac, euismod ec,", "isl. ullam sit amet turpis eu ura elemetum auctor. Pelletesque", "lobortis orare justo. Suspedisse metus felis, iterdum ac, placerat at,", "frigilla mollis, erat. ullam sed odio eu mi egestas scelerisque.", "Pelletesque habitat morbi tristique seectus et etus et malesuada fames", "ac turpis egestas. Cras purus leo, aliquam eget, accumsa volutpat,", "eleifed vel, eros. I ultricies mattis turpis.Curabitur volutpat aliquam lorem.", "Sed at risus. Quisque tristique. Suspedisse mollis. I tellus quam,", "viverra eget, mollis vitae, bibedum sit amet, eim. Pelletesque frigilla", "tortor ac orci. Phasellus commodo porttitor elit. Maeceas ate orci,", "vehicula ticidut, lobortis eu, vehicula id, lorem. Quisque sapie ura,", "iaculis laoreet, digissim ac, adipiscig vitae, elit. ulla fermetum, leo", "ec posuere tempor, isi diam cursus arcu, at egestas ibh", "maga i odio. Mauris o diam sed dolor ultricies egestas.", "Aliquam erat volutpat. Quisque rhocus. ulla vitae arcu o pede", "scelerisque luctus. Pelletesque pretium massa. Fusce i leo eget eros", "fermetum ticidut. ulla velit risus, malesuada sed, auctor faucibus, porta", "sed, lacus. Aeea at eque.Doec o maga. Suspedisse cosequat orci", "sit amet velit. Ut est. Iteger sollicitudi, libero vitae gravida", "imperdiet, sem lorem tristique odio, sed pulviar tortor arcu vel", "mi. Aliquam erat volutpat. Vivamus tellus. Cras semper. Cras dictum", "dictum eros. Praeset et ulla i ulla ultricies auctor. Aeea", "tortor odio, ticidut sit amet, vestibulum id, covallis vel, pede.", "Vivamus volutpat elit i orci. Praeset arcu justo, adipiscig ac,", "commodo quis, scelerisque ac, libero. I odio ate, rutrum eu,", "aliquam vitae, ullamcorper et, sapie. Ut augue purus, pelletesque ut,", "auctor sit amet, laoreet eget, lectus. Vestibulum ate ipsum primis", "i faucibus orci luctus et ultrices posuere cubilia Curae; I", "orare, dui ac cosequat posuere, justo odio fermetum sem, eget", "covallis lacus quam o dui. Etiam mattis lacus cosectetuer pede", "veeatis eleifed. Cras quis tortor.uc libero erat, ultricies eget, ticidut", "sed, placerat eu, sapie. Cras posuere, pede ec dictum egestas,", "tortor orci faucibus lorem, eget iterdum mauris velit dapibus velit.", "ulla digissim imperdiet sapie. Ut tempus tellus. Pelletesque adipiscig varius", "tortor. Doec ligula dolor, pulviar ut, rutrum ac, dictum eget,", "diam. Sed at justo. Etiam orare scelerisque erat. am arcu.", "Iteger i orci. Fusce cosectetuer, isi o iterdum bladit, velit", "turpis codimetum tellus, i ullamcorper turpis leo at tellus. Doec", "velit. Phasellus augue. Doec et dui quis tortor fermetum eleifed.", "ulla facilisi. am veeatis suscipit ate. Aeea volutpat. Pelletesque ultricies", "accumsa orci. Pelletesque tellus diam, frigilla eu, cursus at, porta", "eget, justo.am dui. Suspedisse poteti. Vestibulum porttitor, purus a ullamcorper", "placerat, justo libero digissim augue, quis pelletesque ura tortor a", "orci. Duis eim. Aeea auctor, augue sed facilisis vulputate, ipsum", "lacus vestibulum metus, eu egestas felis diam a mauris. ulla", "imperdiet elit vel lectus. Ut ac ibh vel pede gravida", "hedrerit. Sed pelletesque, odio et eleifed cosequat, ulla ligula pretium", "ura, vel ultricies eros orci ut pede. Doec cosequat orare", "maga. Pelletesque ulla eim, bladit eget, sollicitudi ticidut, posuere vel,", "dolor. Phasellus facilisis arcu ut isi. Vivamus varius. Curabitur hedrerit,", "ligula sit amet molestie facilisis, ligula libero ultricies ulla, at", "bibedum libero dolor ticidut ibh. Doec pede tellus, pharetra pelletesque,", "euismod eget, placerat ut, dolor.Aeea mauris. Pelletesque sed ligula. Quisque", "faucibus tristique eque. Maeceas tempus auctor uc. Etiam et justo.", "Praeset ultrices odio id arcu aliquam pretium. Sed pulviar purus", "eu lorem. Suspedisse poteti. Aeea lacus. Vestibulum sit amet isi"];
diff --git a/includes/js/dojox/string/tests/notes.txt b/includes/js/dojox/string/tests/notes.txt
new file mode 100644
index 0000000..71d7887
--- /dev/null
+++ b/includes/js/dojox/string/tests/notes.txt
@@ -0,0 +1,153 @@
+notes:
+reference:
+Run with 100 words, 1000 iterations and overhead of 2
+ 62 - concatOnce
+ 73 - joinExisting
+ 241 - plusForAlias
+ 261 - plusFor
+ 360 - concatFor
+ 391 - joinForAlias
+ 398 - concatForAlias
+ 408 - joinFor
+ 636 - plusForEach
+ 763 - concatForEach
+ 851 - joinForEach
+ 4188 - builderReusedFor
+ 4319 - builderFor
+ 5155 - builderForEach
+
+switch to for loop in append and ditch arraylike for array(r9607)
+Run with 100 words, 1000 iterations and overhead of 3
+ 62 - concatOnce
+ 72 - joinExisting
+ 235 - concatForAlias
+ 242 - plusForAlias
+ 263 - plusFor
+ 361 - concatFor
+ 394 - joinForAlias
+ 414 - joinFor
+ 635 - plusForEach
+ 757 - concatForEach
+ 855 - joinForEach
+ 2005 - builderReusedFor
+ 2073 - builderFor
+ 2830 - builderForEach
+
+
+inline append for array, remove string check
+Run with 100 words, 1000 iterations and overhead of 4
+ 55 - concatOnce
+ 75 - joinExisting
+ 243 - plusForAlias
+ 263 - plusFor
+ 363 - concatFor
+ 382 - concatForAlias
+ 398 - joinForAlias
+ 410 - joinFor
+ 629 - plusForEach
+ 754 - concatForEach
+ 857 - joinForEach
+ 1854 - builderReusedFor
+ 1922 - builderFor
+ 2714 - builderForEach
+
+add string check back in using typeof
+Run with 100 words, 1000 iterations and overhead of 3
+ 63 - concatOnce
+ 72 - joinExisting
+ 242 - plusForAlias
+ 262 - plusFor
+ 363 - concatFor
+ 381 - concatForAlias
+ 394 - joinForAlias
+ 410 - joinFor
+ 633 - plusForEach
+ 773 - concatForEach
+ 862 - joinForEach
+ 1870 - builderReusedFor
+ 1937 - builderFor
+ 2702 - builderForEach
+
+first cut less complex isArray
+Run with 100 words, 1000 iterations and overhead of 3
+ 63 - concatOnce
+ 73 - joinExisting
+ 184 - plusFor
+ 251 - plusForAlias
+ 282 - concatFor
+ 381 - concatForAlias
+ 395 - joinForAlias
+ 412 - joinFor
+ 629 - plusForEach
+ 770 - concatForEach
+ 851 - joinForEach
+ 2027 - builderReusedFor
+ 2129 - builderFor
+ 2898 - builderForEach
+
+switch to typeof for array, put string check back in using typeof (r9610)
+Run with 100 words, 1000 iterations and overhead of 2
+ 63 - concatOnce
+ 77 - joinExisting
+ 251 - plusForAlias
+ 272 - plusFor
+ 282 - concatFor
+ 364 - concatForAlias
+ 404 - joinForAlias
+ 415 - joinFor
+ 630 - plusForEach
+ 766 - concatForEach
+ 850 - joinForEach
+ 1274 - builderReusedFor
+ 1510 - builderFor
+ 2108 - builderForEach
+
+remove arguments-style array support. only support an explicit array.
+Run with 100 words, 1000 iterations and overhead of 2
+ 63 - concatOnce
+ 75 - joinExisting
+ 186 - plusFor
+ 207 - builderReusedOnce
+ 255 - plusForAlias
+ 283 - concatFor
+ 306 - builderOnce
+ 367 - concatForAlias
+ 408 - joinForAlias
+ 419 - joinFor
+ 639 - plusForEach
+ 767 - concatForEach
+ 817 - builderReusedFor
+ 865 - joinForEach
+ 975 - builderFor
+ 1562 - builderForEach
+
+just running for tests
+Run with 100 words, 1000 iterations and overhead of 3
+ 63 - concatOnce
+ 203 - plusFor
+ 204 - builderReusedOnce
+ 303 - builderOnce
+ 330 - joinFor
+ 385 - concatFor
+ 748 - builderFor
+ 748 - builderReusedFor
+
+remove array support in append
+Run with 1000 words, 1000 iterations and overhead of 2
+ 382 - concatOnce
+ 1951 - plusFor
+ 2779 - builderFor
+ 2883 - builderReusedFor
+ 3038 - concatFor
+ 3549 - joinFor
+
+add in appendArray support to match once, use += for append
+Run with 1000 words, 1000 iterations and overhead of 3
+ 379 - concatOnce
+ 381 - builderReusedOnce
+ 393 - builderOnce
+ 2022 - plusFor
+ 2862 - builderFor
+ 2973 - builderReusedFor
+ 3128 - concatFor
+ 3548 - joinFor \ No newline at end of file
diff --git a/includes/js/dojox/string/tests/peller.html b/includes/js/dojox/string/tests/peller.html
new file mode 100644
index 0000000..d526548
--- /dev/null
+++ b/includes/js/dojox/string/tests/peller.html
@@ -0,0 +1,78 @@
+<html>
+<head>
+ <title>peller's test</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"></script>
+ <script type="text/javascript">
+
+ var lq = [];
+ function log(s) {
+ lq.push(s);
+ //console.log(s);
+ }
+
+ function dumpLog() {
+ dojo.forEach(lq, function(l) { console.log(l); });
+ lq = [];
+ }
+
+ dojo.addOnLoad(function() {
+ forLoop();
+ forEachLoop();
+ forAgain();
+ forEachAgain();
+ dumpLog();
+ });
+
+ function forLoop() {
+ var x=0;
+ var a = g_a;
+ var start=new Date();
+ for(var i=0;i<100000;i++){x=x+a[i];};
+ log("for loop elapsed:"+(new Date()-start)+" value="+x);
+ }
+
+ function forEachLoop() {
+ var x=0;
+ var a = g_a;
+ var start=new Date();
+ dojo.forEach(a, function(v,i){x=x+a[i];});
+ log("dojo.forEach elapsed:"+(new Date()-start)+" value="+x);
+ }
+
+ function forAgain(){
+ log("for results:");
+ var start=new Date();
+ var x=0;
+ for(var i=0;i<100000;i++){x=x+g_a[i];}
+ log("elapsed:"+(new Date()-start)+" value="+x);
+ }
+ function forEachAgain(){
+ log("forEach results:");
+ var a = g_a;
+ var x=0;
+ var start=new Date();
+ a.forEach(function(v,i){x=x+a[i];});
+ log("elapsed:"+(new Date()-start)+" value="+x);
+ }
+
+ var g_a = new Array(100000);
+ for(var i=0; i<100000;i++){g_a[i]=i;}
+
+ var start, x, i;
+ log("inline for results:");
+ start=new Date();
+ x=0;
+ for(i=0;i<100000;i++){x=x+g_a[i];}
+ log("elapsed:"+(new Date()-start)+" value="+x);
+
+ log("inline forEach results:");
+ start=new Date();
+ x=0;
+ g_a.forEach(function(v,i){x=x+g_a[i];});
+ log("elapsed:"+(new Date()-start)+" value="+x);
+ dumpLog();
+ </script>
+</head>
+<body>
+</body>
+</html> \ No newline at end of file
diff --git a/includes/js/dojox/string/tests/runTests.html b/includes/js/dojox/string/tests/runTests.html
new file mode 100644
index 0000000..b3ea76d
--- /dev/null
+++ b/includes/js/dojox/string/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <title>Dojox Unit Test Runner</title>
+ <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.string.tests.string"></HEAD>
+ <BODY>
+ Redirecting to D.O.H runner.
+ </BODY>
+</HTML>
diff --git a/includes/js/dojox/string/tests/sprintf.js b/includes/js/dojox/string/tests/sprintf.js
new file mode 100644
index 0000000..d9e2f15
--- /dev/null
+++ b/includes/js/dojox/string/tests/sprintf.js
@@ -0,0 +1,277 @@
+if(!dojo._hasResource["dojox.string.tests.sprintf"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.string.tests.sprintf"] = true;
+dojo.provide("dojox.string.tests.sprintf");
+
+dojo.require("dojox.string.sprintf");
+dojo.require("dojo.string");
+
+
+// Mapping using the %(var) format
+
+// Flags:
+// (space): Preceeds a positive number with a blank space
+// +: Preceeds a positive number with a + sign
+// 0: Pads numbers using zeroes
+// -: Left justify a number (they're right justified by default)
+// #: Alternate view for the specifier
+
+tests.register("dojox.string.tests.sprintf", [
+ {
+ name: "Flag: (space)",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ t.is(" 42", sprintf("% d", 42));
+ t.is("-42", sprintf("% d", -42));
+ t.is(" 42", sprintf("% 5d", 42));
+ t.is(" -42", sprintf("% 5d", -42));
+ t.is(" 42", sprintf("% 15d", 42));
+ t.is(" -42", sprintf("% 15d", -42));
+ }
+ },
+ {
+ name: "Flag: +",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ t.is("+42", sprintf("%+d", 42));
+ t.is("-42", sprintf("%+d", -42));
+ t.is(" +42", sprintf("%+5d", 42));
+ t.is(" -42", sprintf("%+5d", -42));
+ t.is(" +42", sprintf("%+15d", 42));
+ t.is(" -42", sprintf("%+15d", -42));
+ }
+ },
+ {
+ name: "Flag: 0",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ t.is("42", sprintf("%0d", 42));
+ t.is("-42", sprintf("%0d", -42));
+ t.is("00042", sprintf("%05d", 42));
+ t.is("00-42", sprintf("%05d", -42));
+ t.is("000000000000042", sprintf("%015d", 42));
+ t.is("000000000000-42", sprintf("%015d", -42));
+ }
+ },
+ {
+ name: "Flag: -",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ t.is("42", sprintf("%-d", 42));
+ t.is("-42", sprintf("%-d", -42));
+ t.is("42 ", sprintf("%-5d", 42));
+ t.is("-42 ", sprintf("%-5d", -42));
+ t.is("42 ", sprintf("%-15d", 42));
+ t.is("-42 ", sprintf("%-15d", -42));
+
+ t.is("42", sprintf("%-0d", 42));
+ t.is("-42", sprintf("%-0d", -42));
+ t.is("42 ", sprintf("%-05d", 42));
+ t.is("-42 ", sprintf("%-05d", -42));
+ t.is("42 ", sprintf("%-015d", 42));
+ t.is("-42 ", sprintf("%-015d", -42));
+
+ t.is("42", sprintf("%0-d", 42));
+ t.is("-42", sprintf("%0-d", -42));
+ t.is("42 ", sprintf("%0-5d", 42));
+ t.is("-42 ", sprintf("%0-5d", -42));
+ t.is("42 ", sprintf("%0-15d", 42));
+ t.is("-42 ", sprintf("%0-15d", -42));
+ }
+ },
+ {
+ name: "Precision",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ t.is("42", sprintf("%d", 42.8952));
+ t.is("42", sprintf("%.2d", 42.8952)); // Note: the %d format is an int
+ t.is("42", sprintf("%.2i", 42.8952));
+ t.is("42.90", sprintf("%.2f", 42.8952));
+ t.is("42.90", sprintf("%.2F", 42.8952));
+ t.is("42.8952000000", sprintf("%.10f", 42.8952));
+ t.is("42.90", sprintf("%1.2f", 42.8952));
+ t.is(" 42.90", sprintf("%6.2f", 42.8952));
+ t.is("042.90", sprintf("%06.2f", 42.8952));
+ t.is("+42.90", sprintf("%+6.2f", 42.8952));
+ t.is("42.8952000000", sprintf("%5.10f", 42.8952));
+ }
+ },
+ {
+ name: "Bases",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ t.is("\x7f", sprintf("%c", 0x7f));
+
+ var error = false;
+ try {
+ sprintf("%c", -100);
+ }catch(e){
+ t.is("invalid character code passed to %c in sprintf", e.message);
+ error = true;
+ }
+ t.t(error);
+
+ error = false;
+ try {
+ sprintf("%c", 0x200000);
+ }catch(e){
+ t.is("invalid character code passed to %c in sprintf", e.message);
+ error = true;
+ }
+ t.t(error);
+ }
+ },
+ {
+ name: "Mapping",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ // %1$s format
+ t.is("%1$", sprintf("%1$"));
+ t.is("%0$s", sprintf("%0$s"));
+ t.is("Hot Pocket", sprintf("%1$s %2$s", "Hot", "Pocket"));
+ t.is("12.0 Hot Pockets", sprintf("%1$.1f %2$s %3$ss", 12, "Hot", "Pocket"));
+ t.is(" 42", sprintf("%1$*.f", "42", 3));
+
+ error = false;
+ try {
+ sprintf("%2$*s", "Hot Pocket");
+ }catch(e){
+ t.is("got 1 printf arguments, insufficient for '%2$*s'", e.message);
+ error = true;
+ }
+ t.t(error);
+
+ // %(map)s format
+ t.is("%(foo", sprintf("%(foo", {}));
+ t.is("Hot Pocket", sprintf("%(temperature)s %(crevace)s", {
+ temperature: "Hot",
+ crevace: "Pocket"
+ }));
+ t.is("12.0 Hot Pockets", sprintf("%(quantity).1f %(temperature)s %(crevace)ss", {
+ quantity: 12,
+ temperature: "Hot",
+ crevace: "Pocket"
+ }));
+
+ var error = false;
+ try {
+ sprintf("%(foo)s", 42);
+ }catch(e){
+ t.is("format requires a mapping", e.message);
+ error = true;
+ }
+ t.t(error);
+
+ error = false;
+ try {
+ sprintf("%(foo)s %(bar)s", "foo", 42);
+ }catch(e){
+ t.is("format requires a mapping", e.message);
+ error = true;
+ }
+ t.t(error);
+
+ error = false;
+ try {
+ sprintf("%(foo)*s", {
+ foo: "Hot Pocket"
+ });
+ }catch(e){
+ t.is("* width not supported in mapped formats", e.message);
+ error = true;
+ }
+ t.t(error);
+ }
+ },
+ {
+ name: "Positionals",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ t.is(" foo", sprintf("%*s", "foo", 4));
+ t.is(" 3.14", sprintf("%*.*f", 3.14159265, 10, 2));
+ t.is("0000003.14", sprintf("%0*.*f", 3.14159265, 10, 2));
+ t.is("3.14 ", sprintf("%-*.*f", 3.14159265, 10, 2));
+
+ var error = false;
+ try {
+ sprintf("%*s", "foo", "bar");
+ }catch(e){
+ t.is("the argument for * width at position 2 is not a number in %*s", e.message);
+ error = true;
+ }
+ t.t(error);
+
+ error = false;
+ try {
+ sprintf("%10.*f", "foo", 42);
+ }catch(e){
+ t.is("format argument 'foo' not a float; parseFloat returned NaN", e.message);
+ error = true;
+ }
+ t.t(error);
+ }
+ },
+ {
+ name: "vs. Formatter",
+ runTest: function(t){
+ var sprintf = dojox.string.sprintf;
+
+ for(var i = 0; i < 1000; i++){
+ sprintf("%d %s Pockets", i, "Hot");
+ }
+ }
+ },
+ {
+ name: "Formatter",
+ runTest: function(t){
+ var Formatter = dojox.string.sprintf.Formatter;
+
+ var str = new Formatter("%d %s Pockets");
+ for(var i = 0; i < 1000; i++){
+ str.format(i, "Hot");
+ }
+ }
+ },
+ {
+ name: "Miscellaneous",
+ runTest: function(t) {
+ var sprintf = dojox.string.sprintf;
+
+ t.is("+hello+", sprintf("+%s+", "hello"));
+ t.is("+10+", sprintf("+%d+", 10));
+ t.is("a", sprintf("%c", "a"));
+ t.is('"', sprintf("%c", 34));
+ t.is('$', sprintf("%c", 36));
+ t.is("10", sprintf("%d", 10));
+
+ var error = false;
+ try {
+ sprintf("%s%s", 42);
+ }catch(e){
+ t.is("got 1 printf arguments, insufficient for '%s%s'", e.message);
+ error = true;
+ }
+ t.t(error);
+
+ error = false;
+ try {
+ sprintf("%c");
+ }catch(e){
+ t.is("got 0 printf arguments, insufficient for '%c'", e.message);
+ error = true;
+ }
+ t.t(error);
+
+ t.is("%10", sprintf("%10", 42));
+ }
+ }
+]);
+
+}
diff --git a/includes/js/dojox/string/tests/string.js b/includes/js/dojox/string/tests/string.js
new file mode 100644
index 0000000..8afee57
--- /dev/null
+++ b/includes/js/dojox/string/tests/string.js
@@ -0,0 +1,10 @@
+if(!dojo._hasResource["dojox.string.tests.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.string.tests.string"] = true;
+dojo.provide("dojox.string.tests.string");
+
+try{
+ dojo.require("dojox.string.tests.Builder");
+ dojo.require("dojox.string.tests.sprintf");
+} catch(e){ }
+
+}
diff --git a/includes/js/dojox/string/tokenize.js b/includes/js/dojox/string/tokenize.js
new file mode 100644
index 0000000..632eb6e
--- /dev/null
+++ b/includes/js/dojox/string/tokenize.js
@@ -0,0 +1,42 @@
+if(!dojo._hasResource["dojox.string.tokenize"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.string.tokenize"] = true;
+dojo.provide("dojox.string.tokenize");
+
+dojox.string.tokenize = function(/*String*/ str, /*RegExp*/ re, /*Function?*/ parseDelim, /*Object?*/ instance){
+ // summary:
+ // Split a string by a regular expression with the ability to capture the delimeters
+ // parseDelim:
+ // Each group (excluding the 0 group) is passed as a parameter. If the function returns
+ // a value, it's added to the list of tokens.
+ // instance:
+ // Used as the "this" instance when calling parseDelim
+ var tokens = [];
+ var match, content, lastIndex = 0;
+ while(match = re.exec(str)){
+ content = str.slice(lastIndex, re.lastIndex - match[0].length);
+ if(content.length){
+ tokens.push(content);
+ }
+ if(parseDelim){
+ if(dojo.isOpera){
+ var copy = match.slice(0);
+ while(copy.length < match.length){
+ copy.push(null);
+ }
+ match = copy;
+ }
+ var parsed = parseDelim.apply(instance, match.slice(1).concat(tokens.length));
+ if(typeof parsed != "undefined"){
+ tokens.push(parsed);
+ }
+ }
+ lastIndex = re.lastIndex;
+ }
+ content = str.slice(lastIndex);
+ if(content.length){
+ tokens.push(content);
+ }
+ return tokens;
+}
+
+}