1a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// Protocol Buffers - Google's data interchange format
2a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// Copyright 2008 Google Inc.  All rights reserved.
3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson// https://developers.google.com/protocol-buffers/
4a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson//
5a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// Redistribution and use in source and binary forms, with or without
6a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// modification, are permitted provided that the following conditions are
7a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// met:
8a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson//
9a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson//     * Redistributions of source code must retain the above copyright
10a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// notice, this list of conditions and the following disclaimer.
11a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson//     * Redistributions in binary form must reproduce the above
12a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// copyright notice, this list of conditions and the following disclaimer
13a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// in the documentation and/or other materials provided with the
14a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// distribution.
15a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson//     * Neither the name of Google Inc. nor the names of its
16a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// contributors may be used to endorse or promote products derived from
17a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// this software without specific prior written permission.
18a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson//
19a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
31a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonpackage com.google.protobuf;
32a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
33a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.AbstractList;
34a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.ArrayList;
35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Arrays;
36a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.Collection;
37a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.Collections;
38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.List;
39a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.RandomAccess;
40a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
41a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson/**
42a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * An implementation of {@link LazyStringList} that wraps an ArrayList. Each
43a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * element is one of String, ByteString, or byte[]. It caches the last one
44a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * requested which is most likely the one needed next. This minimizes memory
45a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * usage while satisfying the most common use cases.
46a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * <p>
47a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * <strong>Note that this implementation is not synchronized.</strong>
48a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
49a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * and at least one of the threads modifies the list structurally, it
50a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * <i>must</i> be synchronized externally.  (A structural modification is
51a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * any operation that adds or deletes one or more elements, or explicitly
52a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * resizes the backing array; merely setting the value of an element is not
53a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * a structural modification.)  This is typically accomplished by
54a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * synchronizing on some object that naturally encapsulates the list.
55a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * <p>
56a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * If the implementation is accessed via concurrent reads, this is thread safe.
57a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * Conversions are done in a thread safe manner. It's possible that the
58a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * conversion may happen more than once if two threads attempt to access the
59a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * same element and the modifications were not visible to each other, but this
60a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * will not result in any corruption of the list or change in behavior other
61a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * than performance.
62a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson *
63a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * @author jonp@google.com (Jon Perlow)
64a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson */
65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpublic class LazyStringArrayList extends AbstractProtobufList<String>
66a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    implements LazyStringList, RandomAccess {
67a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList();
69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static {
70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    EMPTY_LIST.makeImmutable();
71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static LazyStringArrayList emptyList() {
74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return EMPTY_LIST;
75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // For compatibility with older runtimes.
78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public static final LazyStringList EMPTY = EMPTY_LIST;
79a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
80a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private final List<Object> list;
81a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
82a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public LazyStringArrayList() {
83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this(DEFAULT_CAPACITY);
84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public LazyStringArrayList(int intialCapacity) {
87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this(new ArrayList<Object>(intialCapacity));
88a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
89a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
90a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public LazyStringArrayList(LazyStringList from) {
91a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    list = new ArrayList<Object>(from.size());
92a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    addAll(from);
93a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
94a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
95a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public LazyStringArrayList(List<String> from) {
96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this(new ArrayList<Object>(from));
97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private LazyStringArrayList(ArrayList<Object> list) {
100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this.list = list;
101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public LazyStringArrayList mutableCopyWithCapacity(int capacity) {
105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (capacity < size()) {
106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw new IllegalArgumentException();
107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ArrayList<Object> newList = new ArrayList<Object>(capacity);
109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    newList.addAll(list);
110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new LazyStringArrayList(newList);
111a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
112a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
113a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
114a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public String get(int index) {
115a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Object o = list.get(index);
116a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (o instanceof String) {
117a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return (String) o;
118a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (o instanceof ByteString) {
119a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ByteString bs = (ByteString) o;
120a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      String s = bs.toStringUtf8();
121a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bs.isValidUtf8()) {
122a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        list.set(index, s);
123a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
124a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return s;
125a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
126a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      byte[] ba = (byte[]) o;
127a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      String s = Internal.toStringUtf8(ba);
128a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (Internal.isValidUtf8(ba)) {
129a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        list.set(index, s);
130a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
131a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return s;
132a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
133a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
134a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
135a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
136a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public int size() {
137a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return list.size();
138a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
139a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
140a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
141a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public String set(int index, String s) {
142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
143a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Object o = list.set(index, s);
144a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return asString(o);
145a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
146a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
147a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
148a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void add(int index, String element) {
149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    list.add(index, element);
151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    modCount++;
152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private void add(int index, ByteString element) {
155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    list.add(index, element);
157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    modCount++;
158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private void add(int index, byte[] element) {
161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
162a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    list.add(index, element);
163a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
164a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
165a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
166a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
167a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public boolean addAll(Collection<? extends String> c) {
168a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // The default implementation of AbstractCollection.addAll(Collection)
169a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // delegates to add(Object). This implementation instead delegates to
170a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // addAll(int, Collection), which makes a special case for Collections
171a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // which are instances of LazyStringList.
172a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return addAll(size(), c);
173a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
174a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
175a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
176a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public boolean addAll(int index, Collection<? extends String> c) {
177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
178a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // When copying from another LazyStringList, directly copy the underlying
179a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // elements rather than forcing each element to be decoded to a String.
180a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Collection<?> collection = c instanceof LazyStringList
181a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        ? ((LazyStringList) c).getUnderlyingElements() : c;
182a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    boolean ret = list.addAll(index, collection);
183a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
184a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return ret;
185a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
186a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
188a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public boolean addAllByteString(Collection<? extends ByteString> values) {
189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
190a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    boolean ret = list.addAll(values);
191a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
192a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return ret;
193a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
194a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
196a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public boolean addAllByteArray(Collection<byte[]> c) {
197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
198a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    boolean ret = list.addAll(c);
199a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
200a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return ret;
201a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
202a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
203a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
204a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public String remove(int index) {
205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
206a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Object o = list.remove(index);
207a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
208a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return asString(o);
209a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
210a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
211a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
212a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void clear() {
213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
214a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    list.clear();
215a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
216a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
217a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
219a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void add(ByteString element) {
220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
221a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    list.add(element);
222a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
223a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
224a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
226a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void add(byte[] element) {
227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
228a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    list.add(element);
229a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    modCount++;
230a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
231a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public Object getRaw(int index) {
234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return list.get(index);
235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
238a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public ByteString getByteString(int index) {
239a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Object o = list.get(index);
240a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    ByteString b = asByteString(o);
241a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (b != o) {
242a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      list.set(index, b);
243a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
244a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return b;
245a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
246a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
248a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public byte[] getByteArray(int index) {
249a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Object o = list.get(index);
250a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    byte[] b = asByteArray(o);
251a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (b != o) {
252a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      list.set(index, b);
253a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
254a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return b;
255a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
256a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
258a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void set(int index, ByteString s) {
259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    setAndReturn(index, s);
260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private Object setAndReturn(int index, ByteString s) {
263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return list.set(index, s);
265a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
266a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
268a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void set(int index, byte[] s) {
269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    setAndReturn(index, s);
270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private Object setAndReturn(int index, byte[] s) {
273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return list.set(index, s);
275a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
276a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
277a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private static String asString(Object o) {
278a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (o instanceof String) {
279a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return (String) o;
280a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (o instanceof ByteString) {
281a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return ((ByteString) o).toStringUtf8();
282a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
283a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return Internal.toStringUtf8((byte[]) o);
284a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
285a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
286a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
287a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private static ByteString asByteString(Object o) {
288a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (o instanceof ByteString) {
289a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return (ByteString) o;
290a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (o instanceof String) {
291a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return ByteString.copyFromUtf8((String) o);
292a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
293a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return ByteString.copyFrom((byte[]) o);
294a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
295a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
296a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
297a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private static byte[] asByteArray(Object o) {
298a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (o instanceof byte[]) {
299a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return (byte[]) o;
300a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (o instanceof String) {
301a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return Internal.toByteArray((String) o);
302a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
303a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return ((ByteString) o).toByteArray();
304a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
305a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
306a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
308a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public List<?> getUnderlyingElements() {
309a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return Collections.unmodifiableList(list);
310a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
311a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
313a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void mergeFrom(LazyStringList other) {
314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureIsMutable();
315a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    for (Object o : other.getUnderlyingElements()) {
316a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (o instanceof byte[]) {
317a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        byte[] b = (byte[]) o;
318a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // Byte array's content is mutable so they should be copied rather than
319a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // shared when merging from one message to another.
320a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        list.add(Arrays.copyOf(b, b.length));
321a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else {
322a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        list.add(o);
323a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
324a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
325a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
326a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
327a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private static class ByteArrayListView extends AbstractList<byte[]>
328a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      implements RandomAccess {
329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    private final LazyStringArrayList list;
330a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ByteArrayListView(LazyStringArrayList list) {
332a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      this.list = list;
333a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
334a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
335a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
336a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public byte[] get(int index) {
337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return list.getByteArray(index);
338a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
339a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
340a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
341a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public int size() {
342a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return list.size();
343a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
344a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
345a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
346a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public byte[] set(int index, byte[] s) {
347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      Object o = list.setAndReturn(index, s);
348a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      modCount++;
349a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return asByteArray(o);
350a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
351a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
352a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
353a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public void add(int index, byte[] s) {
354a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      list.add(index, s);
355a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      modCount++;
356a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
357a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
358a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
359a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public byte[] remove(int index) {
360a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      Object o = list.remove(index);
361a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      modCount++;
362a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return asByteArray(o);
363a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
364a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
365a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
367a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public List<byte[]> asByteArrayList() {
368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new ByteArrayListView(this);
369a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
370a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
371a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private static class ByteStringListView extends AbstractList<ByteString>
372a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      implements RandomAccess {
373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    private final LazyStringArrayList list;
374a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ByteStringListView(LazyStringArrayList list) {
376a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      this.list = list;
377a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
378a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
379a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
380a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public ByteString get(int index) {
381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return list.getByteString(index);
382a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
383a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
384a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
385a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public int size() {
386a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return list.size();
387a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
388a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
389a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
390a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public ByteString set(int index, ByteString s) {
391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      Object o = list.setAndReturn(index, s);
392a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      modCount++;
393a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return asByteString(o);
394a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
395a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
396a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
397a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public void add(int index, ByteString s) {
398a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      list.add(index, s);
399a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      modCount++;
400a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
401a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
402a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
403a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public ByteString remove(int index) {
404a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      Object o = list.remove(index);
405a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      modCount++;
406a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return asByteString(o);
407a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
408a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
409a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
411a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public List<ByteString> asByteStringList() {
412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new ByteStringListView(this);
413a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
414a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
416a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public LazyStringList getUnmodifiableView() {
417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (isModifiable()) {
418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return new UnmodifiableLazyStringList(this);
419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return this;
421a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
422a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
423a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson}
424