| 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 |