aboutsummaryrefslogtreecommitdiff
path: root/okio/src/commonMain/kotlin/okio/SegmentedByteString.kt
diff options
context:
space:
mode:
Diffstat (limited to 'okio/src/commonMain/kotlin/okio/SegmentedByteString.kt')
-rw-r--r--okio/src/commonMain/kotlin/okio/SegmentedByteString.kt50
1 files changed, 50 insertions, 0 deletions
diff --git a/okio/src/commonMain/kotlin/okio/SegmentedByteString.kt b/okio/src/commonMain/kotlin/okio/SegmentedByteString.kt
new file mode 100644
index 00000000..bda4f4a3
--- /dev/null
+++ b/okio/src/commonMain/kotlin/okio/SegmentedByteString.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package okio
+
+/**
+ * An immutable byte string composed of segments of byte arrays. This class exists to implement
+ * efficient snapshots of buffers. It is implemented as an array of segments, plus a directory in
+ * two halves that describes how the segments compose this byte string.
+ *
+ * The first half of the directory is the cumulative byte count covered by each segment. The
+ * element at `directory[0]` contains the number of bytes held in `segments[0]`; the
+ * element at `directory[1]` contains the number of bytes held in `segments[0] +
+ * segments[1]`, and so on. The element at `directory[segments.length - 1]` contains the total
+ * size of this byte string. The first half of the directory is always monotonically increasing.
+ *
+ * The second half of the directory is the offset in `segments` of the first content byte.
+ * Bytes preceding this offset are unused, as are bytes beyond the segment's effective size.
+ *
+ * Suppose we have a byte string, `[A, B, C, D, E, F, G, H, I, J, K, L, M]` that is stored
+ * across three byte arrays: `[x, x, x, x, A, B, C, D, E, x, x, x]`, `[x, F, G]`, and `[H, I, J, K,
+ * L, M, x, x, x, x, x, x]`. The three byte arrays would be stored in `segments` in order. Since the
+ * arrays contribute 5, 2, and 6 elements respectively, the directory starts with `[5, 7, 13` to
+ * hold the cumulative total at each position. Since the offsets into the arrays are 4, 1, and 0
+ * respectively, the directory ends with `4, 1, 0]`. Concatenating these two halves, the complete
+ * directory is `[5, 7, 13, 4, 1, 0]`.
+ *
+ * This structure is chosen so that the segment holding a particular offset can be found by
+ * binary search. We use one array rather than two for the directory as a micro-optimization.
+ */
+internal expect class SegmentedByteString internal constructor(
+ segments: Array<ByteArray>,
+ directory: IntArray
+) : ByteString {
+
+ internal val segments: Array<ByteArray>
+ internal val directory: IntArray
+}