private static int readJsonNumber(String json, List<Object> value, int startIndex, int len) {
        int endIndex = len;

        StringBuilder builder = new StringBuilder().append(json.charAt(startIndex));

        boolean hasDot = false;
        boolean hasExp = false;
        // add first digit
        for (int i = startIndex + 1; i < len; i++) {
            char n = json.charAt(i);
            if (n >= '0' && n <= '9') {
                builder.append(n);
            } else if (!hasDot && n == '.') {
                hasDot = true;
                builder.append(n);
            } else if (!hasExp && (n == 'e' || n == 'E')) {
                hasDot = true;
                hasExp = true;
                builder.append(n);
                if (i + 1 < len) {
                    char next = json.charAt(i + 1);
                    if (next == '+' || next == '-') {
                        builder.append(next);
                        i++;
                    }
                }

                boolean hasNum = false;
                for (int j = i + 1; j < len; j++) {
                    char next = json.charAt(j);
                    if (next >= '0' && next <= '9') {
                        hasNum = true;
                        builder.append(next);
                    } else {
                        if (!hasNum) {
                            throw new IllegalArgumentException("Expect number after exponent at " + i);
                        }
                        endIndex = j + 1;
                        break;
                    }
                }
                break;
            } else {
                endIndex = i;
                break;
            }
        }

        if (hasDot) {
            if (hasExp || builder.length() >= 21) {
                value.add(new BigDecimal(builder.toString()));
            } else if (builder.length() >= 11) {
                value.add(Double.parseDouble(builder.toString()));
            } else {
                value.add(Float.parseFloat(builder.toString()));
            }
        } else {
            if (hasExp || builder.length() >= 19) {
                value.add(new BigInteger(builder.toString()));
            } else if (builder.length() >= 10) {
                value.add(Long.parseLong(builder.toString()));
            } else {
                value.add(Integer.parseInt(builder.toString()));
            }
        }

        return endIndex;
    }
Normalizes given directory by appending back slash if it does exist.

@param dir original directory
@return normalized directory
clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseUtils.java