gt:                     String name = readString();
context: /**
   * Copyright (c) 2010-2018 by the respective copyright holders.
   *
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   */
  package org.openhab.binding.homematic.internal.communicator.message;
  
  import java.io.EOFException;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.UnsupportedEncodingException;
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.math.RoundingMode;
  import java.text.ParseException;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.Date;
  import java.util.List;
  import java.util.Map;
  import java.util.TreeMap;
  
  import org.apache.commons.io.IOUtils;
  import org.apache.commons.lang.ArrayUtils;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * Handles BIN-RPC request and response messages to communicate with a Homematic gateway.
   *
   * @author Gerhard Riegler - Initial contribution
   */
  public class BinRpcMessage implements RpcRequest<byte[]>, RpcResponse {
      private final Logger logger = LoggerFactory.getLogger(BinRpcMessage.class);
  
      public enum TYPE {
          REQUEST,
          RESPONSE;
      }
  
      private Object[] messageData;
      private byte binRpcData[];
      private int offset;
  
      private String methodName;
      private TYPE type;
      private int args;
      private String encoding;
  
      public BinRpcMessage(String methodName, String encoding) {
          this(methodName, TYPE.REQUEST, encoding);
      }
  
      /**
       * Creates a new request with the specified methodName.
       */
      public BinRpcMessage(String methodName, TYPE type, String encoding) {
          this.methodName = methodName;
          this.type = type;
          this.encoding = encoding;
          createHeader();
      }
  
      /**
       * Decodes a BIN-RPC message from the given InputStream.
       */
      public BinRpcMessage(InputStream is, boolean methodHeader, String encoding) throws IOException {
          this.encoding = encoding;
          byte sig[] = new byte[8];
          int length = is.read(sig, 0, 4);
          if (length != 4) {
              throw new EOFException("Only " + length + " bytes received reading signature");
          }
          validateBinXSignature(sig);
          length = is.read(sig, 4, 4);
          if (length != 4) {
              throw new EOFException("Only " + length + " bytes received reading message length");
          }
          int datasize = (new BigInteger(ArrayUtils.subarray(sig, 4, 8))).intValue();
          byte[] message = ArrayUtils.addAll(sig, IOUtils.toByteArray(is, datasize));
          decodeMessage(message, methodHeader);
      }
  
      private void validateBinXSignature(byte[] sig) throws UnsupportedEncodingException {
          if (sig[0] != 'B' || sig[1] != 'i' || sig[2] != 'n') {
              throw new UnsupportedEncodingException("No BinX signature");
          }
      }
  
      /**
       * Decodes a BIN-RPC message from the given byte array.
       */
      public BinRpcMessage(byte[] message, boolean methodHeader, String encoding) throws IOException, ParseException {
          this.encoding = encoding;
          if (message.length < 8) {
              throw new EOFException("Only " + message.length + " bytes received");
          }
          validateBinXSignature(message);
          decodeMessage(message, methodHeader);
      }
  
      private void decodeMessage(byte[] message, boolean methodHeader) throws IOException {
          binRpcData = message;
  
          offset = 8;
  
          if (methodHeader) {
              methodName = readString();
              readInt();
          }
          generateResponseData();
      }
  
      public void setType(TYPE type) {
          binRpcData[3] = type == TYPE.RESPONSE ? (byte) 1 : (byte) 0;
      }
  
      private void generateResponseData() throws IOException {
          offset = 8 + (methodName != null ? methodName.length() + 8 : 0);
          List<Object> values = new ArrayList<Object>();
          while (offset < binRpcData.length) {
              values.add(readRpcValue());
          }
          messageData = values.toArray();
          values.clear();
      }
  
      private void createHeader() {
          binRpcData = new byte[256];
          addString("Bin ");
          setType(type);
          addInt(0); // placeholder content length
          if (methodName != null) {
              addInt(methodName.length());
              addString(methodName);
              addInt(0); // placeholder arguments
          }
          setInt(4, offset - 8);
      }
  
      /**
       * Adds arguments to the method.
       */
      @Override
      public void addArg(Object argument) {
          addObject(argument);
          setInt(4, offset - 8);
  
          if (methodName != null) {
              setInt(12 + methodName.length(), ++args);
          }
      }
  
      public int getArgCount() {
          return args;
      }
  
      @Override
      public String getMethodName() {
          return methodName;
      }
  
      @Override
      public byte[] createMessage() {
          trimBinRpcData();
          return binRpcData;
      }
  
      private void trimBinRpcData() {
          byte[] trimmed = new byte[offset];
          System.arraycopy(binRpcData, 0, trimmed, 0, offset);
          binRpcData = trimmed;
      }
  
      @Override
      public Object[] getResponseData() {
          return messageData;
      }
  
      // read rpc values
      private int readInt() {
          byte bi[] = new byte[4];
          System.arraycopy(binRpcData, offset, bi, 0, 4);
          offset += 4;
          return (new BigInteger(bi)).intValue();
      }
  
      private String readString() throws UnsupportedEncodingException {
          int len = readInt();
          offset += len;
          return new String(binRpcData, offset - len, len, encoding);
      }
  
      private Object readRpcValue() throws IOException {
          int type = readInt();
          switch (type) {
              case 1:
                  return new Integer(readInt());
              case 2:
                  return binRpcData[offset++] != 0 ? Boolean.TRUE : Boolean.FALSE;
              case 3:
                  return readString();
              case 4:
                  int mantissa = readInt();
                  int exponent = readInt();
                  BigDecimal bd = new BigDecimal((double) mantissa / (double) (1 << 30) * Math.pow(2, exponent));
                  return bd.setScale(6, RoundingMode.HALF_DOWN).doubleValue();
              case 5:
                  return new Date(readInt() * 1000);
              case 0x100:
                  // Array
                  int numElements = readInt();
                  Collection<Object> array = new ArrayList<Object>();
                  while (numElements-- > 0) {
                      array.add(readRpcValue());
                  }
                  return array.toArray();
              case 0x101:
                  // Struct
                  numElements = readInt();
                  Map<String, Object> struct = new TreeMap<String, Object>();
                  while (numElements-- > 0) {
  