github.com/jbking/gohan@v0.0.0-20151217002006-b41ccf1c2a96/etc/extensions/uuid.js (about) 1 // Copyright (C) 2015 NTT Innovation Institute, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 17 // uuid.js 18 // 19 // Copyright (c) 2010-2012 Robert Kieffer 20 // MIT License - http://opensource.org/licenses/mit-license.php 21 22 (function() { 23 var _global = this; 24 25 // Unique ID creation requires a high quality random # generator. We feature 26 // detect to determine the best RNG source, normalizing to a function that 27 // returns 128-bits of randomness, since that's what's usually required 28 var _rng; 29 30 // Allow for MSIE11 msCrypto 31 var _crypto = _global.crypto || _global.msCrypto; 32 33 // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html 34 // 35 // Moderately fast, high quality 36 if (typeof(_global.require) == 'function') { 37 try { 38 var _rb = _global.require('crypto').randomBytes; 39 _rng = _rb && function() {return _rb(16);}; 40 } catch(e) {} 41 } 42 43 if (!_rng && _crypto && _crypto.getRandomValues) { 44 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto 45 // 46 // Moderately fast, high quality 47 var _rnds8 = new Uint8Array(16); 48 _rng = function whatwgRNG() { 49 _crypto.getRandomValues(_rnds8); 50 return _rnds8; 51 }; 52 } 53 54 if (!_rng) { 55 // Math.random()-based (RNG) 56 // 57 // If all else fails, use Math.random(). It's fast, but is of unspecified 58 // quality. 59 var _rnds = new Array(16); 60 _rng = function() { 61 for (var i = 0, r; i < 16; i++) { 62 if ((i & 0x03) === 0) r = Math.random() * 0x100000000; 63 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; 64 } 65 66 return _rnds; 67 }; 68 } 69 70 // Buffer class to use 71 var BufferClass = typeof(_global.Buffer) == 'function' ? _global.Buffer : Array; 72 73 // Maps for number <-> hex string conversion 74 var _byteToHex = []; 75 var _hexToByte = {}; 76 for (var i = 0; i < 256; i++) { 77 _byteToHex[i] = (i + 0x100).toString(16).substr(1); 78 _hexToByte[_byteToHex[i]] = i; 79 } 80 81 // **`parse()` - Parse a UUID into it's component bytes** 82 function parse(s, buf, offset) { 83 var i = (buf && offset) || 0, ii = 0; 84 85 buf = buf || []; 86 s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { 87 if (ii < 16) { // Don't overflow! 88 buf[i + ii++] = _hexToByte[oct]; 89 } 90 }); 91 92 // Zero out remaining bytes if string was short 93 while (ii < 16) { 94 buf[i + ii++] = 0; 95 } 96 97 return buf; 98 } 99 100 // **`unparse()` - Convert UUID byte array (ala parse()) into a string** 101 function unparse(buf, offset) { 102 var i = offset || 0, bth = _byteToHex; 103 return bth[buf[i++]] + bth[buf[i++]] + 104 bth[buf[i++]] + bth[buf[i++]] + '-' + 105 bth[buf[i++]] + bth[buf[i++]] + '-' + 106 bth[buf[i++]] + bth[buf[i++]] + '-' + 107 bth[buf[i++]] + bth[buf[i++]] + '-' + 108 bth[buf[i++]] + bth[buf[i++]] + 109 bth[buf[i++]] + bth[buf[i++]] + 110 bth[buf[i++]] + bth[buf[i++]]; 111 } 112 113 // **`v1()` - Generate time-based UUID** 114 // 115 // Inspired by https://github.com/LiosK/UUID.js 116 // and http://docs.python.org/library/uuid.html 117 118 // random #'s we need to init node and clockseq 119 var _seedBytes = _rng(); 120 121 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) 122 var _nodeId = [ 123 _seedBytes[0] | 0x01, 124 _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] 125 ]; 126 127 // Per 4.2.2, randomize (14 bit) clockseq 128 var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; 129 130 // Previous uuid creation time 131 var _lastMSecs = 0, _lastNSecs = 0; 132 133 // See https://github.com/broofa/node-uuid for API details 134 function v1(options, buf, offset) { 135 var i = buf && offset || 0; 136 var b = buf || []; 137 138 options = options || {}; 139 140 var clockseq = options.clockseq != null ? options.clockseq : _clockseq; 141 142 // UUID timestamps are 100 nano-second units since the Gregorian epoch, 143 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so 144 // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' 145 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. 146 var msecs = options.msecs != null ? options.msecs : new Date().getTime(); 147 148 // Per 4.2.1.2, use count of uuid's generated during the current clock 149 // cycle to simulate higher resolution clock 150 var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; 151 152 // Time since last uuid creation (in msecs) 153 var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; 154 155 // Per 4.2.1.2, Bump clockseq on clock regression 156 if (dt < 0 && options.clockseq == null) { 157 clockseq = clockseq + 1 & 0x3fff; 158 } 159 160 // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new 161 // time interval 162 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { 163 nsecs = 0; 164 } 165 166 // Per 4.2.1.2 Throw error if too many uuids are requested 167 if (nsecs >= 10000) { 168 throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); 169 } 170 171 _lastMSecs = msecs; 172 _lastNSecs = nsecs; 173 _clockseq = clockseq; 174 175 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch 176 msecs += 12219292800000; 177 178 // `time_low` 179 var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; 180 b[i++] = tl >>> 24 & 0xff; 181 b[i++] = tl >>> 16 & 0xff; 182 b[i++] = tl >>> 8 & 0xff; 183 b[i++] = tl & 0xff; 184 185 // `time_mid` 186 var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; 187 b[i++] = tmh >>> 8 & 0xff; 188 b[i++] = tmh & 0xff; 189 190 // `time_high_and_version` 191 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version 192 b[i++] = tmh >>> 16 & 0xff; 193 194 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) 195 b[i++] = clockseq >>> 8 | 0x80; 196 197 // `clock_seq_low` 198 b[i++] = clockseq & 0xff; 199 200 // `node` 201 var node = options.node || _nodeId; 202 for (var n = 0; n < 6; n++) { 203 b[i + n] = node[n]; 204 } 205 206 return buf ? buf : unparse(b); 207 } 208 209 // **`v4()` - Generate random UUID** 210 211 // See https://github.com/broofa/node-uuid for API details 212 function v4(options, buf, offset) { 213 // Deprecated - 'format' argument, as supported in v1.2 214 var i = buf && offset || 0; 215 216 if (typeof(options) == 'string') { 217 buf = options == 'binary' ? new BufferClass(16) : null; 218 options = null; 219 } 220 options = options || {}; 221 222 var rnds = options.random || (options.rng || _rng)(); 223 224 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` 225 rnds[6] = (rnds[6] & 0x0f) | 0x40; 226 rnds[8] = (rnds[8] & 0x3f) | 0x80; 227 228 // Copy bytes to buffer, if provided 229 if (buf) { 230 for (var ii = 0; ii < 16; ii++) { 231 buf[i + ii] = rnds[ii]; 232 } 233 } 234 235 return buf || unparse(rnds); 236 } 237 238 // Export public API 239 var uuid = v4; 240 uuid.v1 = v1; 241 uuid.v4 = v4; 242 uuid.parse = parse; 243 uuid.unparse = unparse; 244 uuid.BufferClass = BufferClass; 245 246 if (typeof(module) != 'undefined' && module.exports) { 247 // Publish as node.js module 248 module.exports = uuid; 249 } else if (typeof define === 'function' && define.amd) { 250 // Publish as AMD module 251 define(function() {return uuid;}); 252 253 254 } else { 255 // Publish as global (in browsers) 256 var _previousRoot = _global.uuid; 257 258 // **`noConflict()` - (browser only) to reset global 'uuid' var** 259 uuid.noConflict = function() { 260 _global.uuid = _previousRoot; 261 return uuid; 262 }; 263 264 _global.uuid = uuid; 265 } 266 }).call(this);