uuid.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /**
  2. * UUID.js - RFC-compliant UUID Generator for JavaScript
  3. *
  4. * @file
  5. * @author LiosK
  6. * @version v4.2.9
  7. * @license Apache License 2.0: Copyright (c) 2010-2021 LiosK
  8. */
  9. /**
  10. * @class
  11. * @classdesc {@link UUID} object.
  12. * @hideconstructor
  13. */
  14. var UUID;
  15. UUID = (function(overwrittenUUID) {
  16. "use strict";
  17. // Core Component {{{
  18. /**
  19. * Generates a version 4 UUID as a hexadecimal string.
  20. * @returns {string} Hexadecimal UUID string.
  21. */
  22. UUID.generate = function() {
  23. var rand = UUID._getRandomInt, hex = UUID._hexAligner;
  24. return hex(rand(32), 8) // time_low
  25. + "-"
  26. + hex(rand(16), 4) // time_mid
  27. + "-"
  28. + hex(0x4000 | rand(12), 4) // time_hi_and_version
  29. + "-"
  30. + hex(0x8000 | rand(14), 4) // clock_seq_hi_and_reserved clock_seq_low
  31. + "-"
  32. + hex(rand(48), 12); // node
  33. };
  34. /**
  35. * Returns an unsigned x-bit random integer.
  36. * @private
  37. * @param {number} x Unsigned integer ranging from 0 to 53, inclusive.
  38. * @returns {number} Unsigned x-bit random integer (0 <= f(x) < 2^x).
  39. */
  40. UUID._getRandomInt = function(x) {
  41. if (x < 0 || x > 53) { return NaN; }
  42. var n = 0 | Math.random() * 0x40000000; // 1 << 30
  43. return x > 30 ? n + (0 | Math.random() * (1 << x - 30)) * 0x40000000 : n >>> 30 - x;
  44. };
  45. /**
  46. * Converts an integer to a zero-filled hexadecimal string.
  47. * @private
  48. * @param {number} num
  49. * @param {number} length
  50. * @returns {string}
  51. */
  52. UUID._hexAligner = function(num, length) {
  53. var str = num.toString(16), i = length - str.length, z = "0";
  54. for (; i > 0; i >>>= 1, z += z) { if (i & 1) { str = z + str; } }
  55. return str;
  56. };
  57. /**
  58. * Retains the value of 'UUID' global variable assigned before loading UUID.js.
  59. * @since 3.2
  60. * @type {any}
  61. */
  62. UUID.overwrittenUUID = overwrittenUUID;
  63. // }}}
  64. // Advanced Random Number Generator Component {{{
  65. (function() {
  66. var mathPRNG = UUID._getRandomInt;
  67. /**
  68. * Enables Math.random()-based pseudorandom number generator instead of cryptographically safer options.
  69. * @since v3.5.0
  70. * @deprecated This method is provided only to work around performance drawbacks of the safer algorithms.
  71. */
  72. UUID.useMathRandom = function() {
  73. UUID._getRandomInt = mathPRNG;
  74. };
  75. var crypto = null, cryptoPRNG = mathPRNG;
  76. if (typeof window !== "undefined" && (crypto = window.crypto || window.msCrypto)) {
  77. if (crypto.getRandomValues && typeof Uint32Array !== "undefined") {
  78. // Web Cryptography API
  79. cryptoPRNG = function(x) {
  80. if (x < 0 || x > 53) { return NaN; }
  81. var ns = new Uint32Array(x > 32 ? 2 : 1);
  82. ns = crypto.getRandomValues(ns) || ns;
  83. return x > 32 ? ns[0] + (ns[1] >>> 64 - x) * 0x100000000 : ns[0] >>> 32 - x;
  84. };
  85. }
  86. } else if (typeof require !== "undefined" && (crypto = require("crypto"))) {
  87. if (crypto.randomBytes) {
  88. // nodejs
  89. cryptoPRNG = function(x) {
  90. if (x < 0 || x > 53) { return NaN; }
  91. var buf = crypto.randomBytes(x > 32 ? 8 : 4), n = buf.readUInt32BE(0);
  92. return x > 32 ? n + (buf.readUInt32BE(4) >>> 64 - x) * 0x100000000 : n >>> 32 - x;
  93. };
  94. }
  95. }
  96. UUID._getRandomInt = cryptoPRNG;
  97. })();
  98. // }}}
  99. // UUID Object Component {{{
  100. /**
  101. * Names of UUID internal fields.
  102. * @type {string[]}
  103. * @constant
  104. * @since 3.0
  105. */
  106. UUID.FIELD_NAMES = ["timeLow", "timeMid", "timeHiAndVersion",
  107. "clockSeqHiAndReserved", "clockSeqLow", "node"];
  108. /**
  109. * Sizes of UUID internal fields.
  110. * @type {number[]}
  111. * @constant
  112. * @since 3.0
  113. */
  114. UUID.FIELD_SIZES = [32, 16, 16, 8, 8, 48];
  115. /**
  116. * Creates a version 4 {@link UUID} object.
  117. * @returns {UUID} Version 4 {@link UUID} object.
  118. * @since 3.0
  119. */
  120. UUID.genV4 = function() {
  121. var rand = UUID._getRandomInt;
  122. return new UUID()._init(rand(32), rand(16), // time_low time_mid
  123. 0x4000 | rand(12), // time_hi_and_version
  124. 0x80 | rand(6), // clock_seq_hi_and_reserved
  125. rand(8), rand(48)); // clock_seq_low node
  126. };
  127. /**
  128. * Converts a hexadecimal UUID string to a {@link UUID} object.
  129. * @param {string} strId Hexadecimal UUID string ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").
  130. * @returns {UUID} {@link UUID} object or null.
  131. * @since 3.0
  132. */
  133. UUID.parse = function(strId) {
  134. 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;
  135. if (r = p.exec(strId)) {
  136. var l = r[1] || "", t = r[8] || "";
  137. if (((l + t) === "") ||
  138. (l === "{" && t === "}") ||
  139. (l.toLowerCase() === "urn:uuid:" && t === "")) {
  140. return new UUID()._init(parseInt(r[2], 16), parseInt(r[3], 16),
  141. parseInt(r[4], 16), parseInt(r[5], 16),
  142. parseInt(r[6], 16), parseInt(r[7], 16));
  143. }
  144. }
  145. return null;
  146. };
  147. /**
  148. * Initializes a {@link UUID} object.
  149. * @private
  150. * @constructs UUID
  151. * @param {number} [timeLow=0] time_low field (octet 0-3, uint32).
  152. * @param {number} [timeMid=0] time_mid field (octet 4-5, uint16).
  153. * @param {number} [timeHiAndVersion=0] time_hi_and_version field (octet 6-7, uint16).
  154. * @param {number} [clockSeqHiAndReserved=0] clock_seq_hi_and_reserved field (octet 8, uint8).
  155. * @param {number} [clockSeqLow=0] clock_seq_low field (octet 9, uint8).
  156. * @param {number} [node=0] node field (octet 10-15, uint48).
  157. * @returns {UUID} this.
  158. */
  159. UUID.prototype._init = function() {
  160. var names = UUID.FIELD_NAMES, sizes = UUID.FIELD_SIZES;
  161. var bin = UUID._binAligner, hex = UUID._hexAligner;
  162. /**
  163. * UUID internal field values as an array of integers.
  164. * @type {number[]}
  165. */
  166. this.intFields = new Array(6);
  167. /**
  168. * UUID internal field values as an array of binary strings.
  169. * @type {string[]}
  170. */
  171. this.bitFields = new Array(6);
  172. /**
  173. * UUID internal field values as an array of hexadecimal strings.
  174. * @type {string[]}
  175. */
  176. this.hexFields = new Array(6);
  177. for (var i = 0; i < 6; i++) {
  178. var intValue = parseInt(arguments[i] || 0);
  179. this.intFields[i] = this.intFields[names[i]] = intValue;
  180. this.bitFields[i] = this.bitFields[names[i]] = bin(intValue, sizes[i]);
  181. this.hexFields[i] = this.hexFields[names[i]] = hex(intValue, sizes[i] >>> 2);
  182. }
  183. /**
  184. * UUID version number.
  185. * @type {number}
  186. */
  187. this.version = (this.intFields.timeHiAndVersion >>> 12) & 0xF;
  188. /**
  189. * 128-bit binary string representation.
  190. * @type {string}
  191. */
  192. this.bitString = this.bitFields.join("");
  193. /**
  194. * Non-delimited hexadecimal string representation ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").
  195. * @type {string}
  196. * @since v3.3.0
  197. */
  198. this.hexNoDelim = this.hexFields.join("");
  199. /**
  200. * Hexadecimal string representation ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").
  201. * @type {string}
  202. */
  203. this.hexString = this.hexFields[0] + "-" + this.hexFields[1] + "-" + this.hexFields[2]
  204. + "-" + this.hexFields[3] + this.hexFields[4] + "-" + this.hexFields[5];
  205. /**
  206. * URN string representation ("urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").
  207. * @type {string}
  208. */
  209. this.urn = "urn:uuid:" + this.hexString;
  210. return this;
  211. };
  212. /**
  213. * Converts an integer to a zero-filled binary string.
  214. * @private
  215. * @param {number} num
  216. * @param {number} length
  217. * @returns {string}
  218. */
  219. UUID._binAligner = function(num, length) {
  220. var str = num.toString(2), i = length - str.length, z = "0";
  221. for (; i > 0; i >>>= 1, z += z) { if (i & 1) { str = z + str; } }
  222. return str;
  223. };
  224. /**
  225. * Returns the hexadecimal string representation.
  226. * @returns {string} {@link UUID#hexString}.
  227. */
  228. UUID.prototype.toString = function() { return this.hexString; };
  229. /**
  230. * Tests if two {@link UUID} objects are equal.
  231. * @param {UUID} uuid
  232. * @returns {boolean} True if two {@link UUID} objects are equal.
  233. */
  234. UUID.prototype.equals = function(uuid) {
  235. if (!(uuid instanceof UUID)) { return false; }
  236. for (var i = 0; i < 6; i++) {
  237. if (this.intFields[i] !== uuid.intFields[i]) { return false; }
  238. }
  239. return true;
  240. };
  241. /**
  242. * Nil UUID object.
  243. * @type {UUID}
  244. * @constant
  245. * @since v3.4.0
  246. */
  247. UUID.NIL = new UUID()._init(0, 0, 0, 0, 0, 0);
  248. // }}}
  249. // UUID Version 1 Component {{{
  250. /**
  251. * Creates a version 1 {@link UUID} object.
  252. * @returns {UUID} Version 1 {@link UUID} object.
  253. * @since 3.0
  254. */
  255. UUID.genV1 = function() {
  256. if (UUID._state == null) { UUID.resetState(); }
  257. var now = new Date().getTime(), st = UUID._state;
  258. if (now != st.timestamp) {
  259. if (now < st.timestamp) { st.sequence++; }
  260. st.timestamp = now;
  261. st.tick = UUID._getRandomInt(4);
  262. } else if (Math.random() < UUID._tsRatio && st.tick < 9984) {
  263. // advance the timestamp fraction at a probability
  264. // to compensate for the low timestamp resolution
  265. st.tick += 1 + UUID._getRandomInt(4);
  266. } else {
  267. st.sequence++;
  268. }
  269. // format time fields
  270. var tf = UUID._getTimeFieldValues(st.timestamp);
  271. var tl = tf.low + st.tick;
  272. var thav = (tf.hi & 0xFFF) | 0x1000; // set version '0001'
  273. // format clock sequence
  274. st.sequence &= 0x3FFF;
  275. var cshar = (st.sequence >>> 8) | 0x80; // set variant '10'
  276. var csl = st.sequence & 0xFF;
  277. return new UUID()._init(tl, tf.mid, thav, cshar, csl, st.node);
  278. };
  279. /**
  280. * Re-initializes the internal state for version 1 UUID creation.
  281. * @since 3.0
  282. */
  283. UUID.resetState = function() {
  284. UUID._state = new UUIDState();
  285. };
  286. function UUIDState() {
  287. var rand = UUID._getRandomInt;
  288. this.timestamp = 0;
  289. this.sequence = rand(14);
  290. this.node = (rand(8) | 1) * 0x10000000000 + rand(40); // set multicast bit '1'
  291. this.tick = rand(4); // timestamp fraction smaller than a millisecond
  292. }
  293. /**
  294. * Probability to advance the timestamp fraction: the ratio of tick movements to sequence increments.
  295. * @private
  296. * @type {number}
  297. */
  298. UUID._tsRatio = 1 / 4;
  299. /**
  300. * Persistent internal state for version 1 UUID creation.
  301. * @private
  302. * @type {UUIDState}
  303. */
  304. UUID._state = null;
  305. /**
  306. * @private
  307. * @param {Date|number} time ECMAScript Date Object or milliseconds from 1970-01-01.
  308. * @returns {any}
  309. */
  310. UUID._getTimeFieldValues = function(time) {
  311. var ts = time - Date.UTC(1582, 9, 15);
  312. var hm = ((ts / 0x100000000) * 10000) & 0xFFFFFFF;
  313. return { low: ((ts & 0xFFFFFFF) * 10000) % 0x100000000,
  314. mid: hm & 0xFFFF, hi: hm >>> 16, timestamp: ts };
  315. };
  316. // }}}
  317. // create local namespace
  318. function UUID() {}
  319. // for nodejs
  320. if (typeof module === "object" && typeof module.exports === "object") {
  321. module.exports = UUID;
  322. }
  323. return UUID;
  324. })(UUID);
  325. // vim: fdm=marker fmr&