c7edbb6d2b616d30e517be004fadaa167488aefe
[controller.git] / third-party / atomix / storage / src / main / java / io / atomix / storage / buffer / AbstractBytes.java
1 /*
2  * Copyright 2015-present Open Networking Foundation
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 package io.atomix.storage.buffer;
17
18 import java.nio.BufferOverflowException;
19 import java.nio.BufferUnderflowException;
20 import java.nio.ByteOrder;
21 import java.nio.charset.Charset;
22 import java.nio.charset.StandardCharsets;
23
24 /**
25  * Abstract bytes implementation.
26  * <p>
27  * This class provides common state and bounds checking functionality for all {@link Bytes} implementations.
28  *
29  * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
30  */
31 public abstract class AbstractBytes implements Bytes {
32   static final int MAX_SIZE = Integer.MAX_VALUE - 5;
33
34   private boolean open = true;
35   private SwappedBytes swap;
36
37   /**
38    * Checks whether the block is open.
39    */
40   protected void checkOpen() {
41     if (!open) {
42       throw new IllegalStateException("bytes not open");
43     }
44   }
45
46   /**
47    * Checks that the offset is within the bounds of the buffer.
48    */
49   protected void checkOffset(int offset) {
50     checkOpen();
51     if (offset < 0 || offset > size()) {
52       throw new IndexOutOfBoundsException();
53     }
54   }
55
56   /**
57    * Checks bounds for a read.
58    */
59   protected int checkRead(int offset, int length) {
60     checkOffset(offset);
61     int position = offset + length;
62     if (position > size()) {
63       throw new BufferUnderflowException();
64     }
65     return position;
66   }
67
68   /**
69    * Checks bounds for a write.
70    */
71   protected int checkWrite(int offset, int length) {
72     checkOffset(offset);
73     int position = offset + length;
74     if (position > size()) {
75       throw new BufferOverflowException();
76     }
77     return position;
78   }
79
80   @Override
81   public boolean isDirect() {
82     return false;
83   }
84
85   @Override
86   public boolean isFile() {
87     return false;
88   }
89
90   @Override
91   public ByteOrder order() {
92     return ByteOrder.BIG_ENDIAN;
93   }
94
95   @Override
96   public Bytes order(ByteOrder order) {
97     if (order == null) {
98       throw new NullPointerException("order cannot be null");
99     }
100     if (order == order()) {
101       return this;
102     }
103     if (swap != null) {
104       return swap;
105     }
106     swap = new SwappedBytes(this);
107     return swap;
108   }
109
110   @Override
111   public boolean readBoolean(int offset) {
112     return readByte(offset) == 1;
113   }
114
115   @Override
116   public int readUnsignedByte(int offset) {
117     return readByte(offset) & 0xFF;
118   }
119
120   @Override
121   public int readUnsignedShort(int offset) {
122     return readShort(offset) & 0xFFFF;
123   }
124
125   @Override
126   public int readMedium(int offset) {
127     return (readByte(offset)) << 16
128         | (readByte(offset + 1) & 0xff) << 8
129         | (readByte(offset + 2) & 0xff);
130   }
131
132   @Override
133   public int readUnsignedMedium(int offset) {
134     return (readByte(offset) & 0xff) << 16
135         | (readByte(offset + 1) & 0xff) << 8
136         | (readByte(offset + 2) & 0xff);
137   }
138
139   @Override
140   public long readUnsignedInt(int offset) {
141     return readInt(offset) & 0xFFFFFFFFL;
142   }
143
144   @Override
145   public String readString(int offset) {
146     return readString(offset, Charset.defaultCharset());
147   }
148
149   @Override
150   public String readString(int offset, Charset charset) {
151     if (readBoolean(offset)) {
152       byte[] bytes = new byte[readUnsignedShort(offset + BYTE)];
153       read(offset + BYTE + SHORT, bytes, 0, bytes.length);
154       return new String(bytes, charset);
155     }
156     return null;
157   }
158
159   @Override
160   public String readUTF8(int offset) {
161     return readString(offset, StandardCharsets.UTF_8);
162   }
163
164   @Override
165   public Bytes writeBoolean(int offset, boolean b) {
166     return writeByte(offset, b ? 1 : 0);
167   }
168
169   @Override
170   public Bytes writeUnsignedByte(int offset, int b) {
171     return writeByte(offset, (byte) b);
172   }
173
174   @Override
175   public Bytes writeUnsignedShort(int offset, int s) {
176     return writeShort(offset, (short) s);
177   }
178
179   @Override
180   public Bytes writeMedium(int offset, int m) {
181     writeByte(offset, (byte) (m >>> 16));
182     writeByte(offset + 1, (byte) (m >>> 8));
183     writeByte(offset + 2, (byte) m);
184     return this;
185   }
186
187   @Override
188   public Bytes writeUnsignedMedium(int offset, int m) {
189     return writeMedium(offset, m);
190   }
191
192   @Override
193   public Bytes writeUnsignedInt(int offset, long i) {
194     return writeInt(offset, (int) i);
195   }
196
197   @Override
198   public Bytes writeString(int offset, String s) {
199     return writeString(offset, s, Charset.defaultCharset());
200   }
201
202   @Override
203   public Bytes writeString(int offset, String s, Charset charset) {
204     if (s == null) {
205       return writeBoolean(offset, Boolean.FALSE);
206     } else {
207       writeBoolean(offset, Boolean.TRUE);
208       byte[] bytes = s.getBytes(charset);
209       return writeUnsignedShort(offset + BYTE, bytes.length)
210           .write(offset + BYTE + SHORT, bytes, 0, bytes.length);
211     }
212   }
213
214   @Override
215   public Bytes writeUTF8(int offset, String s) {
216     return writeString(offset, s, StandardCharsets.UTF_8);
217   }
218
219   @Override
220   public Bytes flush() {
221     return this;
222   }
223
224   @Override
225   public void close() {
226     open = false;
227   }
228
229 }