PageRenderTime 23ms CodeModel.GetById 12ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/release-0.1-rc2/hive/external/serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyInteger.java

#
Java | 214 lines | 106 code | 15 blank | 93 comment | 26 complexity | 31914d86f7b38b8327c9864bd63c89bd MD5 | raw file
  1/**
  2 * Licensed to the Apache Software Foundation (ASF) under one
  3 * or more contributor license agreements.  See the NOTICE file
  4 * distributed with this work for additional information
  5 * regarding copyright ownership.  The ASF licenses this file
  6 * to you under the Apache License, Version 2.0 (the
  7 * "License"); you may not use this file except in compliance
  8 * with the License.  You may obtain a copy of the License at
  9 *
 10 *     http://www.apache.org/licenses/LICENSE-2.0
 11 *
 12 * Unless required by applicable law or agreed to in writing, software
 13 * distributed under the License is distributed on an "AS IS" BASIS,
 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18package org.apache.hadoop.hive.serde2.lazy;
 19
 20import java.io.IOException;
 21import java.io.OutputStream;
 22
 23import org.apache.hadoop.hive.serde2.lazy.objectinspector.primitive.LazyIntObjectInspector;
 24import org.apache.hadoop.io.IntWritable;
 25
 26/**
 27 * LazyObject for storing a value of Integer.
 28 * 
 29 * <p>
 30 * Part of the code is adapted from Apache Harmony Project.
 31 * 
 32 * As with the specification, this implementation relied on code laid out in <a
 33 * href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's
 34 * Delight, (Addison Wesley, 2002)</a> as well as <a
 35 * href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>.
 36 * </p>
 37 * 
 38 */
 39public class LazyInteger extends
 40    LazyPrimitive<LazyIntObjectInspector, IntWritable> {
 41
 42  public LazyInteger(LazyIntObjectInspector oi) {
 43    super(oi);
 44    data = new IntWritable();
 45  }
 46
 47  public LazyInteger(LazyInteger copy) {
 48    super(copy);
 49    data = new IntWritable(copy.data.get());
 50  }
 51
 52  @Override
 53  public void init(ByteArrayRef bytes, int start, int length) {
 54    try {
 55      data.set(parseInt(bytes.getData(), start, length, 10));
 56      isNull = false;
 57    } catch (NumberFormatException e) {
 58      isNull = true;
 59    }
 60  }
 61
 62  /**
 63   * Parses the string argument as if it was an int value and returns the
 64   * result. Throws NumberFormatException if the string does not represent an
 65   * int quantity.
 66   * 
 67   * @param bytes
 68   * @param start
 69   * @param length
 70   *          a UTF-8 encoded string representation of an int quantity.
 71   * @return int the value represented by the argument
 72   * @exception NumberFormatException
 73   *              if the argument could not be parsed as an int quantity.
 74   */
 75  public static int parseInt(byte[] bytes, int start, int length) {
 76    return parseInt(bytes, start, length, 10);
 77  }
 78
 79  /**
 80   * Parses the string argument as if it was an int value and returns the
 81   * result. Throws NumberFormatException if the string does not represent an
 82   * int quantity. The second argument specifies the radix to use when parsing
 83   * the value.
 84   * 
 85   * @param bytes
 86   * @param start
 87   * @param length
 88   *          a UTF-8 encoded string representation of an int quantity.
 89   * @param radix
 90   *          the base to use for conversion.
 91   * @return the value represented by the argument
 92   * @exception NumberFormatException
 93   *              if the argument could not be parsed as an int quantity.
 94   */
 95  public static int parseInt(byte[] bytes, int start, int length, int radix) {
 96    if (bytes == null) {
 97      throw new NumberFormatException("String is null");
 98    }
 99    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
100      throw new NumberFormatException("Invalid radix: " + radix);
101    }
102    if (length == 0) {
103      throw new NumberFormatException("Empty string!");
104    }
105    int offset = start;
106    boolean negative = bytes[start] == '-';
107    if (negative || bytes[start] == '+') {
108      offset++;
109      if (length == 1) {
110        throw new NumberFormatException(LazyUtils.convertToString(bytes, start,
111            length));
112      }
113    }
114
115    return parse(bytes, start, length, offset, radix, negative);
116  }
117
118  /**
119   * 
120   * @param bytes
121   * @param start
122   * @param length
123   *          a UTF-8 encoded string representation of an int quantity.
124   * @param radix
125   *          the base to use for conversion.
126   * @param offset
127   *          the starting position after the sign (if exists)
128   * @param radix
129   *          the base to use for conversion.
130   * @param negative
131   *          whether the number is negative.
132   * @return the value represented by the argument
133   * @exception NumberFormatException
134   *              if the argument could not be parsed as an int quantity.
135   */
136  private static int parse(byte[] bytes, int start, int length, int offset,
137      int radix, boolean negative) {
138    int max = Integer.MIN_VALUE / radix;
139    int result = 0, end = start + length;
140    while (offset < end) {
141      int digit = LazyUtils.digit(bytes[offset++], radix);
142      if (digit == -1) {
143        throw new NumberFormatException(LazyUtils.convertToString(bytes, start,
144            length));
145      }
146      if (max > result) {
147        throw new NumberFormatException(LazyUtils.convertToString(bytes, start,
148            length));
149      }
150      int next = result * radix - digit;
151      if (next > result) {
152        throw new NumberFormatException(LazyUtils.convertToString(bytes, start,
153            length));
154      }
155      result = next;
156    }
157    if (!negative) {
158      result = -result;
159      if (result < 0) {
160        throw new NumberFormatException(LazyUtils.convertToString(bytes, start,
161            length));
162      }
163    }
164    return result;
165  }
166
167  /**
168   * Writes out the text representation of an integer using base 10 to an
169   * OutputStream in UTF-8 encoding.
170   * 
171   * Note: division by a constant (like 10) is much faster than division by a
172   * variable. That's one of the reasons that we don't make radix a parameter
173   * here.
174   * 
175   * @param out
176   *          the outputstream to write to
177   * @param i
178   *          an int to write out
179   * @throws IOException
180   */
181  public static void writeUTF8(OutputStream out, int i) throws IOException {
182    if (i == 0) {
183      out.write('0');
184      return;
185    }
186
187    boolean negative = i < 0;
188    if (negative) {
189      out.write('-');
190    } else {
191      // negative range is bigger than positive range, so there is no risk
192      // of overflow here.
193      i = -i;
194    }
195
196    int start = 1000000000;
197    while (i / start == 0) {
198      start /= 10;
199    }
200
201    while (start > 0) {
202      out.write('0' - (i / start % 10));
203      start /= 10;
204    }
205  }
206
207  public static void writeUTF8NoException(OutputStream out, int i) {
208    try {
209      writeUTF8(out, i);
210    } catch (IOException e) {
211      throw new RuntimeException(e);
212    }
213  }
214}