-
Notifications
You must be signed in to change notification settings - Fork 1
/
MongoOid.cs
158 lines (120 loc) · 4.22 KB
/
MongoOid.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
using System.Text.RegularExpressions;
using System.Threading;
using System.Text;
using CSMongo.IO;
using CSMongo.Exceptions;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Net;
using System.Diagnostics;
namespace CSMongo {
/// <summary>
/// Represents an ID number to use for MongoOids
/// </summary>
public class MongoOid {
#region Constants
/// <summary>
/// The number of bytes to expect from a MongoOid
/// </summary>
public static readonly int MongoOidByteLength = 12;
#endregion
#region Constructors
/// <summary>
/// Creates a new Oid and generates an Oid automatically
/// </summary>
public MongoOid() {
this.Value = MongoOid.Generate();
}
/// <summary>
/// Creates an ID using a string version of the Oid
/// </summary>
public MongoOid(string id) {
this.SetId(id);
}
/// <summary>
/// Creates an new Oid with the provided bytes - Must be 12 bytes long
/// </summary>
public MongoOid(byte[] identifier) {
this.Value = identifier;
}
#endregion
#region Static Fields
//holds the current incremented value
private static int _Identifier = 0;
#endregion
#region Static Methods
//handles getting access to a shared identifier
private static int _GetIdentifier() {
return Interlocked.Increment(ref MongoOid._Identifier);
}
#endregion
#region Properties
/// <summary>
/// The byte value of the identifier
/// </summary>
public byte[] Value { get; private set; }
/// <summary>
/// Sets the ID to a specific value using a set of bytes
/// </summary>
public void SetId(byte[] value) {
this.Value = value;
}
/// <summary>
/// Converts a string into an ID - IDs should be a hexadecimal string
/// that is either 35 characters (with hyphens) or 24 characters without
/// </summary>
public void SetId(string value) {
//clean up the string first
value = Regex.Replace(value, "[^a-z0-9]", string.Empty, RegexOptions.IgnoreCase);
//verify the length
if (value.Length != 24) {
throw new ArgumentException("The provided ID was not in an expected format.", "value");
}
//parse every pair of bytes
List<byte> bytes = new List<byte>();
for (int i = 0; i < value.Length; i += 2) {
string pair = value.Substring(i, 2);
byte parsed = byte.Parse(pair, NumberStyles.HexNumber);
bytes.Add(parsed);
}
//and then assign normally
this.SetId(bytes.ToArray());
}
/// <summary>
/// Returns a string version of this ID
/// </summary>
public string GetId() {
return BitConverter.ToString(this.Value)
.Replace("-", string.Empty)
.ToLower();
}
#endregion
#region Overriding Methods
/// <summary>
/// Returns the string format of the Oid
/// </summary>
public override string ToString() {
return string.Format("Oid:{0}", this.GetId());
}
#endregion
#region Static Creation
/// <summary>
/// Generates the bytes for a new MongoOid
/// </summary>
public static byte[] Generate() {
List<byte> bytes = new List<byte>();
//generate the correct prefix (Suggestion from Sam Corder)
double span = (DateTime.UtcNow - Mongo.Epoch).TotalSeconds;
int floor = Convert.ToInt32(Math.Floor(span));
bytes.AddRange(BitConverter.GetBytes(floor).Reverse());
//use a semi-unique value - Not sure if this
//is supposed to be any paticular format
bytes.AddRange(Guid.NewGuid().ToByteArray().Skip(8));
return bytes.ToArray();
}
#endregion
}
}