001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.fusesource.hawtbuf; 018 019 import java.io.IOException; 020 import java.net.ProtocolException; 021 022 /** 023 * <p> 024 * Used to write and read primitives to and from a Buffer. Reads and 025 * writes are done at the buffers offset. Every read and write 026 * increases the buffer's offset and decreases the buffer's length. 027 * </p> 028 * <p> 029 * Bounds checking are only performed when assertions are enabled on 030 * the JVM. It's up to you to make sure there is enough data/space 031 * in the buffer to do the read or write. 032 * </p> 033 * 034 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 035 */ 036 abstract public class BufferEditor { 037 protected final Buffer buffer; 038 039 private BufferEditor(Buffer buffer) { 040 this.buffer = buffer; 041 } 042 043 protected boolean hasCapacity(int len) { 044 return buffer.length >= len; 045 } 046 047 public int read() { 048 buffer.length--; 049 return buffer.data[buffer.offset++] & 0xff; 050 } 051 052 public void readFully(byte[] b) { 053 readFully(b, 0, b.length); 054 } 055 056 public void readFully(byte[] b, int off, int len) { 057 assert (hasCapacity(len)); 058 System.arraycopy(buffer.data, buffer.offset, b, off, len); 059 buffer.offset += len; 060 buffer.length -= len; 061 } 062 063 public int skipBytes(int n) { 064 int len = Math.min(n, buffer.length); 065 buffer.offset += len; 066 buffer.length -= len; 067 return len; 068 } 069 070 public boolean readBoolean() { 071 assert (hasCapacity(1)); 072 return read() != 0; 073 } 074 075 public byte readByte() { 076 assert (hasCapacity(1)); 077 return (byte) read(); 078 } 079 080 public int readUnsignedByte() { 081 assert (hasCapacity(1)); 082 return read(); 083 } 084 085 public void write(int b) { 086 assert (hasCapacity(1)); 087 buffer.data[buffer.offset++] = (byte) b; 088 buffer.length--; 089 } 090 091 public void write(byte[] b) { 092 write(b, 0, b.length); 093 } 094 095 public void write(byte[] b, int off, int len) { 096 assert (hasCapacity(len)); 097 System.arraycopy(b, off, buffer.data, buffer.offset, len); 098 buffer.offset += len; 099 buffer.length -= len; 100 } 101 102 public void writeBoolean(boolean v) { 103 assert (hasCapacity(1)); 104 write(v ? 1 : 0); 105 } 106 107 public void writeByte(int v) { 108 assert (hasCapacity(1)); 109 write(v); 110 } 111 112 /** 113 * Read a raw Varint from the stream. If larger than 32 bits, discard the 114 * upper bits. 115 */ 116 public int readVarInt() throws IOException { 117 byte tmp = readByte(); 118 if (tmp >= 0) { 119 return tmp; 120 } 121 int result = tmp & 0x7f; 122 if ((tmp = readByte()) >= 0) { 123 result |= tmp << 7; 124 } else { 125 result |= (tmp & 0x7f) << 7; 126 if ((tmp = readByte()) >= 0) { 127 result |= tmp << 14; 128 } else { 129 result |= (tmp & 0x7f) << 14; 130 if ((tmp = readByte()) >= 0) { 131 result |= tmp << 21; 132 } else { 133 result |= (tmp & 0x7f) << 21; 134 result |= (tmp = readByte()) << 28; 135 if (tmp < 0) { 136 // Discard upper 32 bits. 137 for (int i = 0; i < 5; i++) { 138 if (readByte() >= 0) 139 return result; 140 } 141 throw new ProtocolException("Encountered a malformed variable int"); 142 } 143 } 144 } 145 } 146 return result; 147 } 148 149 /** Read a raw Varint from the stream. */ 150 public long readVarLong() throws IOException { 151 int shift = 0; 152 long result = 0; 153 while (shift < 64) { 154 byte b = readByte(); 155 result |= (long) (b & 0x7F) << shift; 156 if ((b & 0x80) == 0) 157 return result; 158 shift += 7; 159 } 160 throw new ProtocolException("Encountered a malformed variable int"); 161 } 162 163 164 /** Read an {@code sint32} field value from the stream. */ 165 public int readVarSignedInt() throws IOException { 166 return decodeZigZag32(readVarInt()); 167 } 168 169 /** Read an {@code sint64} field value from the stream. */ 170 public long readVarSignedLong() throws IOException { 171 return decodeZigZag64(readVarLong()); 172 } 173 174 /** 175 * Encode and write a varint. {@code value} is treated as unsigned, so it 176 * won't be sign-extended if negative. 177 */ 178 public void writeVarInt(int value) throws IOException { 179 while (true) { 180 if ((value & ~0x7F) == 0) { 181 writeByte(value); 182 return; 183 } else { 184 writeByte((value & 0x7F) | 0x80); 185 value >>>= 7; 186 } 187 } 188 } 189 190 191 /** Encode and write a varint. */ 192 public void writeVarLong(long value) throws IOException { 193 while (true) { 194 if ((value & ~0x7FL) == 0) { 195 writeByte((int) value); 196 return; 197 } else { 198 writeByte(((int) value & 0x7F) | 0x80); 199 value >>>= 7; 200 } 201 } 202 } 203 204 public void writeVarSignedInt(int value) throws IOException { 205 writeVarInt(encodeZigZag32(value)); 206 } 207 208 public void writeVarSignedLong(long value) throws IOException { 209 writeVarLong(encodeZigZag64(value)); 210 } 211 212 private static int decodeZigZag32(int n) { 213 return (n >>> 1) ^ -(n & 1); 214 } 215 216 private static long decodeZigZag64(long n) { 217 return (n >>> 1) ^ -(n & 1); 218 } 219 220 private static int encodeZigZag32(int n) { 221 return (n << 1) ^ (n >> 31); 222 } 223 224 private static long encodeZigZag64(long n) { 225 return (n << 1) ^ (n >> 63); 226 } 227 228 abstract public short readShort(); 229 230 abstract public int readUnsignedShort(); 231 232 abstract public char readChar(); 233 234 abstract public int readInt(); 235 236 abstract public long readLong(); 237 238 abstract public double readDouble(); 239 240 abstract public float readFloat(); 241 242 abstract public void writeShort(int v); 243 244 abstract public void writeChar(int v); 245 246 abstract public void writeInt(int v); 247 248 abstract public void writeLong(long v); 249 250 abstract public void writeDouble(double v); 251 252 abstract public void writeFloat(float v); 253 254 abstract public void writeRawDouble(double v); 255 256 abstract public void writeRawFloat(float v); 257 258 static class BigEndianBufferEditor extends BufferEditor { 259 260 BigEndianBufferEditor(Buffer buffer) { 261 super(buffer); 262 } 263 264 public short readShort() { 265 assert (hasCapacity(2)); 266 return (short) ((read() << 8) + (read() << 0)); 267 } 268 269 270 public int readUnsignedShort() { 271 assert (hasCapacity(2)); 272 return (read() << 8) + (read() << 0); 273 } 274 275 public char readChar() { 276 assert (hasCapacity(2)); 277 return (char) ((read() << 8) + (read() << 0)); 278 } 279 280 281 public int readInt() { 282 assert (hasCapacity(4)); 283 return (read() << 24) + (read() << 16) + (read() << 8) + (read() << 0); 284 } 285 286 287 public long readLong() { 288 assert (hasCapacity(8)); 289 return ((long) read() << 56) + ((long) read() << 48) + ((long) read() << 40) + ((long) read() << 32) + ((long) read() << 24) 290 + ((read()) << 16) + ((read()) << 8) + ((read()) << 0); 291 } 292 293 294 public double readDouble() { 295 return Double.longBitsToDouble(readLong()); 296 } 297 298 299 public float readFloat() { 300 return Float.intBitsToFloat(readInt()); 301 } 302 303 public void writeShort(int v) { 304 assert (hasCapacity(2)); 305 write((v >>> 8) & 0xFF); 306 write((v >>> 0) & 0xFF); 307 } 308 309 310 public void writeChar(int v) { 311 assert (hasCapacity(2)); 312 write((v >>> 8) & 0xFF); 313 write((v >>> 0) & 0xFF); 314 } 315 316 317 public void writeInt(int v) { 318 assert (hasCapacity(4)); 319 write((v >>> 24) & 0xFF); 320 write((v >>> 16) & 0xFF); 321 write((v >>> 8) & 0xFF); 322 write((v >>> 0) & 0xFF); 323 } 324 325 public void writeLong(long v) { 326 assert (hasCapacity(8)); 327 write((int) (v >>> 56) & 0xFF); 328 write((int) (v >>> 48) & 0xFF); 329 write((int) (v >>> 40) & 0xFF); 330 write((int) (v >>> 32) & 0xFF); 331 write((int) (v >>> 24) & 0xFF); 332 write((int) (v >>> 16) & 0xFF); 333 write((int) (v >>> 8) & 0xFF); 334 write((int) (v >>> 0) & 0xFF); 335 } 336 337 338 public void writeDouble(double v) { 339 writeLong(Double.doubleToLongBits(v)); 340 } 341 342 public void writeFloat(float v) { 343 writeInt(Float.floatToIntBits(v)); 344 } 345 346 public void writeRawDouble(double v) { 347 writeLong(Double.doubleToRawLongBits(v)); 348 } 349 350 public void writeRawFloat(float v) { 351 writeInt(Float.floatToRawIntBits(v)); 352 } 353 } 354 355 ; 356 357 358 static class LittleEndianBufferEditor extends BufferEditor { 359 360 LittleEndianBufferEditor(Buffer buffer) { 361 super(buffer); 362 } 363 364 public short readShort() { 365 assert (hasCapacity(2)); 366 return (short) ((read() << 0) + (read() << 8)); 367 } 368 369 public int readUnsignedShort() { 370 assert (hasCapacity(2)); 371 return (read() << 0) + (read() << 8); 372 } 373 374 public char readChar() { 375 assert (hasCapacity(2)); 376 return (char) ((read() << 0) + (read() << 8)); 377 } 378 379 public int readInt() { 380 assert (hasCapacity(4)); 381 return (read() << 0) + (read() << 8) + (read() << 16) + (read() << 24); 382 } 383 384 public long readLong() { 385 assert (hasCapacity(8)); 386 return (read() << 0) + (read() << 8) + (read() << 16) + ((long) read() << 24) + ((long) read() << 32) + ((long) read() << 40) 387 + ((long) read() << 48) + ((long) read() << 56); 388 } 389 390 public double readDouble() { 391 return Double.longBitsToDouble(readLong()); 392 } 393 394 public float readFloat() { 395 return Float.intBitsToFloat(readInt()); 396 } 397 398 public void writeShort(int v) { 399 assert (hasCapacity(2)); 400 write((v >>> 0) & 0xFF); 401 write((v >>> 8) & 0xFF); 402 } 403 404 public void writeChar(int v) { 405 assert (hasCapacity(2)); 406 write((v >>> 0) & 0xFF); 407 write((v >>> 8) & 0xFF); 408 } 409 410 411 public void writeInt(int v) { 412 assert (hasCapacity(4)); 413 write((v >>> 0) & 0xFF); 414 write((v >>> 8) & 0xFF); 415 write((v >>> 16) & 0xFF); 416 write((v >>> 24) & 0xFF); 417 } 418 419 420 public void writeLong(long v) { 421 assert (hasCapacity(8)); 422 write((int) (v >>> 0) & 0xFF); 423 write((int) (v >>> 8) & 0xFF); 424 write((int) (v >>> 16) & 0xFF); 425 write((int) (v >>> 24) & 0xFF); 426 write((int) (v >>> 32) & 0xFF); 427 write((int) (v >>> 40) & 0xFF); 428 write((int) (v >>> 48) & 0xFF); 429 write((int) (v >>> 56) & 0xFF); 430 } 431 432 public void writeDouble(double v) { 433 writeLong(Double.doubleToLongBits(v)); 434 } 435 436 437 public void writeFloat(float v) { 438 writeInt(Float.floatToIntBits(v)); 439 } 440 441 public void writeRawDouble(double v) { 442 writeLong(Double.doubleToRawLongBits(v)); 443 } 444 445 446 public void writeRawFloat(float v) { 447 writeInt(Float.floatToRawIntBits(v)); 448 } 449 450 } 451 452 ; 453 }