OLD | NEW |
1 #region Copyright notice and license | 1 #region Copyright notice and license |
2 // Protocol Buffers - Google's data interchange format | 2 // Protocol Buffers - Google's data interchange format |
3 // Copyright 2015 Google Inc. All rights reserved. | 3 // Copyright 2015 Google Inc. All rights reserved. |
4 // https://developers.google.com/protocol-buffers/ | 4 // https://developers.google.com/protocol-buffers/ |
5 // | 5 // |
6 // Redistribution and use in source and binary forms, with or without | 6 // Redistribution and use in source and binary forms, with or without |
7 // modification, are permitted provided that the following conditions are | 7 // modification, are permitted provided that the following conditions are |
8 // met: | 8 // met: |
9 // | 9 // |
10 // * Redistributions of source code must retain the above copyright | 10 // * Redistributions of source code must retain the above copyright |
(...skipping 16 matching lines...) Expand all Loading... |
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 #endregion | 31 #endregion |
32 | 32 |
33 using System; | 33 using System; |
34 using System.Collections; | 34 using System.Collections; |
35 using System.Collections.Generic; | 35 using System.Collections.Generic; |
36 using System.IO; | 36 using System.IO; |
37 using System.Text; | |
38 | 37 |
39 namespace Google.Protobuf.Collections | 38 namespace Google.Protobuf.Collections |
40 { | 39 { |
41 /// <summary> | 40 /// <summary> |
42 /// The contents of a repeated field: essentially, a collection with some ex
tra | 41 /// The contents of a repeated field: essentially, a collection with some ex
tra |
43 /// restrictions (no null values) and capabilities (deep cloning). | 42 /// restrictions (no null values) and capabilities (deep cloning). |
44 /// </summary> | 43 /// </summary> |
45 /// <remarks> | 44 /// <remarks> |
46 /// This implementation does not generally prohibit the use of types which a
re not | 45 /// This implementation does not generally prohibit the use of types which a
re not |
47 /// supported by Protocol Buffers but nor does it guarantee that all operati
ons will work in such cases. | 46 /// supported by Protocol Buffers but nor does it guarantee that all operati
ons will work in such cases. |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 array = tmp; | 219 array = tmp; |
221 } | 220 } |
222 } | 221 } |
223 | 222 |
224 /// <summary> | 223 /// <summary> |
225 /// Adds the specified item to the collection. | 224 /// Adds the specified item to the collection. |
226 /// </summary> | 225 /// </summary> |
227 /// <param name="item">The item to add.</param> | 226 /// <param name="item">The item to add.</param> |
228 public void Add(T item) | 227 public void Add(T item) |
229 { | 228 { |
230 if (item == null) | 229 ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); |
231 { | |
232 throw new ArgumentNullException("item"); | |
233 } | |
234 EnsureSize(count + 1); | 230 EnsureSize(count + 1); |
235 array[count++] = item; | 231 array[count++] = item; |
236 } | 232 } |
237 | 233 |
238 /// <summary> | 234 /// <summary> |
239 /// Removes all items from the collection. | 235 /// Removes all items from the collection. |
240 /// </summary> | 236 /// </summary> |
241 public void Clear() | 237 public void Clear() |
242 { | 238 { |
243 array = EmptyArray; | 239 array = EmptyArray; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 } | 274 } |
279 Array.Copy(array, index + 1, array, index, count - index - 1); | 275 Array.Copy(array, index + 1, array, index, count - index - 1); |
280 count--; | 276 count--; |
281 array[count] = default(T); | 277 array[count] = default(T); |
282 return true; | 278 return true; |
283 } | 279 } |
284 | 280 |
285 /// <summary> | 281 /// <summary> |
286 /// Gets the number of elements contained in the collection. | 282 /// Gets the number of elements contained in the collection. |
287 /// </summary> | 283 /// </summary> |
288 public int Count { get { return count; } } | 284 public int Count => count; |
289 | 285 |
290 /// <summary> | 286 /// <summary> |
291 /// Gets a value indicating whether the collection is read-only. | 287 /// Gets a value indicating whether the collection is read-only. |
292 /// </summary> | 288 /// </summary> |
293 public bool IsReadOnly { get { return false; } } | 289 public bool IsReadOnly => false; |
294 | |
295 // TODO: Remove this overload and just handle it in the one below, at ex
ecution time? | |
296 | 290 |
297 /// <summary> | 291 /// <summary> |
298 /// Adds all of the specified values into this collection. | 292 /// Adds all of the specified values into this collection. |
299 /// </summary> | 293 /// </summary> |
300 /// <param name="values">The values to add to this collection.</param> | 294 /// <param name="values">The values to add to this collection.</param> |
301 public void Add(RepeatedField<T> values) | 295 public void AddRange(IEnumerable<T> values) |
302 { | 296 { |
303 if (values == null) | 297 ProtoPreconditions.CheckNotNull(values, nameof(values)); |
| 298 |
| 299 // Optimization 1: If the collection we're adding is already a Repea
tedField<T>, |
| 300 // we know the values are valid. |
| 301 var otherRepeatedField = values as RepeatedField<T>; |
| 302 if (otherRepeatedField != null) |
304 { | 303 { |
305 throw new ArgumentNullException("values"); | 304 EnsureSize(count + otherRepeatedField.count); |
| 305 Array.Copy(otherRepeatedField.array, 0, array, count, otherRepea
tedField.count); |
| 306 count += otherRepeatedField.count; |
| 307 return; |
306 } | 308 } |
307 EnsureSize(count + values.count); | |
308 // We know that all the values will be valid, because it's a Repeate
dField. | |
309 Array.Copy(values.array, 0, array, count, values.count); | |
310 count += values.count; | |
311 } | |
312 | 309 |
313 /// <summary> | 310 // Optimization 2: The collection is an ICollection, so we can expan
d |
314 /// Adds all of the specified values into this collection. | 311 // just once and ask the collection to copy itself into the array. |
315 /// </summary> | 312 var collection = values as ICollection; |
316 /// <param name="values">The values to add to this collection.</param> | 313 if (collection != null) |
317 public void Add(IEnumerable<T> values) | |
318 { | |
319 if (values == null) | |
320 { | 314 { |
321 throw new ArgumentNullException("values"); | 315 var extraCount = collection.Count; |
| 316 // For reference types and nullable value types, we need to chec
k that there are no nulls |
| 317 // present. (This isn't a thread-safe approach, but we don't adv
ertise this is thread-safe.) |
| 318 // We expect the JITter to optimize this test to true/false, so
it's effectively conditional |
| 319 // specialization. |
| 320 if (default(T) == null) |
| 321 { |
| 322 // TODO: Measure whether iterating once to check and then le
tting the collection copy |
| 323 // itself is faster or slower than iterating and adding as w
e go. For large |
| 324 // collections this will not be great in terms of cache usag
e... but the optimized |
| 325 // copy may be significantly faster than doing it one at a t
ime. |
| 326 foreach (var item in collection) |
| 327 { |
| 328 if (item == null) |
| 329 { |
| 330 throw new ArgumentException("Sequence contained null
element", nameof(values)); |
| 331 } |
| 332 } |
| 333 } |
| 334 EnsureSize(count + extraCount); |
| 335 collection.CopyTo(array, count); |
| 336 count += extraCount; |
| 337 return; |
322 } | 338 } |
323 // TODO: Check for ICollection and get the Count, to optimize? | 339 |
| 340 // We *could* check for ICollection<T> as well, but very very few co
llections implement |
| 341 // ICollection<T> but not ICollection. (HashSet<T> does, for one...) |
| 342 |
| 343 // Fall back to a slower path of adding items one at a time. |
324 foreach (T item in values) | 344 foreach (T item in values) |
325 { | 345 { |
326 Add(item); | 346 Add(item); |
327 } | 347 } |
328 } | 348 } |
329 | 349 |
330 /// <summary> | 350 /// <summary> |
| 351 /// Adds all of the specified values into this collection. This method i
s present to |
| 352 /// allow repeated fields to be constructed from queries within collecti
on initializers. |
| 353 /// Within non-collection-initializer code, consider using the equivalen
t <see cref="AddRange"/> |
| 354 /// method instead for clarity. |
| 355 /// </summary> |
| 356 /// <param name="values">The values to add to this collection.</param> |
| 357 public void Add(IEnumerable<T> values) |
| 358 { |
| 359 AddRange(values); |
| 360 } |
| 361 |
| 362 /// <summary> |
331 /// Returns an enumerator that iterates through the collection. | 363 /// Returns an enumerator that iterates through the collection. |
332 /// </summary> | 364 /// </summary> |
333 /// <returns> | 365 /// <returns> |
334 /// An enumerator that can be used to iterate through the collection. | 366 /// An enumerator that can be used to iterate through the collection. |
335 /// </returns> | 367 /// </returns> |
336 public IEnumerator<T> GetEnumerator() | 368 public IEnumerator<T> GetEnumerator() |
337 { | 369 { |
338 for (int i = 0; i < count; i++) | 370 for (int i = 0; i < count; i++) |
339 { | 371 { |
340 yield return array[i]; | 372 yield return array[i]; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 } | 443 } |
412 | 444 |
413 /// <summary> | 445 /// <summary> |
414 /// Returns the index of the given item within the collection, or -1 if
the item is not | 446 /// Returns the index of the given item within the collection, or -1 if
the item is not |
415 /// present. | 447 /// present. |
416 /// </summary> | 448 /// </summary> |
417 /// <param name="item">The item to find in the collection.</param> | 449 /// <param name="item">The item to find in the collection.</param> |
418 /// <returns>The zero-based index of the item, or -1 if it is not found.
</returns> | 450 /// <returns>The zero-based index of the item, or -1 if it is not found.
</returns> |
419 public int IndexOf(T item) | 451 public int IndexOf(T item) |
420 { | 452 { |
421 if (item == null) | 453 ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); |
422 { | |
423 throw new ArgumentNullException("item"); | |
424 } | |
425 EqualityComparer<T> comparer = EqualityComparer<T>.Default; | 454 EqualityComparer<T> comparer = EqualityComparer<T>.Default; |
426 for (int i = 0; i < count; i++) | 455 for (int i = 0; i < count; i++) |
427 { | 456 { |
428 if (comparer.Equals(array[i], item)) | 457 if (comparer.Equals(array[i], item)) |
429 { | 458 { |
430 return i; | 459 return i; |
431 } | 460 } |
432 } | 461 } |
433 return -1; | 462 return -1; |
434 } | 463 } |
435 | 464 |
436 /// <summary> | 465 /// <summary> |
437 /// Inserts the given item at the specified index. | 466 /// Inserts the given item at the specified index. |
438 /// </summary> | 467 /// </summary> |
439 /// <param name="index">The index at which to insert the item.</param> | 468 /// <param name="index">The index at which to insert the item.</param> |
440 /// <param name="item">The item to insert.</param> | 469 /// <param name="item">The item to insert.</param> |
441 public void Insert(int index, T item) | 470 public void Insert(int index, T item) |
442 { | 471 { |
443 if (item == null) | 472 ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); |
444 { | |
445 throw new ArgumentNullException("item"); | |
446 } | |
447 if (index < 0 || index > count) | 473 if (index < 0 || index > count) |
448 { | 474 { |
449 throw new ArgumentOutOfRangeException("index"); | 475 throw new ArgumentOutOfRangeException(nameof(index)); |
450 } | 476 } |
451 EnsureSize(count + 1); | 477 EnsureSize(count + 1); |
452 Array.Copy(array, index, array, index + 1, count - index); | 478 Array.Copy(array, index, array, index + 1, count - index); |
453 array[index] = item; | 479 array[index] = item; |
454 count++; | 480 count++; |
455 } | 481 } |
456 | 482 |
457 /// <summary> | 483 /// <summary> |
458 /// Removes the item at the given index. | 484 /// Removes the item at the given index. |
459 /// </summary> | 485 /// </summary> |
460 /// <param name="index">The zero-based index of the item to remove.</par
am> | 486 /// <param name="index">The zero-based index of the item to remove.</par
am> |
461 public void RemoveAt(int index) | 487 public void RemoveAt(int index) |
462 { | 488 { |
463 if (index < 0 || index >= count) | 489 if (index < 0 || index >= count) |
464 { | 490 { |
465 throw new ArgumentOutOfRangeException("index"); | 491 throw new ArgumentOutOfRangeException(nameof(index)); |
466 } | 492 } |
467 Array.Copy(array, index + 1, array, index, count - index - 1); | 493 Array.Copy(array, index + 1, array, index, count - index - 1); |
468 count--; | 494 count--; |
469 array[count] = default(T); | 495 array[count] = default(T); |
470 } | 496 } |
471 | 497 |
472 /// <summary> | 498 /// <summary> |
473 /// Returns a string representation of this repeated field, in the same | 499 /// Returns a string representation of this repeated field, in the same |
474 /// way as it would be represented by the default JSON formatter. | 500 /// way as it would be represented by the default JSON formatter. |
475 /// </summary> | 501 /// </summary> |
(...skipping 11 matching lines...) Expand all Loading... |
487 /// The element at the specified index. | 513 /// The element at the specified index. |
488 /// </value> | 514 /// </value> |
489 /// <param name="index">The zero-based index of the element to get or se
t.</param> | 515 /// <param name="index">The zero-based index of the element to get or se
t.</param> |
490 /// <returns>The item at the specified index.</returns> | 516 /// <returns>The item at the specified index.</returns> |
491 public T this[int index] | 517 public T this[int index] |
492 { | 518 { |
493 get | 519 get |
494 { | 520 { |
495 if (index < 0 || index >= count) | 521 if (index < 0 || index >= count) |
496 { | 522 { |
497 throw new ArgumentOutOfRangeException("index"); | 523 throw new ArgumentOutOfRangeException(nameof(index)); |
498 } | 524 } |
499 return array[index]; | 525 return array[index]; |
500 } | 526 } |
501 set | 527 set |
502 { | 528 { |
503 if (index < 0 || index >= count) | 529 if (index < 0 || index >= count) |
504 { | 530 { |
505 throw new ArgumentOutOfRangeException("index"); | 531 throw new ArgumentOutOfRangeException(nameof(index)); |
506 } | 532 } |
507 if (value == null) | 533 ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value
)); |
508 { | |
509 throw new ArgumentNullException("value"); | |
510 } | |
511 array[index] = value; | 534 array[index] = value; |
512 } | 535 } |
513 } | 536 } |
514 | 537 |
515 #region Explicit interface implementation for IList and ICollection. | 538 #region Explicit interface implementation for IList and ICollection. |
516 bool IList.IsFixedSize { get { return false; } } | 539 bool IList.IsFixedSize => false; |
517 | 540 |
518 void ICollection.CopyTo(Array array, int index) | 541 void ICollection.CopyTo(Array array, int index) |
519 { | 542 { |
520 Array.Copy(this.array, 0, array, index, count); | 543 Array.Copy(this.array, 0, array, index, count); |
521 } | 544 } |
522 | 545 |
523 bool ICollection.IsSynchronized { get { return false; } } | 546 bool ICollection.IsSynchronized => false; |
524 | 547 |
525 object ICollection.SyncRoot { get { return this; } } | 548 object ICollection.SyncRoot => this; |
526 | 549 |
527 object IList.this[int index] | 550 object IList.this[int index] |
528 { | 551 { |
529 get { return this[index]; } | 552 get { return this[index]; } |
530 set { this[index] = (T)value; } | 553 set { this[index] = (T)value; } |
531 } | 554 } |
532 | 555 |
533 int IList.Add(object value) | 556 int IList.Add(object value) |
534 { | 557 { |
535 Add((T) value); | 558 Add((T) value); |
(...skipping 23 matching lines...) Expand all Loading... |
559 { | 582 { |
560 if (!(value is T)) | 583 if (!(value is T)) |
561 { | 584 { |
562 return; | 585 return; |
563 } | 586 } |
564 Remove((T)value); | 587 Remove((T)value); |
565 } | 588 } |
566 #endregion | 589 #endregion |
567 } | 590 } |
568 } | 591 } |
OLD | NEW |