13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/*
23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2014 Square, Inc.
33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License.
63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at
73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software
113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and
143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License.
153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage okio;
173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/**
19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * A segment of a buffer.
203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
21a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * <p>Each segment in a buffer is a circularly-linked list node referencing the following and
22a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * preceding segments in the buffer.
233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
24a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * <p>Each segment in the pool is a singly-linked list node referencing the rest of segments in the
25a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * pool.
26a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller *
27a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * <p>The underlying byte arrays of segments may be shared between buffers and byte strings. When a
28a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * segment's byte array is shared the segment may not be recycled, nor may its byte data be changed.
29a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * The lone exception is that the owner segment is allowed to append to the segment, writing data at
30a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * {@code limit} and beyond. There is a single owning segment for each byte array. Positions,
31a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * limits, prev, and next references are not shared.
323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerfinal class Segment {
343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** The size of all segments in bytes. */
35147e5ea75d85f64f2b051a11ed1879dfa56050e9Thierry Strudel  static final int SIZE = 8192;
363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
37a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  final byte[] data;
383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** The next byte of application data byte to read in this segment. */
403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  int pos;
413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** The first byte of available data ready to be written to. */
433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  int limit;
443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
45a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  /** True if other segments or byte strings use the same byte array. */
46a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  boolean shared;
47a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
48a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  /** True if this segment owns the byte array and can append to it, extending {@code limit}. */
49a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  boolean owner;
50a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Next segment in a linked or circularly-linked list. */
523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  Segment next;
533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Previous segment in a circularly-linked list. */
553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  Segment prev;
563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
57a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  Segment() {
58a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.data = new byte[SIZE];
59a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.owner = true;
60a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.shared = false;
61a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
62a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
63a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  Segment(Segment shareFrom) {
64a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this(shareFrom.data, shareFrom.pos, shareFrom.limit);
65a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    shareFrom.shared = true;
66a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
67a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
68a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  Segment(byte[] data, int pos, int limit) {
69a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.data = data;
70a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.pos = pos;
71a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.limit = limit;
72a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.owner = false;
73a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    this.shared = true;
74a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
75a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Removes this segment of a circularly-linked list and returns its successor.
783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Returns null if the list is now empty.
793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public Segment pop() {
813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment result = next != this ? next : null;
823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    prev.next = next;
833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    next.prev = prev;
843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    next = null;
853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    prev = null;
863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result;
873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Appends {@code segment} after this segment in the circularly-linked list.
913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Returns the pushed segment.
923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public Segment push(Segment segment) {
943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    segment.prev = this;
953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    segment.next = next;
963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    next.prev = segment;
973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    next = segment;
983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return segment;
993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
1023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Splits this head of a circularly-linked list into two segments. The first
1033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * segment contains the data in {@code [pos..pos+byteCount)}. The second
1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * segment contains the data in {@code [pos+byteCount..limit)}. This can be
105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * useful when moving partial segments from one buffer to another.
1063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   *
1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * <p>Returns the new head of the circularly-linked list.
1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public Segment split(int byteCount) {
110a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    if (byteCount <= 0 || byteCount > limit - pos) throw new IllegalArgumentException();
111a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    Segment prefix = new Segment(this);
112a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    prefix.limit = prefix.pos + byteCount;
113a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    pos += byteCount;
114a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    prev.push(prefix);
115a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    return prefix;
1163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
1193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Call this when the tail and its predecessor may both be less than half
1203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * full. This will copy data so that segments can be recycled.
1213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
1223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public void compact() {
1233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (prev == this) throw new IllegalStateException();
124a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    if (!prev.owner) return; // Cannot compact: prev isn't writable.
125a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    int byteCount = limit - pos;
126a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    int availableByteCount = SIZE - prev.limit + (prev.shared ? 0 : prev.pos);
127a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    if (byteCount > availableByteCount) return; // Cannot compact: not enough writable space.
128a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    writeTo(prev, byteCount);
1293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    pop();
130a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    SegmentPool.recycle(this);
1313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /** Moves {@code byteCount} bytes from this segment to {@code sink}. */
1343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public void writeTo(Segment sink, int byteCount) {
135a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    if (!sink.owner) throw new IllegalArgumentException();
1363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (sink.limit + byteCount > SIZE) {
137a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      // We can't fit byteCount bytes at the sink's current position. Shift sink first.
138a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      if (sink.shared) throw new IllegalArgumentException();
139a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      if (sink.limit + byteCount - sink.pos > SIZE) throw new IllegalArgumentException();
1403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      System.arraycopy(sink.data, sink.pos, sink.data, 0, sink.limit - sink.pos);
1413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      sink.limit -= sink.pos;
1423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      sink.pos = 0;
1433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
1443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    System.arraycopy(data, pos, sink.data, sink.limit, byteCount);
1463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    sink.limit += byteCount;
1473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    pos += byteCount;
1483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller}
150