Fix byte ordering.
Store fields in network byte order internally.
--- a/UUID.st Mon Feb 20 13:53:54 2006 +0100
+++ b/UUID.st Mon Feb 20 17:21:19 2006 +0100
@@ -40,8 +40,16 @@
128-bit Universal Unique Ids (UUIDs) as defined by OpenGroup/DCE
http://www.opengroup.org/onlinepubs/9629399/apdxa.htm.
+ See also RFC4122.
+
A UUID is unique in time and space (at least until about Year 3400).
+ Several fields if the UUID are interpreted as integers, so host/network byte
+ order is relevant. UUIDs are stored in a ByteArray in network byte order (MSB-first),
+ so they may be exported/imported between different machines.
+
+ You can import UUIDs in host byte order using #fromNativeBytes:
+
[author:]
[instance variables:]
@@ -78,24 +86,33 @@
!UUID class methodsFor:'instance creation'!
fromBytes:aByteArray
- ^ self fromBytes:aByteArray msb:(UninterpretedBytes isBigEndian)
-!
+ "set uuid from aByteArray.
+ aByteArray must be 16 bytes in network byte order (MSB-first)"
-fromBytes:aByteArray msb:msb
- |uuid d1 d2 d3|
+ |uuid|
uuid := self new.
uuid replaceFrom:1 to:16 with:aByteArray.
+ ^ uuid.
- msb ifTrue:[
- d1 := aByteArray unsignedLongAt:1 bigEndian:msb.
- uuid unsignedLongAt:1 put:d1 bigEndian:false.
+ "
+ UUID fromBytes:#[16r01 16r02 16r03 16r04
+ 16r05 16r06 16r07 16r08
+ 16r09 16r10 16r11 16r12
+ 16r13 16r14 16r15 16r16].
+ "
+!
- d2 := aByteArray unsignedShortAt:1+4 bigEndian:msb.
- uuid unsignedShortAt:1+4 put:d2 bigEndian:false.
+fromBytes:aByteArray msb:msb
+ "Set the UUID from aByteArray. UUIDS are stored internally as MSB-first.
+ So, alway set
+ msb = true if reading from network or persistent storage"
- d3 := aByteArray unsignedShortAt:1+4+2 bigEndian:msb.
- uuid unsignedShortAt:1+4+2 put:d3 bigEndian:false.
+ |uuid|
+
+ uuid := self fromBytes:aByteArray.
+ msb ifFalse:[
+ self adjustByteOrder:uuid.
].
^ uuid
@@ -114,6 +131,28 @@
"
!
+fromNativeBytes:aByteArray
+ "convert bytes to uuid.
+ aByteArray represents a UUID in host byte order
+ - e.g. an UUID fetched from the Windows OS"
+
+ |uuid|
+
+ uuid := self fromBytes:aByteArray.
+ self isBigEndian ifFalse:[
+ self adjustByteOrder:uuid.
+ ].
+ ^ uuid.
+
+ "
+ UUID fromNativeBytes:#[16r01 16r02 16r03 16r04
+ 16r05 16r06 16r07 16r08
+ 16r09 16r10 16r11 16r12
+ 16r13 16r14 16r15 16r16].
+
+ "
+!
+
genUUID
"generate a new UUID"
@@ -144,7 +183,6 @@
] do:[
s := aStringOrStream readStream.
uuid := self new.
- offs := 1.
s skipSeparators.
s peek == ${ ifTrue:[s next].
@@ -152,24 +190,26 @@
t := s next:8.
d := Integer readFrom:t radix:16 onError:[^ errorBlock value].
- uuid unsignedLongAt:1 put:d bigEndian:false.
- offs := offs + 4.
+ uuid unsignedLongAt:1 put:d bigEndian:true.
+ offs := 5.
- s next.
+ s next. "skip $-"
1 to:2 do:[:i |
t := s next:4.
d := Integer readFrom:t radix:16 onError:[^ errorBlock value].
- uuid unsignedShortAt:offs put:d bigEndian:false.
+ uuid unsignedShortAt:offs put:d bigEndian:true.
offs := offs + 2.
- s next.
+ s next. "skip $-"
].
- t := s next:4.
- d := Integer readFrom:t radix:16 onError:[^ errorBlock value].
- uuid unsignedShortAt:offs put:d bigEndian:true.
- offs := offs + 2.
- s next.
+ 1 to:2 do:[:i |
+ t := s next:2.
+ d := Integer readFrom:t radix:16 onError:[^ errorBlock value].
+ uuid at:offs put:d.
+ offs := offs + 1.
+ ].
+ s next. "skip $-"
1 to:6 do:[:i |
t := s next:2.
@@ -196,6 +236,21 @@
!UUID class methodsFor:'helpers'!
+adjustByteOrder:aByteArray
+ "change the byte order of the uuid"
+
+ |d|
+
+ d := aByteArray unsignedLongAt:1 bigEndian:false.
+ aByteArray unsignedLongAt:1 put:d bigEndian:true.
+
+ d := aByteArray unsignedShortAt:1+4 bigEndian:false.
+ aByteArray unsignedShortAt:1+4 put:d bigEndian:true.
+
+ d := aByteArray unsignedShortAt:1+4+2 bigEndian:false.
+ aByteArray unsignedShortAt:1+4+2 put:d bigEndian:true.
+!
+
getDtssUtcTime
"return the DTSS based time in 100 nsec intervals
DTSS UTC base time is October 15, 1582.
@@ -238,53 +293,77 @@
!UUID methodsFor:'accessing'!
-clockSeqAndReserved
+clockSeqHiAndReserved
+ ^ self at:9
+!
- ^ self unsignedShortAt:9 bigEndian:false
+clockSeqLow
+ ^ self at:10
!
node
-
- ^ self copyFrom:10 to:16
+ ^ self copyFrom:11 to:16
!
timeHighAndVersion
-
- ^ self unsignedShortAt:7 bigEndian:false
+ ^ self unsignedShortAt:7 bigEndian:true
!
timeLow
-
- ^ self unsignedLongAt:1 bigEndian:false
+ ^ self unsignedLongAt:1 bigEndian:true
!
timeMid
-
- ^ self unsignedShortAt:5 bigEndian:false
+ ^ self unsignedShortAt:5 bigEndian:true
! !
!UUID methodsFor:'converting'!
asBytes
- ^ self asBytesMSB:(UninterpretedBytes isBigEndian)
-!
+ "convert this UUID to a ByteArray in network byte order (MSB-first)"
-asBytesMSB:msb
- |bytes d1 d2 d3|
+ |bytes|
bytes := ByteArray new:16.
bytes replaceFrom:1 to:16 with:self.
+ ^ bytes
- msb ifTrue:[
- d1 := self unsignedLongAt:1 bigEndian:false.
- d2 := self unsignedShortAt:1+4 bigEndian:false.
- d3 := self unsignedShortAt:1+4+2 bigEndian:false.
+ "
+ |bytes|
+
+ bytes := #[16r01 16r02 16r03 16r04
+ 16r05 16r06 16r07 16r08
+ 16r09 16r10 16r11 16r12
+ 16r13 16r14 16r15 16r16].
+ (UUID fromBytes:bytes) asBytes ~= bytes ifTrue:[self halt]
+ "
+!
- bytes unsignedLongAt:1 put:d1 bigEndian:true.
- bytes unsignedShortAt:1+4 put:d2 bigEndian:true.
- bytes unsignedShortAt:1+4+2 put:d3 bigEndian:true.
+asBytesMSB:msb
+ "convert this UUID to a ByteArray.
+ If msb == false, it is converted into LSB-first byte oredering"
+
+ |bytes|
+
+ bytes := self asBytes.
+
+ msb ifFalse:[
+ self class adjustByteOrder:bytes.
].
^ bytes
+!
+
+asNativeBytes
+ "convert this uuid to a ByteArray in host byte order.
+ Use this only to pass the UUID to the OS (Windows)"
+
+ |bytes|
+
+ bytes := self asBytes.
+ self class isBigEndian ifFalse:[
+ self class adjustByteOrder:bytes.
+ ].
+ ^ bytes.
! !
!UUID methodsFor:'generating uuids'!
@@ -350,30 +429,22 @@
!
printOn:aStream
- |offs d tmpStream|
+ |d tmpStream|
tmpStream := '' writeStream.
- d := self unsignedLongAt:1 bigEndian:false.
- d printOn:tmpStream base:16 size:8 fill:$0.
-
+ self timeLow printOn:tmpStream base:16 size:8 fill:$0.
+ tmpStream nextPut:$-.
+ self timeMid printOn:tmpStream base:16 size:4 fill:$0.
+ tmpStream nextPut:$-.
+ self timeHighAndVersion printOn:tmpStream base:16 size:4 fill:$0.
+ tmpStream nextPut:$-.
+ self clockSeqHiAndReserved printOn:tmpStream base:16 size:2 fill:$0.
+ self clockSeqLow printOn:tmpStream base:16 size:2 fill:$0.
tmpStream nextPut:$-.
- offs := 5.
- 2 timesRepeat:[
- d := self unsignedShortAt:offs bigEndian:false.
- offs := offs + 2.
- d printOn:tmpStream base:16 size:4 fill:$0.
- tmpStream nextPut:$-.
- ].
- d := self unsignedShortAt:offs bigEndian:true.
- offs := offs + 2.
- d printOn:tmpStream base:16 size:4 fill:$0.
- tmpStream nextPut:$-.
-
- 6 timesRepeat:[
- d := self at:offs.
- offs := offs + 1.
+ 11 to:16 do:[:idx|
+ d := self at:idx.
d printOn:tmpStream base:16 size:2 fill:$0.
].
@@ -383,7 +454,7 @@
!UUID class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic2/UUID.st,v 1.15 2006-02-20 12:53:54 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic2/UUID.st,v 1.16 2006-02-20 16:21:19 stefan Exp $'
! !
UUID initialize!