/** * @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 */