Home | History | Annotate | Download | only in micro
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 package com.google.protobuf.micro;
     32 
     33 import java.io.UnsupportedEncodingException;
     34 
     35 /**
     36  * Immutable array of bytes.
     37  *
     38  * @author crazybob (at) google.com Bob Lee
     39  * @author kenton (at) google.com Kenton Varda
     40  */
     41 public final class ByteStringMicro {
     42   private final byte[] bytes;
     43 
     44   private ByteStringMicro(final byte[] bytes) {
     45     this.bytes = bytes;
     46   }
     47 
     48   /**
     49    * Gets the byte at the given index.
     50    *
     51    * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
     52    */
     53   public byte byteAt(final int index) {
     54     return bytes[index];
     55   }
     56 
     57   /**
     58    * Gets the number of bytes.
     59    */
     60   public int size() {
     61     return bytes.length;
     62   }
     63 
     64   /**
     65    * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
     66    */
     67   public boolean isEmpty() {
     68     return bytes.length == 0;
     69   }
     70 
     71   // =================================================================
     72   // byte[] -> ByteStringMicro
     73 
     74   /**
     75    * Empty ByteStringMicro.
     76    */
     77   public static final ByteStringMicro EMPTY = new ByteStringMicro(new byte[0]);
     78 
     79   /**
     80    * Copies the given bytes into a {@code ByteStringMicro}.
     81    */
     82   public static ByteStringMicro copyFrom(final byte[] bytes, final int offset,
     83                                     final int size) {
     84     final byte[] copy = new byte[size];
     85     System.arraycopy(bytes, offset, copy, 0, size);
     86     return new ByteStringMicro(copy);
     87   }
     88 
     89   /**
     90    * Copies the given bytes into a {@code ByteStringMicro}.
     91    */
     92   public static ByteStringMicro copyFrom(final byte[] bytes) {
     93     return copyFrom(bytes, 0, bytes.length);
     94   }
     95 
     96   /**
     97    * Encodes {@code text} into a sequence of bytes using the named charset
     98    * and returns the result as a {@code ByteStringMicro}.
     99    */
    100   public static ByteStringMicro copyFrom(final String text, final String charsetName)
    101       throws UnsupportedEncodingException {
    102     return new ByteStringMicro(text.getBytes(charsetName));
    103   }
    104 
    105   /**
    106    * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
    107    * result as a {@code ByteStringMicro}.
    108    */
    109   public static ByteStringMicro copyFromUtf8(final String text) {
    110     try {
    111       return new ByteStringMicro(text.getBytes("UTF-8"));
    112     } catch (UnsupportedEncodingException e) {
    113       throw new RuntimeException("UTF-8 not supported?");
    114     }
    115   }
    116 
    117   // =================================================================
    118   // ByteStringMicro -> byte[]
    119 
    120   /**
    121    * Copies bytes into a buffer at the given offset.
    122    *
    123    * @param target buffer to copy into
    124    * @param offset in the target buffer
    125    */
    126   public void copyTo(final byte[] target, final int offset) {
    127     System.arraycopy(bytes, 0, target, offset, bytes.length);
    128   }
    129 
    130   /**
    131    * Copies bytes into a buffer.
    132    *
    133    * @param target buffer to copy into
    134    * @param sourceOffset offset within these bytes
    135    * @param targetOffset offset within the target buffer
    136    * @param size number of bytes to copy
    137    */
    138   public void copyTo(final byte[] target, final int sourceOffset,
    139                      final int targetOffset,
    140       final int size) {
    141     System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
    142   }
    143 
    144   /**
    145    * Copies bytes to a {@code byte[]}.
    146    */
    147   public byte[] toByteArray() {
    148     final int size = bytes.length;
    149     final byte[] copy = new byte[size];
    150     System.arraycopy(bytes, 0, copy, 0, size);
    151     return copy;
    152   }
    153 
    154   /**
    155    * Constructs a new {@code String} by decoding the bytes using the
    156    * specified charset.
    157    */
    158   public String toString(final String charsetName)
    159       throws UnsupportedEncodingException {
    160     return new String(bytes, charsetName);
    161   }
    162 
    163   /**
    164    * Constructs a new {@code String} by decoding the bytes as UTF-8.
    165    */
    166   public String toStringUtf8() {
    167     try {
    168       return new String(bytes, "UTF-8");
    169     } catch (UnsupportedEncodingException e) {
    170       throw new RuntimeException("UTF-8 not supported?");
    171     }
    172   }
    173 
    174   // =================================================================
    175   // equals() and hashCode()
    176 
    177   //@Override for compatibility with Java 1.3 code we can't use annotations
    178   public boolean equals(final Object o) {
    179     if (o == this) {
    180       return true;
    181     }
    182 
    183     if (!(o instanceof ByteStringMicro)) {
    184       return false;
    185     }
    186 
    187     final ByteStringMicro other = (ByteStringMicro) o;
    188     final int size = bytes.length;
    189     if (size != other.bytes.length) {
    190       return false;
    191     }
    192 
    193     final byte[] thisBytes = bytes;
    194     final byte[] otherBytes = other.bytes;
    195     for (int i = 0; i < size; i++) {
    196       if (thisBytes[i] != otherBytes[i]) {
    197         return false;
    198       }
    199     }
    200 
    201     return true;
    202   }
    203 
    204   private volatile int hash = 0;
    205 
    206   //@Override for compatibility with Java 1.3 code we can't use annotations
    207   public int hashCode() {
    208     int h = hash;
    209 
    210     if (h == 0) {
    211       final byte[] thisBytes = bytes;
    212       final int size = bytes.length;
    213 
    214       h = size;
    215       for (int i = 0; i < size; i++) {
    216         h = h * 31 + thisBytes[i];
    217       }
    218       if (h == 0) {
    219         h = 1;
    220       }
    221 
    222       hash = h;
    223     }
    224 
    225     return h;
    226   }
    227 }
    228