Subversion Repositories uuid_mac_utils

Rev

Rev 69 | Rev 71 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 69 Rev 70
Line 578... Line 578...
578
                                case 7:
578
                                case 7:
579
                                        /*
579
                                        /*
580
                                        Variant 1, Version 7 UUID
580
                                        Variant 1, Version 7 UUID
581
                                        - 48 bit Unix Time in milliseconds
581
                                        - 48 bit Unix Time in milliseconds
582
                                        -  4 bit Version (fix 0x7)
582
                                        -  4 bit Version (fix 0x7)
583
                                        - 12 bit Random
583
                                        - 12 bit Data
584
                                        -  2 bit Variant (fix 0b10)
584
                                        -  2 bit Variant (fix 0b10)
585
                                        - 62 bit Random
585
                                        - 62 bit Data
-
 
586
 
-
 
587
                                        Structure of data (74 bits):
-
 
588
                                        - OPTIONAL : Sub-millisecond timestamp fraction (0-12 bits)
-
 
589
                                        - OPTIONAL : Carefully seeded counter
-
 
590
                                        - Random generated bits for any remaining space
-
 
591
 
-
 
592
                                        Since we don't know if timestamp fraction or counters are implemented
-
 
593
                                        (and if so, how many bits), we don't decode this information
586
                                        */
594
                                        */
587
 
595
 
588
                                        echo sprintf("%-32s %s\n", "Version:", "[0x7] Unix Epoch Time");
596
                                        echo sprintf("%-32s %s\n", "Version:", "[0x7] Unix Epoch Time");
589
 
597
 
590
                                        $timestamp = substr($uuid, 0, 12);
598
                                        $timestamp = substr($uuid, 0, 12);
Line 1219... Line 1227...
1219
 
1227
 
1220
# --------------------------------------
1228
# --------------------------------------
1221
// Variant 1, Version 7 (Unix Epoch) UUID
1229
// Variant 1, Version 7 (Unix Epoch) UUID
1222
# --------------------------------------
1230
# --------------------------------------
1223
 
1231
 
1224
function gen_uuid_v7() {
1232
function gen_uuid_v7(int $num_ms_frac_bits=12) {
1225
        return gen_uuid_unix_epoch();
1233
        return gen_uuid_unix_epoch($num_ms_frac_bits);
1226
}
1234
}
1227
function gen_uuid_unix_epoch() {
1235
function gen_uuid_unix_epoch(int $num_ms_frac_bits=12) {
1228
        // Start with an UUIDv4
-
 
1229
        $uuid = gen_uuid_random();
1236
        $uuid_nibbles = '';
1230
 
1237
 
1231
        // Add the timestamp
1238
        // Add the timestamp (milliseconds Unix)
1232
        usleep(1000); // Wait 1ms, to make sure that the time part changes if multiple UUIDs are generated
-
 
1233
        if (function_exists('gmp_init')) {
1239
        if (function_exists('gmp_init')) {
1234
                list($ms,$sec) = explode(' ', microtime(false));
1240
                list($ms,$sec) = explode(' ', microtime(false));
1235
                $sec = gmp_init($sec, 10);
1241
                $sec = gmp_init($sec, 10);
1236
                $ms = gmp_init(substr($ms,2,3), 10);
1242
                $ms = gmp_init(substr($ms,2,3), 10);
1237
                $unix_ts = gmp_strval(gmp_add(gmp_mul($sec, '1000'), $ms),16);
1243
                $unix_ts = gmp_strval(gmp_add(gmp_mul($sec, '1000'), $ms),16);
1238
        } else {
1244
        } else {
1239
                $unix_ts = dechex((int)round(microtime(true)*1000));
1245
                $unix_ts = dechex((int)ceil(microtime(true)*1000));
1240
        }
1246
        }
1241
        $unix_ts = str_pad($unix_ts, 12, '0', STR_PAD_LEFT);
1247
        $unix_ts = str_pad($unix_ts, 12, '0', STR_PAD_LEFT);
1242
        for ($i=0;$i<8;$i++) $uuid[$i] = substr($unix_ts, $i, 1);
1248
        $uuid_nibbles = $unix_ts;
1243
        for ($i=0;$i<4;$i++) $uuid[9+$i] = substr($unix_ts, 8+$i, 1);
-
 
1244
 
1249
 
1245
        // set version
1250
        // Version = 7
1246
        $uuid[14] = '7';
1251
        $uuid_nibbles .= '7';
1247
 
1252
 
-
 
1253
        // Optional: millisecond fraction (max 12 bits)
-
 
1254
        if (($num_ms_frac_bits < 0) || ($num_ms_frac_bits > 12)) throw new Exception("Invalid msec frac bits (must be 0..12)");
-
 
1255
        if ($num_ms_frac_bits > 0) {
-
 
1256
                $seconds_fraction = (float)explode(' ',microtime(false))[0];
-
 
1257
                $nanoseconds_fraction = $seconds_fraction * 1000000;
-
 
1258
                $resolution_ns = 1000000 / pow(2,$num_ms_frac_bits);
-
 
1259
                $val = (int)ceil($nanoseconds_fraction / $resolution_ns);
-
 
1260
 
-
 
1261
                // Currently, for the output we only allow frac bits 0, 4, 8, 12 (0-3 nibbles),
-
 
1262
                // since UUIDs are usually sorted in their hex notation
-
 
1263
                $num_nibbles = (int)ceil($num_ms_frac_bits/4);
-
 
1264
                $nibble_string = str_pad(dechex($val), $num_nibbles, '0', STR_PAD_LEFT);
-
 
1265
                $uuid_nibbles .= $nibble_string;
-
 
1266
        } else {
-
 
1267
                $resolution_ns = 1000000;
-
 
1268
        }
-
 
1269
 
-
 
1270
        // TODO Not implemented: Optional counter (to be defined as parameter to this method)
-
 
1271
        // The counter bits need to be spread before and after the variant bits
-
 
1272
 
-
 
1273
        // Fill with random bits (and the variant bits)
-
 
1274
        $uuid = gen_uuid_random();
-
 
1275
        $uuid = str_replace('-', '', $uuid);
-
 
1276
        for ($i=0; $i<strlen($uuid_nibbles); $i++) $uuid[$i] = $uuid_nibbles[$i];
-
 
1277
 
-
 
1278
        // Wait to make sure that the time part changes if multiple UUIDs are generated
-
 
1279
        // We don't use usleep(), because it often does not sleep long enough!
-
 
1280
        //       $resolution_us = (int)ceil($resolution_ns/1000);
-
 
1281
        //       if ($resolution_us > 0) usleep($resolution_us);
-
 
1282
        // We use this naive approach instead:
-
 
1283
        if ($num_ms_frac_bits > 0) {
-
 
1284
                $seconds_fraction = (float)explode(' ',microtime(false))[0];
-
 
1285
                $nanoseconds_fraction = $seconds_fraction * 1000000;
-
 
1286
                $resolution_ns = 1000000 / pow(2,$num_ms_frac_bits);
-
 
1287
                $val = (int)ceil($nanoseconds_fraction / $resolution_ns);
-
 
1288
                do {
-
 
1289
                        $seconds_fraction = (float)explode(' ',microtime(false))[0];
-
 
1290
                        $nanoseconds_fraction = $seconds_fraction * 1000000;
-
 
1291
                        $resolution_ns = 1000000 / pow(2,$num_ms_frac_bits);
-
 
1292
                        $val2 = (int)ceil($nanoseconds_fraction / $resolution_ns);
-
 
1293
                } while ($val == $val2);
-
 
1294
        } else {
-
 
1295
                $unix_ts = dechex((int)ceil(microtime(true)*1000));
-
 
1296
                do {
-
 
1297
                        $unix_ts2 = dechex((int)ceil(microtime(true)*1000));
-
 
1298
                } while ($unix_ts == $unix_ts2);
-
 
1299
        }
-
 
1300
 
-
 
1301
        // Output
1248
        return $uuid;
1302
        return substr($uuid,  0, 8).'-'.
-
 
1303
               substr($uuid,  8, 4).'-'.
-
 
1304
               substr($uuid, 12, 4).'-'.
-
 
1305
               substr($uuid, 16, 4).'-'.
-
 
1306
               substr($uuid, 20, 12);
1249
}
1307
}
1250
 
1308
 
1251
# --------------------------------------
1309
# --------------------------------------
1252
// Variant 1, Version 8 (Custom) UUID
1310
// Variant 1, Version 8 (Custom) UUID
1253
# --------------------------------------
1311
# --------------------------------------