@@ -41,6 +41,17 @@ public struct ObjectId : IComparable<ObjectId>, IEquatable<ObjectId>, IConvertib
41
41
private readonly int _c ;
42
42
43
43
// constructors
44
+ /// <summary>
45
+ /// Initializes a new instance of the ObjectId class.
46
+ /// </summary>
47
+ /// <param name="a">First 32 bits</param>
48
+ /// <param name="b">Second 32 bits</param>
49
+ /// <param name="c">Third 32 bits</param>
50
+ private ObjectId ( int a , int b , int c )
51
+ {
52
+ _a = a ; _b = b ; _c = c ;
53
+ }
54
+
44
55
/// <summary>
45
56
/// Initializes a new instance of the ObjectId class.
46
57
/// </summary>
@@ -49,11 +60,11 @@ public ObjectId(byte[] bytes)
49
60
{
50
61
if ( bytes == null )
51
62
{
52
- throw new ArgumentNullException ( " bytes" ) ;
63
+ throw new ArgumentNullException ( nameof ( bytes ) ) ;
53
64
}
54
65
if ( bytes . Length != 12 )
55
66
{
56
- throw new ArgumentException ( "Byte array must be 12 bytes long" , " bytes" ) ;
67
+ throw new ArgumentException ( "Byte array must be 12 bytes long" , nameof ( bytes ) ) ;
57
68
}
58
69
59
70
FromByteArray ( bytes , 0 , out _a , out _b , out _c ) ;
@@ -92,16 +103,16 @@ public ObjectId(int timestamp, int machine, short pid, int increment)
92
103
{
93
104
if ( ( machine & 0xff000000 ) != 0 )
94
105
{
95
- throw new ArgumentOutOfRangeException ( " machine" , "The machine value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
106
+ throw new ArgumentOutOfRangeException ( nameof ( machine ) , "The machine value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
96
107
}
97
108
if ( ( increment & 0xff000000 ) != 0 )
98
109
{
99
- throw new ArgumentOutOfRangeException ( " increment" , "The increment value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
110
+ throw new ArgumentOutOfRangeException ( nameof ( increment ) , "The increment value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
100
111
}
101
112
102
113
_a = timestamp ;
103
- _b = ( machine << 8 ) | ( ( ( int ) pid >> 8 ) & 0xff ) ;
104
- _c = ( ( int ) pid << 24 ) | increment ;
114
+ _b = ( machine << 8 ) | ( ( pid >> 8 ) & 0xff ) ;
115
+ _c = ( pid << 24 ) | increment ;
105
116
}
106
117
107
118
/// <summary>
@@ -112,11 +123,13 @@ public ObjectId(string value)
112
123
{
113
124
if ( value == null )
114
125
{
115
- throw new ArgumentNullException ( " value" ) ;
126
+ throw new ArgumentNullException ( nameof ( value ) ) ;
116
127
}
117
128
118
- var bytes = BsonUtils . ParseHexString ( value ) ;
119
- FromByteArray ( bytes , 0 , out _a , out _b , out _c ) ;
129
+ if ( ! TryParse ( value , out _a , out _b , out _c ) )
130
+ {
131
+ throw new ArgumentException ( "String value is not valid." , nameof ( value ) ) ;
132
+ }
120
133
}
121
134
122
135
// public static properties
@@ -279,11 +292,11 @@ public static byte[] Pack(int timestamp, int machine, short pid, int increment)
279
292
{
280
293
if ( ( machine & 0xff000000 ) != 0 )
281
294
{
282
- throw new ArgumentOutOfRangeException ( " machine" , "The machine value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
295
+ throw new ArgumentOutOfRangeException ( nameof ( machine ) , "The machine value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
283
296
}
284
297
if ( ( increment & 0xff000000 ) != 0 )
285
298
{
286
- throw new ArgumentOutOfRangeException ( " increment" , "The increment value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
299
+ throw new ArgumentOutOfRangeException ( nameof ( increment ) , "The increment value must be between 0 and 16777215 (it must fit in 3 bytes)." ) ;
287
300
}
288
301
289
302
byte [ ] bytes = new byte [ 12 ] ;
@@ -311,7 +324,7 @@ public static ObjectId Parse(string s)
311
324
{
312
325
if ( s == null )
313
326
{
314
- throw new ArgumentNullException ( "s" ) ;
327
+ throw new ArgumentNullException ( nameof ( s ) ) ;
315
328
}
316
329
317
330
ObjectId objectId ;
@@ -335,14 +348,11 @@ public static ObjectId Parse(string s)
335
348
public static bool TryParse ( string s , out ObjectId objectId )
336
349
{
337
350
// don't throw ArgumentNullException if s is null
338
- if ( s != null && s . Length == 24 )
351
+ int a , b , c ;
352
+ if ( TryParse ( s , out a , out b , out c ) )
339
353
{
340
- byte [ ] bytes ;
341
- if ( BsonUtils . TryParseHexString ( s , out bytes ) )
342
- {
343
- objectId = new ObjectId ( bytes ) ;
344
- return true ;
345
- }
354
+ objectId = new ObjectId ( a , b , c ) ;
355
+ return true ;
346
356
}
347
357
348
358
objectId = default ( ObjectId ) ;
@@ -361,11 +371,11 @@ public static void Unpack(byte[] bytes, out int timestamp, out int machine, out
361
371
{
362
372
if ( bytes == null )
363
373
{
364
- throw new ArgumentNullException ( " bytes" ) ;
374
+ throw new ArgumentNullException ( nameof ( bytes ) ) ;
365
375
}
366
376
if ( bytes . Length != 12 )
367
377
{
368
- throw new ArgumentOutOfRangeException ( " bytes" , "Byte array must be 12 bytes long." ) ;
378
+ throw new ArgumentOutOfRangeException ( nameof ( bytes ) , "Byte array must be 12 bytes long." ) ;
369
379
}
370
380
371
381
timestamp = ( bytes [ 0 ] << 24 ) + ( bytes [ 1 ] << 16 ) + ( bytes [ 2 ] << 8 ) + bytes [ 3 ] ;
@@ -429,6 +439,38 @@ private static int GetTimestampFromDateTime(DateTime timestamp)
429
439
return ( int ) secondsSinceEpoch ;
430
440
}
431
441
442
+ private static bool TryParse ( string value , out int a , out int b , out int c )
443
+ {
444
+ a = 0 ; b = 0 ; c = 0 ;
445
+
446
+ if ( value == null || value . Length != 24 )
447
+ {
448
+ return false ;
449
+ }
450
+
451
+ var err = 0 ;
452
+
453
+ for ( int i = 0 ; i < 8 && err == 0 ; i ++ )
454
+ {
455
+ var ch = value [ i ] | 0x20 ;
456
+ var r = ( ch >= '0' && ch <= '9' ) ? ( ch - '0' ) : ( ch >= 'a' && ch <= 'f' ) ? ( ch - 'a' + 10 ) : 16 ;
457
+ a = ( a << 4 ) | ( r & 0x0F ) ;
458
+ err |= ( r & 0xF0 ) ;
459
+
460
+ ch = value [ i + 8 ] | 0x20 ;
461
+ r = ( ch >= '0' && ch <= '9' ) ? ( ch - '0' ) : ( ch >= 'a' && ch <= 'f' ) ? ( ch - 'a' + 10 ) : 16 ;
462
+ b = ( b << 4 ) | ( r & 0x0F ) ;
463
+ err |= ( r & 0xF0 ) ;
464
+
465
+ ch = value [ i + 16 ] | 0x20 ;
466
+ r = ( ch >= '0' && ch <= '9' ) ? ( ch - '0' ) : ( ch >= 'a' && ch <= 'f' ) ? ( ch - 'a' + 10 ) : 16 ;
467
+ c = ( c << 4 ) | ( r & 0x0F ) ;
468
+ err |= ( r & 0xF0 ) ;
469
+ }
470
+
471
+ return err == 0 ;
472
+ }
473
+
432
474
private static void FromByteArray ( byte [ ] bytes , int offset , out int a , out int b , out int c )
433
475
{
434
476
a = ( bytes [ offset ] << 24 ) | ( bytes [ offset + 1 ] << 16 ) | ( bytes [ offset + 2 ] << 8 ) | bytes [ offset + 3 ] ;
@@ -471,14 +513,7 @@ public bool Equals(ObjectId rhs)
471
513
/// <returns>True if the other object is an ObjectId and equal to this one.</returns>
472
514
public override bool Equals ( object obj )
473
515
{
474
- if ( obj is ObjectId )
475
- {
476
- return Equals ( ( ObjectId ) obj ) ;
477
- }
478
- else
479
- {
480
- return false ;
481
- }
516
+ return obj is ObjectId && Equals ( ( ObjectId ) obj ) ;
482
517
}
483
518
484
519
/// <summary>
@@ -514,11 +549,11 @@ public void ToByteArray(byte[] destination, int offset)
514
549
{
515
550
if ( destination == null )
516
551
{
517
- throw new ArgumentNullException ( " destination" ) ;
552
+ throw new ArgumentNullException ( nameof ( destination ) ) ;
518
553
}
519
554
if ( offset + 12 > destination . Length )
520
555
{
521
- throw new ArgumentException ( "Not enough room in destination buffer." , " offset" ) ;
556
+ throw new ArgumentException ( "Not enough room in destination buffer." , nameof ( offset ) ) ;
522
557
}
523
558
524
559
destination [ offset + 0 ] = ( byte ) ( _a >> 24 ) ;
@@ -541,7 +576,24 @@ public void ToByteArray(byte[] destination, int offset)
541
576
/// <returns>A string representation of the value.</returns>
542
577
public override string ToString ( )
543
578
{
544
- return BsonUtils . ToHexString ( ToByteArray ( ) ) ;
579
+ var buffer = new char [ 24 ] ;
580
+
581
+ for ( int i = 7 , a = _a , b = _b , c = _c ; i >= 0 ; i -- )
582
+ {
583
+ var r = ( a & 0x0F ) ;
584
+ buffer [ i ] = ( char ) ( r < 10 ? ( r + '0' ) : ( r - 10 + 'a' ) ) ;
585
+ a >>= 4 ;
586
+
587
+ r = ( b & 0x0F ) ;
588
+ buffer [ i + 8 ] = ( char ) ( r < 10 ? ( r + '0' ) : ( r - 10 + 'a' ) ) ;
589
+ b >>= 4 ;
590
+
591
+ r = ( c & 0x0F ) ;
592
+ buffer [ i + 16 ] = ( char ) ( r < 10 ? ( r + '0' ) : ( r - 10 + 'a' ) ) ;
593
+ c >>= 4 ;
594
+ }
595
+
596
+ return new string ( buffer ) ;
545
597
}
546
598
547
599
// explicit IConvertible implementation
0 commit comments