Line data Source code
1 : // Copyright 2008 Google Inc. All rights reserved.
2 : // http://code.google.com/p/protobuf/
3 : //
4 : // Redistribution and use in source and binary forms, with or without
5 : // modification, are permitted provided that the following conditions are
6 : // met:
7 : //
8 : // * Redistributions of source code must retain the above copyright
9 : // notice, this list of conditions and the following disclaimer.
10 : // * Redistributions in binary form must reproduce the above
11 : // copyright notice, this list of conditions and the following disclaimer
12 : // in the documentation and/or other materials provided with the
13 : // distribution.
14 : // * Neither the name of Google Inc. nor the names of its
15 : // contributors may be used to endorse or promote products derived from
16 : // this software without specific prior written permission.
17 : //
18 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 :
30 : package com.google.gerrit.server.ioutil;
31 :
32 : import static java.nio.charset.StandardCharsets.UTF_8;
33 :
34 : import com.google.gerrit.common.Nullable;
35 : import com.google.gerrit.entities.CodedEnum;
36 : import java.io.EOFException;
37 : import java.io.IOException;
38 : import java.io.InputStream;
39 : import java.io.OutputStream;
40 : import org.eclipse.jgit.util.IO;
41 :
42 : public class BasicSerialization {
43 8 : private static final byte[] NO_BYTES = {};
44 :
45 : private static int safeRead(InputStream input) throws IOException {
46 2 : final int b = input.read();
47 2 : if (b == -1) {
48 0 : throw new EOFException();
49 : }
50 2 : return b;
51 : }
52 :
53 : /** Read a fixed-width 64 bit integer in network byte order (big-endian). */
54 : public static long readFixInt64(InputStream input) throws IOException {
55 1 : final long h = readFixInt32(input);
56 1 : final long l = readFixInt32(input) & 0xFFFFFFFFL;
57 1 : return (h << 32) | l;
58 : }
59 :
60 : /** Write a fixed-width 64 bit integer in network byte order (big-endian). */
61 : public static void writeFixInt64(OutputStream output, long val) throws IOException {
62 1 : writeFixInt32(output, (int) (val >>> 32));
63 1 : writeFixInt32(output, (int) (val & 0xFFFFFFFFL));
64 1 : }
65 :
66 : /** Read a fixed-width 32 bit integer in network byte order (big-endian). */
67 : public static int readFixInt32(InputStream input) throws IOException {
68 1 : final int b1 = safeRead(input);
69 1 : final int b2 = safeRead(input);
70 1 : final int b3 = safeRead(input);
71 1 : final int b4 = safeRead(input);
72 1 : return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
73 : }
74 :
75 : /** Write a fixed-width 32 bit integer in network byte order (big-endian). */
76 : public static void writeFixInt32(OutputStream output, int val) throws IOException {
77 1 : output.write((val >>> 24) & 0xFF);
78 1 : output.write((val >>> 16) & 0xFF);
79 1 : output.write((val >>> 8) & 0xFF);
80 1 : output.write(val & 0xFF);
81 1 : }
82 :
83 : /** Read a varint from the input, one byte at a time. */
84 : public static int readVarInt32(InputStream input) throws IOException {
85 2 : int result = 0;
86 2 : int offset = 0;
87 2 : for (; offset < 32; offset += 7) {
88 2 : final int b = safeRead(input);
89 2 : result |= (b & 0x7f) << offset;
90 2 : if ((b & 0x80) == 0) {
91 2 : return result;
92 : }
93 : }
94 0 : throw new EOFException();
95 : }
96 :
97 : /** Write a varint; value is treated as an unsigned value. */
98 : public static void writeVarInt32(OutputStream output, int value) throws IOException {
99 : while (true) {
100 8 : if ((value & ~0x7F) == 0) {
101 8 : output.write(value);
102 8 : return;
103 : }
104 2 : output.write((value & 0x7F) | 0x80);
105 2 : value >>>= 7;
106 : }
107 : }
108 :
109 : /** Read a fixed length byte array whose length is specified as a varint. */
110 : public static byte[] readBytes(InputStream input) throws IOException {
111 1 : final int len = readVarInt32(input);
112 1 : if (len == 0) {
113 1 : return NO_BYTES;
114 : }
115 1 : final byte[] buf = new byte[len];
116 1 : IO.readFully(input, buf, 0, len);
117 1 : return buf;
118 : }
119 :
120 : /** Write a byte array prefixed by its length in a varint. */
121 : public static void writeBytes(OutputStream output, byte[] data) throws IOException {
122 6 : writeBytes(output, data, 0, data.length);
123 6 : }
124 :
125 : /** Write a byte array prefixed by its length in a varint. */
126 : public static void writeBytes(final OutputStream output, byte[] data, int offset, int len)
127 : throws IOException {
128 6 : writeVarInt32(output, len);
129 6 : output.write(data, offset, len);
130 6 : }
131 :
132 : /** Read a UTF-8 string, prefixed by its byte length in a varint. */
133 : @Nullable
134 : public static String readString(InputStream input) throws IOException {
135 1 : final byte[] bin = readBytes(input);
136 1 : if (bin.length == 0) {
137 1 : return null;
138 : }
139 1 : return new String(bin, 0, bin.length, UTF_8);
140 : }
141 :
142 : /** Write a UTF-8 string, prefixed by its byte length in a varint. */
143 : public static void writeString(OutputStream output, String s) throws IOException {
144 5 : if (s == null) {
145 1 : writeVarInt32(output, 0);
146 : } else {
147 5 : writeBytes(output, s.getBytes(UTF_8));
148 : }
149 5 : }
150 :
151 : /** Read an enum whose code is stored as a varint. */
152 : public static <T extends CodedEnum> T readEnum(InputStream input, T[] all) throws IOException {
153 0 : final int val = readVarInt32(input);
154 0 : for (T t : all) {
155 0 : if (t.getCode() == val) {
156 0 : return t;
157 : }
158 : }
159 0 : throw new IOException("Invalid enum " + val + " for " + all[0].getClass());
160 : }
161 :
162 : /** Write an enum whose code is stored as a varint. */
163 : public static <T extends CodedEnum> void writeEnum(OutputStream output, T e) throws IOException {
164 0 : writeVarInt32(output, e.getCode());
165 0 : }
166 :
167 : private BasicSerialization() {}
168 : }
|