comparison src/implab/Uuid.js @ 3:00779cb63b12

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