Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2005-05

GUID code

14 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

listmember

Hi,

Can anyone let me have a snippet of (or pointers to) code that generates GUI.

I mean the whole code for CreateGUI() --one that does not use OS's GUID stuff.

Cheers,
Ray

listmember
to listmember

Sorry for the typos. Here is a more correct form :-)

Can anyone let me have a snippet of (or pointers to) code that generates GUIDs.

I mean the whole code for CreateGUID() --one that does not use OS's GUID stuff.

Cheers,
Ray

Michael Van Canneyt
to listmember
listmember wrote 7 lines
Sorry for the typos. Here is a more correct form :-) Can anyone let me have a snippet of (or pointers to) code that generates GUIDs. I mean the whole code for CreateGUID() --one that does not use OS's GUID stuff.

See Subversion, SysUtils unit, more specific uuid.pp in the rtl/unix dir.

Michael.

listmember
to Michael Van Canneyt

Michael Van Canneyt wrote:

Hi Michael,

Show quoted text 5 lines
> I mean the whole code for CreateGUID() --one that does not > use OS's GUID stuff. See Subversion, SysUtils unit, more specific uuid.pp in the rtl/unix dir.

Thank you for the pointer.

Without creating incompatibility to the existing code (that of Deplphi and Kylix included), might I suggest a little extension to CreateGUID().

The reason I would like this is, there are timesone would want to create GUIDs based on self supplied MAC numbers.

Here is a template of what I propose. If no one objects to the idea, I can submit real code later.

---BEGIN PSEUDO CODE---

{These should be in Interface section of sysutils unit}
Type
   TMACNumber = Array [0..5] Of Byte;
   TUUIDCreationKind = (ucKernel, ucNIC, ucPseudoMAC);

{I could not find where PreferKernelUUID was defined, but, with these changes we will not need it anymore}

Const
   NullMAC: TMacArray = [0,0,0,0,0,0];
   TUUIDCreationKind = (ucKernel, ucNIC, ucPseudoMAC);

{This should be in the Implemantation section}

Function CreateGUID(
   out GUID : TGUID;
   const UUIDCreationKind: TUUIDCreationKind = ucKernel;
   const MACNumber: TMACNumber = NullMAC
   ) : Integer;
begin
   case UUIDCreationKind of
     ucKernel: begin
       if not CreateKernelGUID(Guid) then
         if not CreateMACGuid(Guid) then
           GetRandomBytes(GUID,SizeOf(Guid));
       end;
     end;
     ucNIC: begin
       if not CreateMACGuid(Guid) then
         if not CreateKernelGUID(Guid) then
           GetRandomBytes(GUID,SizeOf(Guid));
     end;
     ucPseudoMAC: begin
      {Here comes code that uses MACNumber}
     end;
   end;
   Result:=0;
end;
---END PSEUDO CODE---

Cheers,
Adem

Michael Van Canneyt
to listmember
listmember wrote 22 lines
Michael Van Canneyt wrote: Hi Michael, > > I mean the whole code for CreateGUID() --one that does not > > use OS's GUID stuff. > > See Subversion, SysUtils unit, more specific uuid.pp in the > rtl/unix dir. Thank you for the pointer. Without creating incompatibility to the existing code (that of Deplphi and Kylix included), might I suggest a little extension to CreateGUID(). The reason I would like this is, there are timesone would want to create GUIDs based on self supplied MAC numbers. Here is a template of what I propose. If no one objects to the idea, I can submit real code later.

Well, the implementation as it is now for Unix turns out to be very Linux specific. Therefore, the system will be done slightly different.

An

  OnCreateGUID : TCreateGUIDFunc = Nil;

event will be made. if it is set, it will be used instead of the default implementation (which will still be system specific). You can then set this handler to supply your own GUID generation routine. I will supply some example code for Linux, one with the uuid C library, one with the implementation I made earlier (it will be in the packages).

I am working on this now, you can expect it in SubVersion tonight.

Michael.

Michael Van Canneyt
to Michael Van Canneyt
Michael Van Canneyt wrote 41 lines
On Sat, 21 May 2005, listmember wrote: > Michael Van Canneyt wrote: > > Hi Michael, > > > > I mean the whole code for CreateGUID() --one that does not > > > use OS's GUID stuff. > > > > See Subversion, SysUtils unit, more specific uuid.pp in the > > rtl/unix dir. > > Thank you for the pointer. > > Without creating incompatibility to the existing code (that of > Deplphi and Kylix included), might I suggest a little extension > to CreateGUID(). > > The reason I would like this is, there are timesone would > want to create GUIDs based on self supplied MAC numbers. > > Here is a template of what I propose. If no one objects > to the idea, I can submit real code later. > Well, the implementation as it is now for Unix turns out to be very Linux specific. Therefore, the system will be done slightly different. An OnCreateGUID : TCreateGUIDFunc = Nil; event will be made. if it is set, it will be used instead of the default implementation (which will still be system specific). You can then set this handler to supply your own GUID generation routine. I will supply some example code for Linux, one with the uuid C library, one with the implementation I made earlier (it will be in the packages). I am working on this now, you can expect it in SubVersion tonight.

It's in SubVersion.
2 demo units are in packages/extra/uuid, with testprograms.

Michael.

listmember
to Michael Van Canneyt
Michael Van Canneyt wrote
It's in SubVersion. 2 demo units are in packages/extra/uuid, with testprograms.

http://svn.freepascal.org/svn/fpc/trunk/packages/extra/uuid/

It looks OK to me, except that it may be a little more optimized for speed since GUIDs are CPU-expensive to begin with.

A couple of questions, wrt FPC v2.x:

-- Is Int64 supported in all platforms?

-- Is there a Int128 or something like it?
When Windows was 32bit, Delphi had Int64; it's only natural that now we should have Int128 :-)

-- GUID unit being in extra/uuid/, does it mean it will not be available in, say, Windows since Windows has a native call for that.

    Personally, I'd like 'OnCreateGUID : TCreateGUIDFunc = Nil;
    to be available in all platforms.

Cheers,
Basri

Florian Klaempfl
to listmember
listmember wrote 14 lines
Michael Van Canneyt wrote: > It's in SubVersion. 2 demo units are in packages/extra/uuid, with > testprograms. http://svn.freepascal.org/svn/fpc/trunk/packages/extra/uuid/ It looks OK to me, except that it may be a little more optimized for speed since GUIDs are CPU-expensive to begin with. A couple of questions, wrt FPC v2.x: -- Is Int64 supported in all platforms?

Yes.

-- Is there a Int128 or something like it? When Windows was 32bit, Delphi had Int64; it's only natural that now we should have Int128 :-)

Well, has it's purposes for e.g. file size. But tell me applications where you need an Int128?

listmember
to Florian Klaempfl
Florian Klaempfl wrote 12 lines
>A couple of questions, wrt FPC v2.x: > >-- Is Int64 supported in all platforms? Yes. >-- Is there a Int128 or something like it? > When Windows was 32bit, Delphi had Int64; it's only natural > that now we should have Int128 :-) Well, has it's purposes for e.g. file size. But tell me applications where you need an Int128?

I can not come up with a compelling arguement right now, much like I could not come up with one, say, 20 years ago.

Except that, it seems customary to have a data type double the available CPU/OS max bit size.

Ah, here is one: what happens if I wanted to multiply 2 Int64 numbers?

I don't know why I would need to do it right now, though :-)

Michael Van Canneyt
to listmember: http://svn.freepascal.org/svn/fpc/trunk/packages/extra/uuid/ It looks OK to me, except…
listmember wrote 9 lines
Michael Van Canneyt wrote: > It's in SubVersion. 2 demo units are in packages/extra/uuid, with > testprograms. http://svn.freepascal.org/svn/fpc/trunk/packages/extra/uuid/ It looks OK to me, except that it may be a little more optimized for speed since GUIDs are CPU-expensive to begin with.

Feel free to submit patches and a testprogram to prove that your implementation is significantly faster :-)

A couple of questions, wrt FPC v2.x: -- Is Int64 supported in all platforms?

Yes.

-- Is there a Int128 or something like it?

No.

Show quoted text 8 lines
When Windows was 32bit, Delphi had Int64; it's only natural that now we should have Int128 :-) -- GUID unit being in extra/uuid/, does it mean it will not be available in, say, Windows since Windows has a native call for that. Personally, I'd like 'OnCreateGUID : TCreateGUIDFunc = Nil; to be available in all platforms.

It is, sysutils is cross-platform.

On windows the default implementation calls CoCreateGUID, but with OnCreateGUID you can override this behaviour.

On Linux, the default behaviour is to use the kernel /proc/sys/kernel/random/uuid file, and fall back.

On BSD, /dev/urandom is used to generate a random GUID

on all other platforms, the system unit random() function is used.

On all platforms, the default behaviour can be changed using the OnCreateGUID event.

Michael.

Marco van de Voort
to Michael Van Canneyt
On BSD, /dev/urandom is used to generate a random GUID

No, that was my first hunch, but it turned out to be a single kernel call. (FreeBSD 5.x+)

on all other platforms, the system unit random() function is used.

This is FreeBSD4 inclusive.

listmember
to Michael Van Canneyt: Feel free to submit patches and a testprogram to prove that your implementation is…
Michael Van Canneyt wrote 15 lines
On Sat, 21 May 2005, listmember wrote: >Michael Van Canneyt wrote: > >>It's in SubVersion. 2 demo units are in packages/extra/uuid, with >>testprograms. > >http://svn.freepascal.org/svn/fpc/trunk/packages/extra/uuid/ > >It looks OK to me, except that it may be a little more optimized >for speed since GUIDs are CPU-expensive to begin with. Feel free to submit patches and a testprogram to prove that your implementation is significantly faster :-)

:-)

I did not mean it to be condescending; but it probably came out that way. I apologize if it did sound like that.

So, let me start afresh.

I am wet behind-the-ears when it comes to Free Pascal, I don't even know wehere, say, TGUID is declared in FPC (yet).

But, I am not that new to Pascal/Delphi, and I have used them to write engine stuff mainly, in the past.

I have found that it can be easier, faster and more convenient to use variant records to do some 'sub-atomic' operations.

So, in unit uuid, I'd use one of these variant record types in a couple of routines, say, Procedure UUIDPack() instead of SHR ops.

And in Function GetMacAddr() instead of

   P:=Pchar(@ifr.ifru_hwaddr.sa_data);
   Result:=(p[0]#0) or (p[1]#0) or (p[2]#0)
           or (p[3]#0) or (p[4]#0) or (p[5]#0);
we'd have
   Move(ifr.ifru_hwaddr.sa_data, P.Bytes[0], SizeOf(TInt128Splitter));
   Result:= (p.Int640  0) Or (p.Int641  0);
where
  p: TInt128Splitter;

etc.

You might or might not agree with the above, so independent of all that, here is some more blurb promoting it :-)

These variant arrays are, IMHO, more pascal-like than bitwise operations for general users, more convenient (yu get to pick and choose the kind of value you want), and faster sometimes (instead of many SGR/SHL ops), plus they can be useful to convert between little-endian and big-endian numbers etc.

Here below is what they look like, I wonder if you'd consider them.

TWordSplitter = Packed Record
   Case Split: Byte Of
     0: Self: Word;
     1: (
        Byte0 : Byte;
        Byte1 : Byte;
        );
     2: (
        Bytes : Packed Array [0..1] Of Byte;
        );
End;
TIntegerSplitter = Packed Record
   Case Split: Byte Of
     0: Self: Integer;
     1: (
        Byte0 : Byte;
        Byte1 : Byte;
        Byte2 : Byte;
        Byte3 : Byte;
        );
     2: (
        Word0 : Word;
        Word1 : Word;
        );
     3: (
        Bytes : Packed Array [0..3] Of Byte;
        );
     4: (
        Words : Packed Array [0..1] Of Word;
        );
End;
TInt64Splitter = Packed Record
   Case Split: Byte Of
     0: Self: Int64;
     1: (
        Byte0 : Byte;
        Byte1 : Byte;
        Byte2 : Byte;
        Byte3 : Byte;
        Byte4 : Byte;
        Byte5 : Byte;
        Byte6 : Byte;
        Byte7 : Byte;
        );
     2: (
        Word0 : Word;
        Word1 : Word;
        Word2 : Word;
        Word3 : Word;
        );
     3: (
        Integer0 : Integer;
        Integer1 : Integer;
        );
     4: (
        Bytes : Packed Array [0..7] Of Byte;
        );
     5: (
        Words : Packed Array [0..3] Of Word;
        );
     6: (
        Integers : Packed Array [0..1] Of Integers;
        );
End;
{This would be useful for 128-bit stuf, like GUIDs :-) }
TInt128Splitter = Packed Record
   Case Split: Byte Of
     // 0: Self: Int128; //This does not exist
     0: (
        Byte0 : Byte;
        Byte1 : Byte;
        Byte2 : Byte;
        Byte3 : Byte;
        Byte4 : Byte;
        Byte5 : Byte;
        Byte6 : Byte;
        Byte7 : Byte;
        Byte8 : Byte;
        Byte9 : Byte;
        Byte10 : Byte;
        Byte11 : Byte;
        Byte12 : Byte;
        Byte13 : Byte;
        Byte14 : Byte;
        Byte15 : Byte;
        );
     1: (
        Word0 : Word;
        Word1 : Word;
        Word2 : Word;
        Word3 : Word;
        Word4 : Word;
        Word5 : Word;
        Word6 : Word;
        Word7 : Word;
        );
     2: (
        Integer0 : Integer;
        Integer1 : Integer;
        Integer2 : Integer;
        Integer3 : Integer;
        );
     3: (
        Int640 : Int64;
        Int641 : Int64;
        );
     4: (
        Bytes : Packed Array [0..15] Of Byte;
        );
     5: (
        Words : Packed Array [0..7] Of Word;
        );
     6: (
        Integers : Packed Array [0..3] Of Integers;
        );
     7: (
        Int64s : Packed Array [0..1] Of Int64;
        );
End;

Similar stuff can be made for single, double etc. just to work on their byte content (not much more useful than that).

On all platforms, the default behaviour can be changed using the OnCreateGUID event.

This is excellent. Thank you.

Cheers,
Basri

Matt Emson
to listmember: Thank you for the pointer. Without creating incompatibility to the existing code (that of…
The reason I would like this is, there are timesone would want to create GUIDs based on self supplied MAC numbers.

Except, this is not how GUID's are generated under Windows anymore. Microsoft bowed to preassure and now use a completely random key generation technique. This was because a reaction to the paranoid people shouting that Microsoft were attempting to track them via their MAC address. Okay, MAC address is by no means unique, but it does single out a very small subsection of users to be pinpointed by MAC address. Basing any GUID code on MAC address manipulation to gain pseudo random numbers is therefor on shaky ground.

Matt

listmember
to Matt Emson
Matt Emson wrote 11 lines
>The reason I would like this is, there are timesone would >want to create GUIDs based on self supplied MAC numbers. Except, this is not how GUID's are generated under Windows anymore. Microsoft bowed to preassure and now use a completely random key generation technique. This was because a reaction to the paranoid people shouting that Microsoft were attempting to track them via their MAC address. Okay, MAC address is by no means unique, but it does single out a very small subsection of users to be pinpointed by MAC address. Basing any GUID code on MAC address manipulation to gain pseudo random numbers is therefor on shaky ground.

Ah, but you seemed to have missed the gist of my request:

I am aware of Microsoft's plight, and, their problem was due to having embedded the GUID in to, say, MS Word Docs etc. Not a wise move wrt privacy, but completely understandable from POV of police etc.

Frankly, I still think the privacy issue is there; the GUID stuff generated during the MS Office install is stored persistently and every doc you create is watermarked with it. The only way to get rid of it is either by stripping the *.doc file of the GUID, or by reinstalling the OS.

Anyway, back to the topic:

First, we all know that you can alter the MAC address reported to/by the OS, don't we? So, it never was too reliable in the first place.

The reason why one might "want to create GUIDs based on self supplied MAC numbers" is not for those semi-blackhat cases, we may need that in order to be able to generate truely unique (or, as unique as we can) GUIDs and do it faster (i.e. lower overhead) than polling a random number generator or the OS for the MAC address.

This sort of thing is neded for generating prime keys for disconnected database operation. As long as the *client* *count* for the database does not exceed 281,474,976,710,655 (max value you can store in a 6-byte number, i.e. MAC number) we are assured of uniqueness :-)

Cheers,