• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.timezone.location.storage.io.write;
18 
19 import com.android.timezone.location.storage.util.BitwiseUtils;
20 
21 import java.io.BufferedOutputStream;
22 import java.io.Closeable;
23 import java.io.DataOutputStream;
24 import java.io.Flushable;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 
28 /**
29  * A stream-based writer of typed data that can be read back by
30  * {@link com.android.timezone.location.storage.block.read.BlockData} and
31  * {@link com.android.timezone.location.storage.io.read.TypedInputStream}
32  */
33 public final class TypedOutputStream implements Flushable, Closeable {
34 
35     private final DataOutputStream mDataOutputStream;
36 
37     /** Creates an instance, wrapping the supplied stream. */
TypedOutputStream(OutputStream out)38     public TypedOutputStream(OutputStream out) {
39         mDataOutputStream = new DataOutputStream(new BufferedOutputStream(out, 8192));
40     }
41 
42     /**
43      * Writes {@code value} as a sequence of network-ordered bytes. {@code byteCount} must be
44      * between 1 and 8 inclusive. All bits not to be written in {@code value} <em>must</em> be
45      * zero'd otherwise an {@link IllegalArgumentException} will be thrown.
46      */
writeVarByteValue(int byteCount, long value)47     public void writeVarByteValue(int byteCount, long value) throws IOException {
48         if (byteCount < 1 || byteCount > 8) {
49             throw new IllegalArgumentException("byteCount " + byteCount + " out of range");
50         }
51 
52         // To avoid errors, we check for zeros in the bytes we're not writing.
53         if (byteCount < 8) {
54             long unusedBits = value & BitwiseUtils.getHighBitsMask((8 - byteCount) * 8);
55             if (unusedBits != 0) {
56                 throw new IllegalArgumentException("Bits not to be written should be zero,"
57                         + " unusedBits=" + unusedBits);
58             }
59         }
60 
61         // Write the high bytes first.
62         for (int i = byteCount - 1; i >= 0; i--) {
63             byte b = (byte) (value >>> (i * 8));
64             mDataOutputStream.write(b);
65         }
66     }
67 
68     /**
69      * Writes {@code unsignedValue} as an unsigned byte. If {@code unsignedValue} is outside of the
70      * range 0-255 inclusive, an {@link IllegalArgumentException} is thrown.
71      */
writeUnsignedByte(int unsignedValue)72     public void writeUnsignedByte(int unsignedValue) throws IOException {
73         if (unsignedValue < 0 || unsignedValue > 255) {
74             throw new IllegalArgumentException("unsignedValue=" + unsignedValue + " is negative");
75         }
76         mDataOutputStream.writeByte(unsignedValue);
77     }
78 
79     /**
80      * Writes {@code b} as a signed byte. If {@code b} is outside of the range -128-127 inclusive,
81      * an {@link IllegalArgumentException} is thrown.
82      */
writeByte(int b)83     public void writeByte(int b) throws IOException {
84         BitwiseUtils.checkSignedValueInRange(Byte.SIZE, b);
85         mDataOutputStream.writeByte(b);
86     }
87 
88     /**
89      * Writes {@code bytes}.
90      */
writeBytes(byte[] bytes)91     public void writeBytes(byte[] bytes) throws IOException {
92         mDataOutputStream.write(bytes);
93     }
94 
95     /**
96      * Writes {@code len} {@code bytes} starting at {@code off}.
97      */
writeBytes(byte[] bytes, int off, int len)98     public void writeBytes(byte[] bytes, int off, int len) throws IOException {
99         mDataOutputStream.write(bytes, off, len);
100     }
101 
102     /**
103      * Writes a tiny (<= 255 entry) byte array as an unsigned byte (length) followed by the bytes.
104      */
writeTinyByteArray(byte[] bytes)105     public void writeTinyByteArray(byte[] bytes) throws IOException {
106         writeUnsignedByte(bytes.length);
107         mDataOutputStream.write(bytes);
108     }
109 
110     /**
111      * Writes a tiny (<= 255 entry) char array as an unsigned byte (length) followed by the chars.
112      */
writeTinyCharArray(char[] chars)113     public void writeTinyCharArray(char[] chars) throws IOException {
114         writeUnsignedByte(chars.length);
115         for (int i = 0; i < chars.length; i++) {
116             mDataOutputStream.writeChar(chars[i]);
117         }
118     }
119 
120     /**
121      * Writes {@code v} as an 16-bit value in network byte order. If {@code v} is outside of the
122      * char range, an {@link IllegalArgumentException} is thrown.
123      */
writeChar(int v)124     public void writeChar(int v) throws IOException {
125         BitwiseUtils.checkUnsignedValueInRange(Character.SIZE, v);
126         mDataOutputStream.writeChar(v);
127     }
128 
129     /**
130      * Writes {@code v} as an 32-bit value in network byte order.
131      */
writeInt(int v)132     public void writeInt(int v) throws IOException {
133         mDataOutputStream.writeInt(v);
134     }
135 
136     /**
137      * Writes {@code v} as an 64-bit value in network byte order.
138      */
writeLong(long v)139     public void writeLong(long v) throws IOException {
140         mDataOutputStream.writeLong(v);
141     }
142 
143     @Override
close()144     public void close() throws IOException {
145         mDataOutputStream.close();
146     }
147 
148     @Override
flush()149     public void flush() throws IOException {
150         mDataOutputStream.flush();
151     }
152 }
153