private static void encodeSingleValue(LittleEndianOutput out, Object value) {
    if (value == EMPTY_REPRESENTATION) {
      out.writeByte(TYPE_EMPTY);
      out.writeLong(0L);
      return;
    }
    if (value instanceof Boolean) {
      Boolean bVal = ((Boolean) value);
      out.writeByte(TYPE_BOOLEAN);
      long longVal = bVal.booleanValue() ? 1L : 0L;
      out.writeLong(longVal);
      return;
    }
    if (value instanceof Double) {
      Double dVal = (Double) value;
      out.writeByte(TYPE_NUMBER);
      out.writeDouble(dVal.doubleValue());
      return;
    }
    if (value instanceof String) {
      String val = (String) value;
      out.writeByte(TYPE_STRING);
      StringUtil.writeUnicodeString(out, val);
      return;
    }
    if (value instanceof ErrorConstant) {
      ErrorConstant ecVal = (ErrorConstant) value;
      out.writeByte(TYPE_ERROR_CODE);
      long longVal = ecVal.getErrorCode();
      out.writeLong(longVal);
      return;
    }

    throw new IllegalStateException("Unexpected value type (" + value.getClass().getName() + "'");
  }
/** @author Josh Micich */
public final class TestConstantValueParser extends TestCase {
  private static final Object[] SAMPLE_VALUES = {
    Boolean.TRUE,
    null,
    new Double(1.1),
    "Sample text",
    ErrorConstant.valueOf(HSSFErrorConstants.ERROR_DIV_0),
  };
  private static final byte[] SAMPLE_ENCODING =
      HexRead.readFromString(
          "04 01 00 00 00 00 00 00 00 "
              + "00 00 00 00 00 00 00 00 00 "
              + "01 9A 99 99 99 99 99 F1 3F "
              + "02 0B 00 00 53 61 6D 70 6C 65 20 74 65 78 74 "
              + "10 07 00 00 00 00 00 00 00");

  public void testGetEncodedSize() {
    int actual = ConstantValueParser.getEncodedSize(SAMPLE_VALUES);
    assertEquals(51, actual);
  }

  public void testEncode() {
    int size = ConstantValueParser.getEncodedSize(SAMPLE_VALUES);
    byte[] data = new byte[size];

    ConstantValueParser.encode(new LittleEndianByteArrayOutputStream(data, 0), SAMPLE_VALUES);

    if (!Arrays.equals(data, SAMPLE_ENCODING)) {
      fail("Encoding differs");
    }
  }

  public void testDecode() {
    LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(SAMPLE_ENCODING);

    Object[] values = ConstantValueParser.parse(in, 4);
    for (int i = 0; i < values.length; i++) {
      if (!isEqual(SAMPLE_VALUES[i], values[i])) {
        fail("Decoded result differs");
      }
    }
  }

  private static boolean isEqual(Object a, Object b) {
    if (a == null) {
      return b == null;
    }
    return a.equals(b);
  }
}
 private static Object readAConstantValue(LittleEndianInput in) {
   byte grbit = in.readByte();
   switch (grbit) {
     case TYPE_EMPTY:
       in.readLong(); // 8 byte 'not used' field
       return EMPTY_REPRESENTATION;
     case TYPE_NUMBER:
       return new Double(in.readDouble());
     case TYPE_STRING:
       return StringUtil.readUnicodeString(in);
     case TYPE_BOOLEAN:
       return readBoolean(in);
     case TYPE_ERROR_CODE:
       int errCode = in.readUShort();
       // next 6 bytes are unused
       in.readUShort();
       in.readInt();
       return ErrorConstant.valueOf(errCode);
   }
   throw new RuntimeException("Unknown grbit value (" + grbit + ")");
 }