OLD | NEW |
| (Empty) |
1 #region Copyright notice and license | |
2 // Protocol Buffers - Google's data interchange format | |
3 // Copyright 2008 Google Inc. All rights reserved. | |
4 // https://developers.google.com/protocol-buffers/ | |
5 // | |
6 // Redistribution and use in source and binary forms, with or without | |
7 // modification, are permitted provided that the following conditions are | |
8 // met: | |
9 // | |
10 // * Redistributions of source code must retain the above copyright | |
11 // notice, this list of conditions and the following disclaimer. | |
12 // * Redistributions in binary form must reproduce the above | |
13 // copyright notice, this list of conditions and the following disclaimer | |
14 // in the documentation and/or other materials provided with the | |
15 // distribution. | |
16 // * Neither the name of Google Inc. nor the names of its | |
17 // contributors may be used to endorse or promote products derived from | |
18 // this software without specific prior written permission. | |
19 // | |
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 #endregion | |
32 | |
33 using System; | |
34 using System.Collections; | |
35 using System.Collections.Generic; | |
36 using System.IO; | |
37 using System.Text; | |
38 | |
39 namespace Google.Protobuf | |
40 { | |
41 /// <summary> | |
42 /// Immutable array of bytes. | |
43 /// </summary> | |
44 public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString> | |
45 { | |
46 private static readonly ByteString empty = new ByteString(new byte[0]); | |
47 | |
48 private readonly byte[] bytes; | |
49 | |
50 /// <summary> | |
51 /// Unsafe operations that can cause IO Failure and/or other catestrophi
c side-effects. | |
52 /// </summary> | |
53 public static class Unsafe | |
54 { | |
55 /// <summary> | |
56 /// Constructs a new ByteString from the given byte array. The array
is | |
57 /// *not* copied, and must not be modified after this constructor is
called. | |
58 /// </summary> | |
59 public static ByteString FromBytes(byte[] bytes) | |
60 { | |
61 return new ByteString(bytes); | |
62 } | |
63 | |
64 /// <summary> | |
65 /// Provides direct, unrestricted access to the bytes contained in t
his instance. | |
66 /// You must not modify or resize the byte array returned by this me
thod. | |
67 /// </summary> | |
68 public static byte[] GetBuffer(ByteString bytes) | |
69 { | |
70 return bytes.bytes; | |
71 } | |
72 } | |
73 | |
74 /// <summary> | |
75 /// Internal use only. Ensure that the provided array is not mutated an
d belongs to this instance. | |
76 /// </summary> | |
77 internal static ByteString AttachBytes(byte[] bytes) | |
78 { | |
79 return new ByteString(bytes); | |
80 } | |
81 | |
82 /// <summary> | |
83 /// Constructs a new ByteString from the given byte array. The array is | |
84 /// *not* copied, and must not be modified after this constructor is cal
led. | |
85 /// </summary> | |
86 private ByteString(byte[] bytes) | |
87 { | |
88 this.bytes = bytes; | |
89 } | |
90 | |
91 /// <summary> | |
92 /// Returns an empty ByteString. | |
93 /// </summary> | |
94 public static ByteString Empty | |
95 { | |
96 get { return empty; } | |
97 } | |
98 | |
99 /// <summary> | |
100 /// Returns the length of this ByteString in bytes. | |
101 /// </summary> | |
102 public int Length | |
103 { | |
104 get { return bytes.Length; } | |
105 } | |
106 | |
107 /// <summary> | |
108 /// Returns <c>true</c> if this byte string is empty, <c>false</c> other
wise. | |
109 /// </summary> | |
110 public bool IsEmpty | |
111 { | |
112 get { return Length == 0; } | |
113 } | |
114 | |
115 /// <summary> | |
116 /// Converts this <see cref="ByteString"/> into a byte array. | |
117 /// </summary> | |
118 /// <remarks>The data is copied - changes to the returned array will not
be reflected in this <c>ByteString</c>.</remarks> | |
119 /// <returns>A byte array with the same data as this <c>ByteString</c>.<
/returns> | |
120 public byte[] ToByteArray() | |
121 { | |
122 return (byte[]) bytes.Clone(); | |
123 } | |
124 | |
125 /// <summary> | |
126 /// Converts this <see cref="ByteString"/> into a standard base64 repres
entation. | |
127 /// </summary> | |
128 /// <returns>A base64 representation of this <c>ByteString</c>.</returns
> | |
129 public string ToBase64() | |
130 { | |
131 return Convert.ToBase64String(bytes); | |
132 } | |
133 | |
134 /// <summary> | |
135 /// Constructs a <see cref="ByteString" /> from the Base64 Encoded Strin
g. | |
136 /// </summary> | |
137 public static ByteString FromBase64(string bytes) | |
138 { | |
139 // By handling the empty string explicitly, we not only optimize but
we fix a | |
140 // problem on CF 2.0. See issue 61 for details. | |
141 return bytes == "" ? Empty : new ByteString(Convert.FromBase64String
(bytes)); | |
142 } | |
143 | |
144 /// <summary> | |
145 /// Constructs a <see cref="ByteString" /> from the given array. The con
tents | |
146 /// are copied, so further modifications to the array will not | |
147 /// be reflected in the returned ByteString. | |
148 /// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb
, ...)</c> form | |
149 /// which is primarily useful for testing. | |
150 /// </summary> | |
151 public static ByteString CopyFrom(params byte[] bytes) | |
152 { | |
153 return new ByteString((byte[]) bytes.Clone()); | |
154 } | |
155 | |
156 /// <summary> | |
157 /// Constructs a <see cref="ByteString" /> from a portion of a byte arra
y. | |
158 /// </summary> | |
159 public static ByteString CopyFrom(byte[] bytes, int offset, int count) | |
160 { | |
161 byte[] portion = new byte[count]; | |
162 ByteArray.Copy(bytes, offset, portion, 0, count); | |
163 return new ByteString(portion); | |
164 } | |
165 | |
166 /// <summary> | |
167 /// Creates a new <see cref="ByteString" /> by encoding the specified te
xt with | |
168 /// the given encoding. | |
169 /// </summary> | |
170 public static ByteString CopyFrom(string text, Encoding encoding) | |
171 { | |
172 return new ByteString(encoding.GetBytes(text)); | |
173 } | |
174 | |
175 /// <summary> | |
176 /// Creates a new <see cref="ByteString" /> by encoding the specified te
xt in UTF-8. | |
177 /// </summary> | |
178 public static ByteString CopyFromUtf8(string text) | |
179 { | |
180 return CopyFrom(text, Encoding.UTF8); | |
181 } | |
182 | |
183 /// <summary> | |
184 /// Retuns the byte at the given index. | |
185 /// </summary> | |
186 public byte this[int index] | |
187 { | |
188 get { return bytes[index]; } | |
189 } | |
190 | |
191 /// <summary> | |
192 /// Converts this <see cref="ByteString"/> into a string by applying the
given encoding. | |
193 /// </summary> | |
194 /// <remarks> | |
195 /// This method should only be used to convert binary data which was the
result of encoding | |
196 /// text with the given encoding. | |
197 /// </remarks> | |
198 /// <param name="encoding">The encoding to use to decode the binary data
into text.</param> | |
199 /// <returns>The result of decoding the binary data with the given decod
ing.</returns> | |
200 public string ToString(Encoding encoding) | |
201 { | |
202 return encoding.GetString(bytes, 0, bytes.Length); | |
203 } | |
204 | |
205 /// <summary> | |
206 /// Converts this <see cref="ByteString"/> into a string by applying the
UTF-8 encoding. | |
207 /// </summary> | |
208 /// <remarks> | |
209 /// This method should only be used to convert binary data which was the
result of encoding | |
210 /// text with UTF-8. | |
211 /// </remarks> | |
212 /// <returns>The result of decoding the binary data with the given decod
ing.</returns> | |
213 public string ToStringUtf8() | |
214 { | |
215 return ToString(Encoding.UTF8); | |
216 } | |
217 | |
218 /// <summary> | |
219 /// Returns an iterator over the bytes in this <see cref="ByteString"/>. | |
220 /// </summary> | |
221 /// <returns>An iterator over the bytes in this object.</returns> | |
222 public IEnumerator<byte> GetEnumerator() | |
223 { | |
224 return ((IEnumerable<byte>) bytes).GetEnumerator(); | |
225 } | |
226 | |
227 /// <summary> | |
228 /// Returns an iterator over the bytes in this <see cref="ByteString"/>. | |
229 /// </summary> | |
230 /// <returns>An iterator over the bytes in this object.</returns> | |
231 IEnumerator IEnumerable.GetEnumerator() | |
232 { | |
233 return GetEnumerator(); | |
234 } | |
235 | |
236 /// <summary> | |
237 /// Creates a CodedInputStream from this ByteString's data. | |
238 /// </summary> | |
239 public CodedInputStream CreateCodedInput() | |
240 { | |
241 // We trust CodedInputStream not to reveal the provided byte array o
r modify it | |
242 return new CodedInputStream(bytes); | |
243 } | |
244 | |
245 /// <summary> | |
246 /// Compares two byte strings for equality. | |
247 /// </summary> | |
248 /// <param name="lhs">The first byte string to compare.</param> | |
249 /// <param name="rhs">The second byte string to compare.</param> | |
250 /// <returns><c>true</c> if the byte strings are equal; false otherwise.
</returns> | |
251 public static bool operator ==(ByteString lhs, ByteString rhs) | |
252 { | |
253 if (ReferenceEquals(lhs, rhs)) | |
254 { | |
255 return true; | |
256 } | |
257 if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null)) | |
258 { | |
259 return false; | |
260 } | |
261 if (lhs.bytes.Length != rhs.bytes.Length) | |
262 { | |
263 return false; | |
264 } | |
265 for (int i = 0; i < lhs.Length; i++) | |
266 { | |
267 if (rhs.bytes[i] != lhs.bytes[i]) | |
268 { | |
269 return false; | |
270 } | |
271 } | |
272 return true; | |
273 } | |
274 | |
275 /// <summary> | |
276 /// Compares two byte strings for inequality. | |
277 /// </summary> | |
278 /// <param name="lhs">The first byte string to compare.</param> | |
279 /// <param name="rhs">The second byte string to compare.</param> | |
280 /// <returns><c>false</c> if the byte strings are equal; true otherwise.
</returns> | |
281 public static bool operator !=(ByteString lhs, ByteString rhs) | |
282 { | |
283 return !(lhs == rhs); | |
284 } | |
285 | |
286 /// <summary> | |
287 /// Compares this byte string with another object. | |
288 /// </summary> | |
289 /// <param name="obj">The object to compare this with.</param> | |
290 /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <s
ee cref="ByteString"/>; <c>false</c> otherwise.</returns> | |
291 public override bool Equals(object obj) | |
292 { | |
293 return this == (obj as ByteString); | |
294 } | |
295 | |
296 /// <summary> | |
297 /// Returns a hash code for this object. Two equal byte strings | |
298 /// will return the same hash code. | |
299 /// </summary> | |
300 /// <returns>A hash code for this object.</returns> | |
301 public override int GetHashCode() | |
302 { | |
303 int ret = 23; | |
304 foreach (byte b in bytes) | |
305 { | |
306 ret = (ret << 8) | b; | |
307 } | |
308 return ret; | |
309 } | |
310 | |
311 /// <summary> | |
312 /// Compares this byte string with another. | |
313 /// </summary> | |
314 /// <param name="other">The <see cref="ByteString"/> to compare this wit
h.</param> | |
315 /// <returns><c>true</c> if <paramref name="other"/> refers to an equal
byte string; <c>false</c> otherwise.</returns> | |
316 public bool Equals(ByteString other) | |
317 { | |
318 return this == other; | |
319 } | |
320 | |
321 /// <summary> | |
322 /// Used internally by CodedOutputStream to avoid creating a copy for th
e write | |
323 /// </summary> | |
324 internal void WriteRawBytesTo(CodedOutputStream outputStream) | |
325 { | |
326 outputStream.WriteRawBytes(bytes, 0, bytes.Length); | |
327 } | |
328 | |
329 /// <summary> | |
330 /// Copies the entire byte array to the destination array provided at th
e offset specified. | |
331 /// </summary> | |
332 public void CopyTo(byte[] array, int position) | |
333 { | |
334 ByteArray.Copy(bytes, 0, array, position, bytes.Length); | |
335 } | |
336 | |
337 /// <summary> | |
338 /// Writes the entire byte array to the provided stream | |
339 /// </summary> | |
340 public void WriteTo(Stream outputStream) | |
341 { | |
342 outputStream.Write(bytes, 0, bytes.Length); | |
343 } | |
344 } | |
345 } | |
OLD | NEW |