indexing description: "UUID" author: "Beat Strasser " date: "$Date$" revision: "$Revision$" deferred class P2P_UUID inherit P2P_ID redefine parse_unique_id, is_unique_id_valid end feature -- Access format: STRING is "uuid" bytes: ARRAY [NATURAL_8] flag_id_type: NATURAL_8 is -- Current flag id type deferred end Minimal_bytes_count: INTEGER is 1 Maximal_bytes_count: INTEGER is 64 Flags_bytes_count: INTEGER is 1 Uuid_bytes_count: INTEGER is 16 feature -- Status report is_unique_id_valid (an_id: STRING): BOOLEAN is -- Is `an_id' a valid unique id? do Result := Precursor (an_id) and an_id.count \\ 2 = 0 and an_id.count >= minimal_bytes_count * 2 and an_id.count <= maximal_bytes_count * 2 end feature {NONE} -- Implementation parse_unique_id is -- Parse `unique_id'. local source_pos: INTEGER do -- parse id to array from source_pos := 1 initialize_bytes until source_pos > unique_id.count - flags_bytes_count * 2 loop bytes[source_pos // 2] := hex_to_natural_8 (unique_id.item (source_pos), unique_id.item (source_pos + 1)) source_pos := source_pos + 2 end -- parse flags bytes[maximal_bytes_count - 1] := hex_to_natural_8 (unique_id.item (unique_id.count - 1), unique_id.item (unique_id.count)) -- parse bytes parse_bytes end parse_bytes is -- Parse `bytes'. Do nothing, redefine if necessary. do end initialize_bytes is -- Initialize bytes array do create bytes.make (minimal_bytes_count - 1, maximal_bytes_count - 1) end hex_to_natural_8 (msc, lsc: CHARACTER): NATURAL_8 is -- Converts hex characters `msb' and `lsb' to a NATURAL_8 require Valid_hex: msc.is_hexa_digit and lsc.is_hexa_digit local n: INTEGER do if msc.is_digit then n := msc.code - ('0').code elseif msc >= 'a' then n := msc.code - ('a').code + 10 else n := msc.code - ('A').code + 10 end if lsc.is_digit then n := (n |<< 4) + lsc.code - ('0').code elseif lsc >= 'a' then n := (n |<< 4) + lsc.code - ('a').code + 10 else n := (n |<< 4) + lsc.code - ('A').code + 10 end Result := n.to_natural_8 end build_uuidformat is -- Build uuid format local id: STRING last, pos: INTEGER do -- look for last used byte (except the flag) from last := maximal_bytes_count - 2 until last < 0 or bytes[last] /= 0 loop last := last - 1 end -- build hex string create id.make (maximal_bytes_count + 1) from pos := 0 until pos > last loop id.append (bytes[pos].to_hex_string) pos := pos + 1 end bytes[maximal_bytes_count - 1] := flag_id_type id.append (flag_id_type.to_hex_string) -- P2P_ID initialization make_with_id (id) end new_uuid: like bytes is -- Create new version 4 IETF variant random UUID local pos: INTEGER do -- create random bytes create Result.make (0, uuid_bytes_count - 1) from pos := 0 until pos = uuid_bytes_count loop Result[pos] := rand.item.as_natural_8 rand.forth pos := pos + 1 end -- mask to produce a version 4 IETF variant random UUID Result[6] := (Result[6] & 0x0F) | 0x40 -- version 4 Result[8] := (Result[8] & 0x3F) | 0x80 -- IETF variant Result[10] := (Result[10] & 0x7F) | 0x80 -- multicast ensure Result_valid: Result /= Void and Result.count = uuid_bytes_count end rand: RANDOM is -- Create random number generator local clock: DT_SHARED_SYSTEM_CLOCK cur_time: DT_DATE_TIME once -- (PROCESS) -- FIXME 20061106 beatstr: not yet implemented in compiler create clock cur_time := clock.system_clock.date_time_now create Result.set_seed (cur_time.day_count * cur_time.seconds_in_day + cur_time.second_count) Result.start end end