It is currently Tue Feb 18, 2020 6:55 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Crossplatform UUID/GUID functions (API Version)
PostPosted: Wed Nov 13, 2019 3:25 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Apr 26, 2003 2:49 pm
Posts: 659
Functions to create unique identifiers in binary or string format like "59a7461e-a234-4b41-8237-9be9e338b58e" for example.
I have seen some code in the forum using pb functions but i wanted to try the API versions.

I think in linux the lib is included but if not use: sudo apt-get install uuid-dev

In mac i used an autorelease pool for each call, i guess everything is released correctly. Wilbert?

Very easy to use, function names are self explanatory, see example.

Edit: Fixed objects release.
Edit2: Fixed objects release again.
Code:
;Crossplatform UUID functions.
;Justin 11/19
;Ver: 1.2

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
   
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
   ImportC "-luuid"
      uuid_generate_time_safe_(id.i) As "uuid_generate_time_safe"
      uuid_unparse_(uuid.i, c.i) As "uuid_unparse"
      uuid_parse_(st.p-UTF8, uid.i) As "uuid_parse"
   EndImport
   
CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS

CompilerEndIf

;- UUID
Structure UUID
   data1.l
   data2.w
   data3.w
   data4.b[8]
EndStructure

Macro uuid_IsEqual(uid1, uid2)
   CompareMemory(uid1, uid2, SizeOf(UUID))
EndMacro

;Creates a new UUID in binary format.
Procedure uuid_Create(*uid.UUID)
   Protected ret
   
   If *uid = #Null : ProcedureReturn #False : EndIf
   
   ret = #False
   
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      If UuidCreate_(*uid) = #RPC_S_OK
         ret = #True
      EndIf

   CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux      
      If uuid_generate_time_safe_(*uid) = 0
         ret = #True
      EndIf
   
   CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
      Protected.i idref
            
      idref = CocoaMessage(0, CocoaMessage(0, 0, "NSUUID alloc"), "init")
      If idref
         CocoaMessage(0, idref, "getUUIDBytes:", *uid)
         CocoaMessage(0, idref, "release") ;alloc
         CocoaMessage(0, idref, "release") ;init
         ret = #True
      EndIf
   CompilerEndIf
   
   ProcedureReturn ret
EndProcedure

;Transforms a binary uuid to its string representation.
Procedure.s uuid_ToString(*uid.UUID)
   Protected.s st
   
   If *uid = #Null : ProcedureReturn "" : EndIf

   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      Protected.i pst
      
      If UuidToString_(*uid, @pst) = #RPC_S_OK
         If pst
            st = PeekS(pst, -1, #PB_Unicode)
            RpcStringFree_(@pst)
         EndIf
      EndIf

   CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
      Protected.i buf

      buf = AllocateMemory(37)
      uuid_unparse_(*uid, buf)
      st = PeekS(buf, -1, #PB_UTF8)
      FreeMemory(buf)
      
   CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
      Protected.i idref, nsStr, strBuf
            
      idref = CocoaMessage(0, CocoaMessage(0, 0, "NSUUID alloc"), "initWithUUIDBytes:", *uid)
      If idref
         nsStr = CocoaMessage(0, idref, "UUIDString")
         If nsStr
            strBuf = CocoaMessage(0, nsStr, "UTF8String")
            If strBuf
               st = PeekS(strBuf, -1, #PB_UTF8)
            EndIf
            
            CocoaMessage(0, nsStr, "release")
         EndIf
         
         CocoaMessage(0, idref, "release") ;alloc
         CocoaMessage(0, idref, "release") ;init
      EndIf
   CompilerEndIf
   
   ProcedureReturn st
EndProcedure

;Transfrom a string uuid to its binary format.
Procedure uuid_FromString(st.s, *uid.UUID)
   Protected ret
   
   If *uid = #Null : ProcedureReturn #Null : EndIf
   
   ret = #False
   
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      If UuidFromString_(st, *uid) = #RPC_S_OK
         ret = #True
      EndIf
      
   CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
      If uuid_parse_(st, *uid) = 0
         ret = #True
      EndIf
      
   CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
      Protected.i idref
            
      idref = CocoaMessage(0, CocoaMessage(0, 0, "NSUUID alloc"), "initWithUUIDString:$", @st)
      If idref
         CocoaMessage(0, idref, "getUUIDBytes:", *uid)
         CocoaMessage(0, idref, "release") ;alloc
         CocoaMessage(0, idref, "release") ;init
         ret = #True
      EndIf    
   CompilerEndIf
   
   ProcedureReturn ret
EndProcedure

Procedure uuid_IsNull(*uid.UUID)
   Protected.UUID idNull
   
   ProcedureReturn uuid_IsEqual(*uid, @idNull)
EndProcedure


;- TEST
EnableExplicit

Define.s sid2
Define.UUID id1, id2

sid2 = "59a7461e-a234-4b41-8237-9be9e338b58e"

uuid_Create(@id1)
uuid_FromString(sid2, @id2)

Debug uuid_ToString(@id1)
Debug uuid_ToString(@id2)

Debug "Are equal " + uuid_IsEqual(@id1, @id2)


Last edited by Justin on Tue Nov 19, 2019 11:30 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Crossplatform UUID/GUID functions (API Version)
PostPosted: Sun Nov 17, 2019 7:43 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4627
Location: Lyon - France
Compiler wrote:
cf618a44-aba9-406b-b47e-ca5a8c2f440e
Are equal 0
Thanks for sharing 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: Crossplatform UUID/GUID functions (API Version)
PostPosted: Mon Nov 18, 2019 6:48 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3601
Location: Netherlands
Justin wrote:
In mac i used an autorelease pool for each call, i guess everything is released correctly. Wilbert?

No, when you use alloc / init, the returned object is not an autorelease object but it should be released manually.
And according to the docs, getUUIDBytes does not have a return value so checking it for being equal to 16 is not safe.

Example ...
Code:
idref = CocoaMessage(0, 0, "NSUUID new")
CocoaMessage(0, idref, "getUUIDBytes:", *uid)
CocoaMessage(0, idref, "release")
ret = #True

idref = CocoaMessage(0, CocoaMessage(0, 0, "NSUUID alloc"), "initWithUUIDString:$", @st)
CocoaMessage(0, idref, "getUUIDBytes:", *uid)
CocoaMessage(0, idref, "release")
ret = #True


By the way, the following C functions are available both on macOS and Linux.
uuid_parse, uuid_unparse, uuid_generate, uuid_generate_random, uuid_generate_time

_________________
macOS 10.15 Catalina, PB 5.71 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: Crossplatform UUID/GUID functions (API Version)
PostPosted: Mon Nov 18, 2019 10:03 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Apr 26, 2003 2:49 pm
Posts: 659
Hi Wilbert, thanks for the tips.

I got rid of the autorelease pool and did it manually, code updated.

With the C functions should be trivial using import, i leave the cocoa version for reference.


Top
 Profile  
Reply with quote  
 Post subject: Re: Crossplatform UUID/GUID functions (API Version)
PostPosted: Tue Nov 19, 2019 12:18 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Apr 26, 2003 2:49 pm
Posts: 659
Fixed the release stuff again it seems a release its needed for both alloc and init. I think is ok now.


Top
 Profile  
Reply with quote  
 Post subject: Re: Crossplatform UUID/GUID functions (API Version)
PostPosted: Tue Nov 19, 2019 8:24 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2224
Location: Germany
Endlich eine gültige UUID für alle OS :wink:

Wenn du noch statt Define in Procedure Protected verwendest und
für "ret.b" und "Procedure.b" statt Byte den Type Integer verwendest, ist alles gut.

Boolean als Rückgabewert ist auf allen OS ein Type Integer. Sonst wird mehr unnötiger ASM Code erzeugt, um das Byte zu Filtern.
Man spart also nichts, wenn man Byte für Boolean nimmt.

Kleine Anpassung für Windows ...
Es kann drei verschiedene Ergebnisse kommen. Ich glaube alles drei sind akzeptabel.
Code:
;Creates a new UUID in binary format.
Procedure uuid_Create(*uid.UUID)
  Protected.i ret
 
  If *uid = #Null : ProcedureReturn #False : EndIf
 
  ret = #False
 
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    Protected r1
    r1 = UuidCreate_(*uid)
    If r1 = #RPC_S_OK Or r1 = #RPC_S_UUID_LOCAL_ONLY Or r1 = #RPC_S_UUID_NO_ADDRESS
      ret = #True
    EndIf

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: Crossplatform UUID/GUID functions (API Version)
PostPosted: Tue Nov 19, 2019 11:36 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Apr 26, 2003 2:49 pm
Posts: 659
Hi mk-soft,
i changed to protected and return integer. About the error codes i'm not sure, i think i will stick to RPC_S_OK otherwise i would have to somehow handle those errors.


Top
 Profile  
Reply with quote  
 Post subject: Re: Crossplatform UUID/GUID functions (API Version)
PostPosted: Wed Nov 20, 2019 12:30 am 
Offline
Enthusiast
Enthusiast

Joined: Sat Jul 07, 2018 6:50 pm
Posts: 118
mk-soft wrote:
Code:
    r1 = UuidCreate_(*uid)


BTW
If you do not need such level of security, your application can use the UuidCreateSequential function, which behaves exactly as the UuidCreate function does on all other versions of the operating system.
The UuidCreateSequential function tends to be slightly faster than the UuidCreate function. When the performance of the generation of a UUID is a significant consideration, the UuidCreateSequential function may be used.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye