UuidGenerator.html 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-data-UuidGenerator'>/**
  19. </span> * @extend Ext.data.IdGenerator
  20. * @author Don Griffin
  21. *
  22. * This class generates UUID's according to RFC 4122. This class has a default id property.
  23. * This means that a single instance is shared unless the id property is overridden. Thus,
  24. * two {@link Ext.data.Model} instances configured like the following share one generator:
  25. *
  26. * Ext.define('MyApp.data.MyModelX', {
  27. * extend: 'Ext.data.Model',
  28. * idgen: 'uuid'
  29. * });
  30. *
  31. * Ext.define('MyApp.data.MyModelY', {
  32. * extend: 'Ext.data.Model',
  33. * idgen: 'uuid'
  34. * });
  35. *
  36. * This allows all models using this class to share a commonly configured instance.
  37. *
  38. * # Using Version 1 (&quot;Sequential&quot;) UUID's
  39. *
  40. * If a server can provide a proper timestamp and a &quot;cryptographic quality random number&quot;
  41. * (as described in RFC 4122), the shared instance can be configured as follows:
  42. *
  43. * Ext.data.IdGenerator.get('uuid').reconfigure({
  44. * version: 1,
  45. * clockSeq: clock, // 14 random bits
  46. * salt: salt, // 48 secure random bits (the Node field)
  47. * timestamp: ts // timestamp per Section 4.1.4
  48. * });
  49. *
  50. * // or these values can be split into 32-bit chunks:
  51. *
  52. * Ext.data.IdGenerator.get('uuid').reconfigure({
  53. * version: 1,
  54. * clockSeq: clock,
  55. * salt: { lo: saltLow32, hi: saltHigh32 },
  56. * timestamp: { lo: timestampLow32, hi: timestamptHigh32 }
  57. * });
  58. *
  59. * This approach improves the generator's uniqueness by providing a valid timestamp and
  60. * higher quality random data. Version 1 UUID's should not be used unless this information
  61. * can be provided by a server and care should be taken to avoid caching of this data.
  62. *
  63. * See http://www.ietf.org/rfc/rfc4122.txt for details.
  64. */
  65. Ext.define('Ext.data.UuidGenerator', (function () {
  66. var twoPow14 = Math.pow(2, 14),
  67. twoPow16 = Math.pow(2, 16),
  68. twoPow28 = Math.pow(2, 28),
  69. twoPow32 = Math.pow(2, 32);
  70. function toHex (value, length) {
  71. var ret = value.toString(16);
  72. if (ret.length &gt; length) {
  73. ret = ret.substring(ret.length - length); // right-most digits
  74. } else if (ret.length &lt; length) {
  75. ret = Ext.String.leftPad(ret, length, '0');
  76. }
  77. return ret;
  78. }
  79. function rand (lo, hi) {
  80. var v = Math.random() * (hi - lo + 1);
  81. return Math.floor(v) + lo;
  82. }
  83. function split (bignum) {
  84. if (typeof(bignum) == 'number') {
  85. var hi = Math.floor(bignum / twoPow32);
  86. return {
  87. lo: Math.floor(bignum - hi * twoPow32),
  88. hi: hi
  89. };
  90. }
  91. return bignum;
  92. }
  93. return {
  94. extend: 'Ext.data.IdGenerator',
  95. alias: 'idgen.uuid',
  96. id: 'uuid', // shared by default
  97. <span id='Ext-data-UuidGenerator-property-salt'> /**
  98. </span> * @property {Number/Object} salt
  99. * When created, this value is a 48-bit number. For computation, this value is split
  100. * into 32-bit parts and stored in an object with `hi` and `lo` properties.
  101. */
  102. <span id='Ext-data-UuidGenerator-property-timestamp'> /**
  103. </span> * @property {Number/Object} timestamp
  104. * When created, this value is a 60-bit number. For computation, this value is split
  105. * into 32-bit parts and stored in an object with `hi` and `lo` properties.
  106. */
  107. <span id='Ext-data-UuidGenerator-cfg-version'> /**
  108. </span> * @cfg {Number} version
  109. * The Version of UUID. Supported values are:
  110. *
  111. * * 1 : Time-based, &quot;sequential&quot; UUID.
  112. * * 4 : Pseudo-random UUID.
  113. *
  114. * The default is 4.
  115. */
  116. version: 4,
  117. constructor: function() {
  118. var me = this;
  119. me.callParent(arguments);
  120. me.parts = [];
  121. me.init();
  122. },
  123. generate: function () {
  124. var me = this,
  125. parts = me.parts,
  126. ts = me.timestamp;
  127. /*
  128. The magic decoder ring (derived from RFC 4122 Section 4.2.2):
  129. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  130. | time_low |
  131. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  132. | time_mid | ver | time_hi |
  133. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  134. |res| clock_hi | clock_low | salt 0 |M| salt 1 |
  135. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  136. | salt (2-5) |
  137. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  138. time_mid clock_hi (low 6 bits)
  139. time_low | time_hi |clock_lo
  140. | | | || salt[0]
  141. | | | || | salt[1..5]
  142. v v v vv v v
  143. 0badf00d-aced-1def-b123-dfad0badbeef
  144. ^ ^ ^
  145. version | multicast (low bit)
  146. |
  147. reserved (upper 2 bits)
  148. */
  149. parts[0] = toHex(ts.lo, 8);
  150. parts[1] = toHex(ts.hi &amp; 0xFFFF, 4);
  151. parts[2] = toHex(((ts.hi &gt;&gt;&gt; 16) &amp; 0xFFF) | (me.version &lt;&lt; 12), 4);
  152. parts[3] = toHex(0x80 | ((me.clockSeq &gt;&gt;&gt; 8) &amp; 0x3F), 2) +
  153. toHex(me.clockSeq &amp; 0xFF, 2);
  154. parts[4] = toHex(me.salt.hi, 4) + toHex(me.salt.lo, 8);
  155. if (me.version == 4) {
  156. me.init(); // just regenerate all the random values...
  157. } else {
  158. // sequentially increment the timestamp...
  159. ++ts.lo;
  160. if (ts.lo &gt;= twoPow32) { // if (overflow)
  161. ts.lo = 0;
  162. ++ts.hi;
  163. }
  164. }
  165. return parts.join('-').toLowerCase();
  166. },
  167. getRecId: function (rec) {
  168. return rec.getId();
  169. },
  170. <span id='Ext-data-UuidGenerator-method-init'> /**
  171. </span> * @private
  172. */
  173. init: function () {
  174. var me = this,
  175. salt, time;
  176. if (me.version == 4) {
  177. // See RFC 4122 (Secion 4.4)
  178. // o If the state was unavailable (e.g., non-existent or corrupted),
  179. // or the saved node ID is different than the current node ID,
  180. // generate a random clock sequence value.
  181. me.clockSeq = rand(0, twoPow14-1);
  182. // we run this on every id generation...
  183. salt = me.salt || (me.salt = {});
  184. time = me.timestamp || (me.timestamp = {});
  185. // See RFC 4122 (Secion 4.4)
  186. salt.lo = rand(0, twoPow32-1);
  187. salt.hi = rand(0, twoPow16-1);
  188. time.lo = rand(0, twoPow32-1);
  189. time.hi = rand(0, twoPow28-1);
  190. } else {
  191. // this is run only once per-instance
  192. me.salt = split(me.salt);
  193. me.timestamp = split(me.timestamp);
  194. // Set multicast bit: &quot;the least significant bit of the first octet of the
  195. // node ID&quot; (nodeId = salt for this implementation):
  196. me.salt.hi |= 0x100;
  197. }
  198. },
  199. <span id='Ext-data-UuidGenerator-method-reconfigure'> /**
  200. </span> * Reconfigures this generator given new config properties.
  201. */
  202. reconfigure: function (config) {
  203. Ext.apply(this, config);
  204. this.init();
  205. }
  206. };
  207. }()));
  208. </pre>
  209. </body>
  210. </html>