/**
* @module Container
* @namespace springroll.pbskids
*/
/* jshint ignore:start */
(function()
{
/**
* UUID.js: The RFC-compliant UUID generator for JavaScript.
* @class UUID
*/
var UUID = function() {};
/**
* The simplest function to get an UUID string.
* @method generate
* @static
* @returns {string} A version 4 UUID string.
*/
UUID.generate = function()
{
var rand = UUID._getRandomInt,
hex = UUID._hexAligner;
return hex(rand(32), 8) // time_low
+
"-" + hex(rand(16), 4) // time_mid
+
"-" + hex(0x4000 | rand(12), 4) // time_hi_and_version
+
"-" + hex(0x8000 | rand(14), 4) // clock_seq_hi_and_reserved clock_seq_low
+
"-" + hex(rand(48), 12); // node
};
/**
* Returns an unsigned x-bit random integer.
* @method _getRandomInt
* @static
* @private
* @param {int} x A positive integer ranging from 0 to 53, inclusive.
* @returns {int} An unsigned x-bit random integer (0 <= f(x) < 2^x).
*/
UUID._getRandomInt = function(x)
{
if (x < 0) return NaN;
if (x <= 30) return (0 | Math.random() * (1 << x));
if (x <= 53) return (0 | Math.random() * (1 << 30)) + (0 | Math.random() * (1 << x - 30)) * (1 << 30);
return NaN;
};
/**
* Returns a function that converts an integer to a zero-filled string.
* @method _getIntAligner
* @static
* @private
* @param {int} radix
* @returns {function(num, length)}
*/
UUID._getIntAligner = function(radix)
{
return function(num, length)
{
var str = num.toString(radix),
i = length - str.length,
z = "0";
for (; i > 0; i >>>= 1, z += z)
{
if (i & 1)
{
str = z + str;
}
}
return str;
};
};
UUID._hexAligner = UUID._getIntAligner(16);
/**
* Names of each UUID field.
* @type string[]
* @constant
* @since 3.0
*/
UUID.FIELD_NAMES = ["timeLow", "timeMid", "timeHiAndVersion",
"clockSeqHiAndReserved", "clockSeqLow", "node"
];
/**
* Sizes of each UUID field.
* @property int[] FIELD_SIZES
* @constant
* @since 3.0
*/
UUID.FIELD_SIZES = [32, 16, 16, 8, 8, 48];
/**
* Generates a version 4 {@link UUID}.
* @method getV4
* @static
* @returns {UUID} A version 4 {@link UUID} object.
* @since 3.0
*/
UUID.genV4 = function()
{
var rand = UUID._getRandomInt;
return new UUID()._init(rand(32), rand(16), // time_low time_mid
0x4000 | rand(12), // time_hi_and_version
0x80 | rand(6), // clock_seq_hi_and_reserved
rand(8), rand(48)); // clock_seq_low node
};
/**
* Converts hexadecimal UUID string to an {@link UUID} object.
* @method parse
* @static
* @param {string} strId UUID hexadecimal string representation ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").
* @returns {UUID} {@link UUID} object or null.
* @since 3.0
*/
UUID.parse = function(strId)
{
var r, p = /^\s*(urn:uuid:|\{)?([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{2})([0-9a-f]{2})-([0-9a-f]{12})(\})?\s*$/i;
if (r = p.exec(strId))
{
var l = r[1] || "",
t = r[8] || "";
if (((l + t) === "") ||
(l === "{" && t === "}") ||
(l.toLowerCase() === "urn:uuid:" && t === ""))
{
return new UUID()._init(parseInt(r[2], 16), parseInt(r[3], 16),
parseInt(r[4], 16), parseInt(r[5], 16),
parseInt(r[6], 16), parseInt(r[7], 16));
}
}
return null;
};
/**
* Initializes {@link UUID} object.
* @method _init
* @private
* @param {uint32} [timeLow=0] time_low field (octet 0-3).
* @param {uint16} [timeMid=0] time_mid field (octet 4-5).
* @param {uint16} [timeHiAndVersion=0] time_hi_and_version field (octet 6-7).
* @param {uint8} [clockSeqHiAndReserved=0] clock_seq_hi_and_reserved field (octet 8).
* @param {uint8} [clockSeqLow=0] clock_seq_low field (octet 9).
* @param {uint48} [node=0] node field (octet 10-15).
* @returns {UUID} this.
*/
UUID.prototype._init = function()
{
var names = UUID.FIELD_NAMES,
sizes = UUID.FIELD_SIZES;
var bin = UUID._binAligner,
hex = UUID._hexAligner;
/**
* List of UUID field values (as integer values).
* @type int[]
*/
this.intFields = new Array(6);
/**
* List of UUID field values (as binary bit string values).
* @type string[]
*/
this.bitFields = new Array(6);
/**
* List of UUID field values (as hexadecimal string values).
* @type string[]
*/
this.hexFields = new Array(6);
for (var i = 0; i < 6; i++)
{
var intValue = parseInt(arguments[i] || 0);
this.intFields[i] = this.intFields[names[i]] = intValue;
this.bitFields[i] = this.bitFields[names[i]] = bin(intValue, sizes[i]);
this.hexFields[i] = this.hexFields[names[i]] = hex(intValue, sizes[i] / 4);
}
/**
* UUID version number defined in RFC 4122.
* @type int
*/
this.version = (this.intFields.timeHiAndVersion >> 12) & 0xF;
/**
* 128-bit binary bit string representation.
* @type string
*/
this.bitString = this.bitFields.join("");
/**
* UUID hexadecimal string representation ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").
* @type string
*/
this.hexString = this.hexFields[0] + "-" + this.hexFields[1] + "-" + this.hexFields[2] + "-" + this.hexFields[3] + this.hexFields[4] + "-" + this.hexFields[5];
/**
* UUID string representation as a URN ("urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").
* @type string
*/
this.urn = "urn:uuid:" + this.hexString;
return this;
};
UUID._binAligner = UUID._getIntAligner(2);
/**
* Returns UUID string representation.
* @method toString
* @returns {string} {@link UUID#hexString}.
*/
UUID.prototype.toString = function()
{
return this.hexString;
};
/**
* Tests if two {@link UUID} objects are equal.
* @method equals
* @param {UUID} uuid
* @returns {bool} True if two {@link UUID} objects are equal.
*/
UUID.prototype.equals = function(uuid)
{
if (!(uuid instanceof UUID))
{
return false;
}
for (var i = 0; i < 6; i++)
{
if (this.intFields[i] !== uuid.intFields[i])
{
return false;
}
}
return true;
};
/**
* Generates a version 1 {@link UUID}.
* @method genV1
* @static
* @returns {UUID} A version 1 {@link UUID} object.
* @since 3.0
*/
UUID.genV1 = function()
{
var now = new Date().getTime(),
st = UUID._state;
if (now != st.timestamp)
{
if (now < st.timestamp)
{
st.sequence++;
}
st.timestamp = now;
st.tick = UUID._getRandomInt(4);
}
else if (Math.random() < UUID._tsRatio && st.tick < 9984)
{
// advance the timestamp fraction at a probability
// to compensate for the low timestamp resolution
st.tick += 1 + UUID._getRandomInt(4);
}
else
{
st.sequence++;
}
// format time fields
var tf = UUID._getTimeFieldValues(st.timestamp);
var tl = tf.low + st.tick;
var thav = (tf.hi & 0xFFF) | 0x1000; // set version '0001'
// format clock sequence
st.sequence &= 0x3FFF;
var cshar = (st.sequence >>> 8) | 0x80; // set variant '10'
var csl = st.sequence & 0xFF;
return new UUID()._init(tl, tf.mid, thav, cshar, csl, st.node);
};
/**
* Re-initializes version 1 UUID state.
* @method resetState
* @static
* @since 3.0
*/
UUID.resetState = function()
{
UUID._state = new UUID._state.constructor();
};
/**
* Probability to advance the timestamp fraction: the ratio of tick movements to sequence increments.
* @property {Number} _tsRadio
* @static
* @private
*/
UUID._tsRatio = 1 / 4;
/**
* Persistent state for UUID version 1.
* @property {UUIDState} _state
* @static
* @private
*/
UUID._state = new function UUIDState()
{
var rand = UUID._getRandomInt;
this.timestamp = 0;
this.sequence = rand(14);
this.node = (rand(8) | 1) * 0x10000000000 + rand(40); // set multicast bit '1'
this.tick = rand(4); // timestamp fraction smaller than a millisecond
};
/**
* Get the time from field values
* @method _getTimeFieldValues
* @private
* @param {Date|int} time ECMAScript Date Object or milliseconds from 1970-01-01.
* @returns {object}
*/
UUID._getTimeFieldValues = function(time)
{
var ts = time - Date.UTC(1582, 9, 15);
var hm = ((ts / 0x100000000) * 10000) & 0xFFFFFFF;
return {
low: ((ts & 0xFFFFFFF) * 10000) % 0x100000000,
mid: hm & 0xFFFF,
hi: hm >>> 16,
timestamp: ts
};
};
/**
* Reinstalls {@link UUID.generate} method to emulate the interface of UUID.js version 2.x.
* @method makeBackwardCompatible
* @static
* @since 3.1
* @deprecated Version 2.x. compatible interface is not recommended.
*/
UUID.makeBackwardCompatible = function()
{
var f = UUID.generate;
UUID.generate = function(o)
{
return (o && o.version == 1) ? UUID.genV1().hexString : f.call(UUID);
};
UUID.makeBackwardCompatible = function() {};
};
// Assign to namespace
namespace('springroll.pbskids').UUID = UUID;
})();
/* jshint ignore:end */