X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..f562e4c6e5fac7bcb445985b99acbea4d706e6f0:/docs/source/UuidGenerator.html diff --git a/docs/source/UuidGenerator.html b/docs/source/UuidGenerator.html new file mode 100644 index 00000000..65ed0899 --- /dev/null +++ b/docs/source/UuidGenerator.html @@ -0,0 +1,235 @@ + + + + + The source code + + + + + + +
/**
+ * @extend Ext.data.IdGenerator
+ * @author Don Griffin
+ *
+ * This class generates UUID's according to RFC 4122. This class has a default id property.
+ * This means that a single instance is shared unless the id property is overridden. Thus,
+ * two {@link Ext.data.Model} instances configured like the following share one generator:
+ *
+ *     Ext.define('MyApp.data.MyModelX', {
+ *         extend: 'Ext.data.Model',
+ *         idgen: 'uuid'
+ *     });
+ *
+ *     Ext.define('MyApp.data.MyModelY', {
+ *         extend: 'Ext.data.Model',
+ *         idgen: 'uuid'
+ *     });
+ *
+ * This allows all models using this class to share a commonly configured instance.
+ *
+ * # Using Version 1 ("Sequential") UUID's
+ *
+ * If a server can provide a proper timestamp and a "cryptographic quality random number"
+ * (as described in RFC 4122), the shared instance can be configured as follows:
+ *
+ *     Ext.data.IdGenerator.get('uuid').reconfigure({
+ *         version: 1,
+ *         clockSeq: clock, // 14 random bits
+ *         salt: salt,      // 48 secure random bits (the Node field)
+ *         timestamp: ts    // timestamp per Section 4.1.4
+ *     });
+ *
+ *     // or these values can be split into 32-bit chunks:
+ *
+ *     Ext.data.IdGenerator.get('uuid').reconfigure({
+ *         version: 1,
+ *         clockSeq: clock,
+ *         salt: { lo: saltLow32, hi: saltHigh32 },
+ *         timestamp: { lo: timestampLow32, hi: timestamptHigh32 }
+ *     });
+ *
+ * This approach improves the generator's uniqueness by providing a valid timestamp and
+ * higher quality random data. Version 1 UUID's should not be used unless this information
+ * can be provided by a server and care should be taken to avoid caching of this data.
+ *
+ * See http://www.ietf.org/rfc/rfc4122.txt for details.
+ */
+Ext.define('Ext.data.UuidGenerator', function () {
+    var twoPow14 = Math.pow(2, 14),
+        twoPow16 = Math.pow(2, 16),
+        twoPow28 = Math.pow(2, 28),
+        twoPow32 = Math.pow(2, 32);
+
+    function toHex (value, length) {
+        var ret = value.toString(16);
+        if (ret.length > length) {
+            ret = ret.substring(ret.length - length); // right-most digits
+        } else if (ret.length < length) {
+            ret = Ext.String.leftPad(ret, length, '0');
+        }
+        return ret;
+    }
+
+    function rand (lo, hi) {
+        var v = Math.random() * (hi - lo + 1);
+        return Math.floor(v) + lo;
+    }
+
+    function split (bignum) {
+        if (typeof(bignum) == 'number') {
+            var hi = Math.floor(bignum / twoPow32);
+            return {
+                lo: Math.floor(bignum - hi * twoPow32),
+                hi: hi
+            };
+        }
+        return bignum;
+    }
+
+    return {
+        extend: 'Ext.data.IdGenerator',
+
+        alias: 'idgen.uuid',
+
+        id: 'uuid', // shared by default
+
+        /**
+         * @property {Number/Object} salt
+         * When created, this value is a 48-bit number. For computation, this value is split
+         * into 32-bit parts and stored in an object with `hi` and `lo` properties.
+         */
+
+        /**
+         * @property {Number/Object} timestamp
+         * When created, this value is a 60-bit number. For computation, this value is split
+         * into 32-bit parts and stored in an object with `hi` and `lo` properties.
+         */
+
+        /**
+         * @cfg {Number} version
+         * The Version of UUID. Supported values are:
+         *
+         *  * 1 : Time-based, "sequential" UUID.
+         *  * 4 : Pseudo-random UUID.
+         *
+         * The default is 4.
+         */
+        version: 4,
+
+        constructor: function() {
+            var me = this;
+
+            me.callParent(arguments);
+
+            me.parts = [];
+            me.init();
+        },
+
+        generate: function () {
+            var me = this,
+                parts = me.parts,
+                ts = me.timestamp;
+
+            /*
+               The magic decoder ring (derived from RFC 4122 Section 4.2.2):
+
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+               |                          time_low                             |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+               |           time_mid            |  ver  |        time_hi        |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+               |res|  clock_hi |   clock_low   |    salt 0   |M|     salt 1    |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+               |                         salt (2-5)                            |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+                         time_mid      clock_hi (low 6 bits)
+                time_low     | time_hi |clock_lo
+                    |        |     |   || salt[0]
+                    |        |     |   ||   | salt[1..5]
+                    v        v     v   vv   v v
+                    0badf00d-aced-1def-b123-dfad0badbeef
+                                  ^    ^     ^
+                            version    |     multicast (low bit)
+                                       |
+                                    reserved (upper 2 bits)
+            */
+            parts[0] = toHex(ts.lo, 8);
+            parts[1] = toHex(ts.hi & 0xFFFF, 4);
+            parts[2] = toHex(((ts.hi >>> 16) & 0xFFF) | (me.version << 12), 4);
+            parts[3] = toHex(0x80 | ((me.clockSeq >>> 8) & 0x3F), 2) +
+                       toHex(me.clockSeq & 0xFF, 2);
+            parts[4] = toHex(me.salt.hi, 4) + toHex(me.salt.lo, 8);
+
+            if (me.version == 4) {
+                me.init(); // just regenerate all the random values...
+            } else {
+                // sequentially increment the timestamp...
+                ++ts.lo;
+                if (ts.lo >= twoPow32) { // if (overflow)
+                    ts.lo = 0;
+                    ++ts.hi;
+                }
+            }
+
+            return parts.join('-').toLowerCase();
+        },
+
+        getRecId: function (rec) {
+            return rec.getId();
+        },
+
+        /**
+         * @private
+         */
+        init: function () {
+            var me = this,
+                salt, time;
+
+            if (me.version == 4) {
+                // See RFC 4122 (Secion 4.4)
+                //   o  If the state was unavailable (e.g., non-existent or corrupted),
+                //      or the saved node ID is different than the current node ID,
+                //      generate a random clock sequence value.
+                me.clockSeq = rand(0, twoPow14-1);
+
+                // we run this on every id generation...
+                salt = me.salt || (me.salt = {});
+                time = me.timestamp || (me.timestamp = {});
+
+                // See RFC 4122 (Secion 4.4)
+                salt.lo = rand(0, twoPow32-1);
+                salt.hi = rand(0, twoPow16-1);
+                time.lo = rand(0, twoPow32-1);
+                time.hi = rand(0, twoPow28-1);
+            } else {
+                // this is run only once per-instance
+                me.salt = split(me.salt);
+                me.timestamp = split(me.timestamp);
+
+                // Set multicast bit: "the least significant bit of the first octet of the
+                // node ID" (nodeId = salt for this implementation):
+                me.salt.hi |= 0x100;
+            }
+        },
+
+        /**
+         * Reconfigures this generator given new config properties.
+         */
+        reconfigure: function (config) {
+            Ext.apply(this, config);
+            this.init();
+        }
+    };
+}());
+
+ +