Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.vxquery.runtime.functions.cast; import java.io.DataOutput; import java.io.IOException; import org.apache.commons.codec.binary.Base64OutputStream; import org.apache.vxquery.datamodel.accessors.atomic.XSBinaryPointable; import org.apache.vxquery.datamodel.accessors.atomic.XSDatePointable; import org.apache.vxquery.datamodel.accessors.atomic.XSDateTimePointable; import org.apache.vxquery.datamodel.accessors.atomic.XSDecimalPointable; import org.apache.vxquery.datamodel.accessors.atomic.XSDurationPointable; import org.apache.vxquery.datamodel.accessors.atomic.XSQNamePointable; import org.apache.vxquery.datamodel.accessors.atomic.XSTimePointable; import org.apache.vxquery.datamodel.util.DateTime; import org.apache.vxquery.datamodel.values.ValueTag; import org.apache.vxquery.exceptions.SystemException; import org.apache.vxquery.runtime.functions.util.FunctionHelper; import edu.uci.ics.hyracks.data.std.primitive.BooleanPointable; import edu.uci.ics.hyracks.data.std.primitive.BytePointable; import edu.uci.ics.hyracks.data.std.primitive.DoublePointable; import edu.uci.ics.hyracks.data.std.primitive.FloatPointable; import edu.uci.ics.hyracks.data.std.primitive.IntegerPointable; import edu.uci.ics.hyracks.data.std.primitive.LongPointable; import edu.uci.ics.hyracks.data.std.primitive.ShortPointable; import edu.uci.ics.hyracks.data.std.primitive.UTF8StringPointable; import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage; import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream; public class CastToStringOperation extends AbstractCastToOperation { private ByteArrayAccessibleOutputStream baaos = new ByteArrayAccessibleOutputStream(); private ArrayBackedValueStorage abvsInner = new ArrayBackedValueStorage(); private DataOutput dOutInner = abvsInner.getDataOutput(); int returnTag = ValueTag.XS_STRING_TAG; private final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; @Override public void convertAnyURI(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { dOut.write(returnTag); dOut.write(stringp.getByteArray(), stringp.getStartOffset(), stringp.getLength()); } @Override public void convertBase64Binary(XSBinaryPointable binaryp, DataOutput dOut) throws SystemException, IOException { baaos.reset(); @SuppressWarnings("resource") Base64OutputStream b64os = new Base64OutputStream(baaos, true); b64os.write(binaryp.getByteArray(), binaryp.getStartOffset() + 2, binaryp.getLength() - 2); dOut.write(returnTag); dOut.write((byte) ((baaos.size() >>> 8) & 0xFF)); dOut.write((byte) ((baaos.size() >>> 0) & 0xFF)); dOut.write(baaos.getByteArray(), 0, baaos.size()); } @Override public void convertBoolean(BooleanPointable boolp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); if (boolp.getBoolean()) { FunctionHelper.writeCharSequence("true", dOutInner); } else { FunctionHelper.writeCharSequence("false", dOutInner); } sendStringDataOutput(dOut); } @Override public void convertDate(XSDatePointable datep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeDateAsString(datep, dOutInner); FunctionHelper.writeTimezoneAsString(datep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertDatetime(XSDateTimePointable datetimep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeDateAsString(datetimep, dOutInner); FunctionHelper.writeChar('T', dOutInner); FunctionHelper.writeTimeAsString(datetimep, dOutInner); FunctionHelper.writeTimezoneAsString(datetimep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertDecimal(XSDecimalPointable decp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); byte decimalPlace = decp.getDecimalPlace(); long value = decp.getDecimalValue(); byte nDigits = decp.getDigitCount(); if (!FunctionHelper.isNumberPostive(value)) { // Negative result, but the rest of the calculations can be based on a positive value. FunctionHelper.writeChar('-', dOutInner); value *= -1; } if (value == 0) { FunctionHelper.writeChar('0', dOutInner); } else { long pow10 = (long) Math.pow(10, nDigits - 1); int start = Math.max(decimalPlace, nDigits - 1); int end = Math.min(0, decimalPlace); for (int i = start; i >= end; --i) { if (i >= nDigits || i < 0) { FunctionHelper.writeChar('0', dOutInner); } else { FunctionHelper.writeChar((char) ('0' + (value / pow10)), dOutInner); value %= pow10; pow10 /= 10; } if (i == decimalPlace && value > 0) { FunctionHelper.writeChar('.', dOutInner); } } } sendStringDataOutput(dOut); } @Override public void convertDouble(DoublePointable doublep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); double value = doublep.getDouble(); if (Double.isInfinite(value)) { if (value == Double.NEGATIVE_INFINITY) { FunctionHelper.writeCharSequence("-", dOutInner); } FunctionHelper.writeCharSequence("INF", dOutInner); sendStringDataOutput(dOut); } else if (Double.isNaN(value)) { FunctionHelper.writeCharSequence("NaN", dOutInner); sendStringDataOutput(dOut); } else if (value == -0.0 || value == 0.0) { long bits = Double.doubleToLongBits(value); boolean negative = ((bits >> 63) == 0) ? false : true; if (negative) { FunctionHelper.writeChar('-', dOutInner); } FunctionHelper.writeCharSequence("0", dOutInner); sendStringDataOutput(dOut); } else if (Math.abs(value) >= 0.000001 && Math.abs(value) <= 10000000) { //the jdk (toString function) does not output number in desired format when //a number is between one and ten million, so we take care of this //case separately here. CastToDecimalOperation castToDecimal = new CastToDecimalOperation(); castToDecimal.convertDouble(doublep, dOutInner); XSDecimalPointable decp = (XSDecimalPointable) XSDecimalPointable.FACTORY.createPointable(); decp.set(abvsInner.getByteArray(), abvsInner.getStartOffset() + 1, XSDecimalPointable.TYPE_TRAITS.getFixedLength()); if (Math.abs(value) <= 1000000) { convertDecimal(decp, dOut); } else { decimalToScientificNotn(decp, dOut); } } else { dOut.write(returnTag); dOut.writeUTF(Double.toString(value)); } } public void convertDoubleCanonical(DoublePointable doublep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); double value = doublep.getDouble(); dOut.write(returnTag); dOut.writeUTF(Double.toString(value)); return; } @Override public void convertDTDuration(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); long dayTime = longp.getLong(); if (dayTime == 0) { FunctionHelper.writeCharSequence("PT0S", dOutInner); } else { if (dayTime < 0) { FunctionHelper.writeChar('-', dOutInner); dayTime *= -1; } FunctionHelper.writeChar('P', dOutInner); // Day if (dayTime >= DateTime.CHRONON_OF_DAY) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_DAY, 1, dOutInner); FunctionHelper.writeChar('D', dOutInner); dayTime %= DateTime.CHRONON_OF_DAY; } if (dayTime > 0) { FunctionHelper.writeChar('T', dOutInner); } // Hour if (dayTime >= DateTime.CHRONON_OF_HOUR) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_HOUR, 1, dOutInner); FunctionHelper.writeChar('H', dOutInner); dayTime %= DateTime.CHRONON_OF_HOUR; } // Minute if (dayTime >= DateTime.CHRONON_OF_MINUTE) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_MINUTE, 1, dOutInner); FunctionHelper.writeChar('M', dOutInner); dayTime %= DateTime.CHRONON_OF_MINUTE; } // Milliseconds if (dayTime > 0) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_SECOND, 1, dOutInner); if (dayTime % DateTime.CHRONON_OF_SECOND != 0) { FunctionHelper.writeChar('.', dOutInner); FunctionHelper.writeNumberWithPadding(dayTime % DateTime.CHRONON_OF_SECOND, 3, dOutInner); } FunctionHelper.writeChar('S', dOutInner); } } sendStringDataOutput(dOut); } @Override public void convertDuration(XSDurationPointable durationp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); int yearMonth = durationp.getYearMonth(); long dayTime = durationp.getDayTime(); if (yearMonth < 0 || dayTime < 0) { FunctionHelper.writeChar('-', dOutInner); yearMonth *= -1; dayTime *= -1; } FunctionHelper.writeChar('P', dOutInner); // Year if (yearMonth >= 12) { FunctionHelper.writeNumberWithPadding(yearMonth / 12, 1, dOutInner); FunctionHelper.writeChar('Y', dOutInner); } // Month if (yearMonth % 12 > 0) { FunctionHelper.writeNumberWithPadding(yearMonth % 12, 1, dOutInner); FunctionHelper.writeChar('M', dOutInner); } // Day if (dayTime >= DateTime.CHRONON_OF_DAY) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_DAY, 1, dOutInner); FunctionHelper.writeChar('D', dOutInner); dayTime %= DateTime.CHRONON_OF_DAY; } if (dayTime > 0) { FunctionHelper.writeChar('T', dOutInner); } // Hour if (dayTime >= DateTime.CHRONON_OF_HOUR) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_HOUR, 1, dOutInner); FunctionHelper.writeChar('H', dOutInner); dayTime %= DateTime.CHRONON_OF_HOUR; } // Minute if (dayTime >= DateTime.CHRONON_OF_MINUTE) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_MINUTE, 1, dOutInner); FunctionHelper.writeChar('M', dOutInner); dayTime %= DateTime.CHRONON_OF_MINUTE; } // Milliseconds if (dayTime > 0) { FunctionHelper.writeNumberWithPadding(dayTime / DateTime.CHRONON_OF_SECOND, 1, dOutInner); if (dayTime % DateTime.CHRONON_OF_SECOND != 0) { FunctionHelper.writeChar('.', dOutInner); FunctionHelper.writeNumberWithPadding(dayTime % DateTime.CHRONON_OF_SECOND, 3, dOutInner); } FunctionHelper.writeChar('S', dOutInner); } sendStringDataOutput(dOut); } @Override public void convertFloat(FloatPointable floatp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); float value = floatp.getFloat(); if (!Float.isInfinite(value) && !Float.isNaN(value) && Math.abs(value) >= 0.000001 && Math.abs(value) <= 1000000) { CastToDecimalOperation castToDecimal = new CastToDecimalOperation(); castToDecimal.convertFloat(floatp, dOutInner); XSDecimalPointable decp = (XSDecimalPointable) XSDecimalPointable.FACTORY.createPointable(); decp.set(abvsInner.getByteArray(), abvsInner.getStartOffset() + 1, abvsInner.getLength()); convertDecimal(decp, dOut); } else if (value == -0.0f || value == 0.0f) { long bits = Float.floatToIntBits(value); boolean negative = ((bits >> 31) == 0) ? false : true; if (negative) { FunctionHelper.writeChar('-', dOutInner); } FunctionHelper.writeCharSequence("0", dOutInner); sendStringDataOutput(dOut); } else { convertFloatCanonical(floatp, dOut); } } public void convertFloatCanonical(FloatPointable floatp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); float value = floatp.getFloat(); if (Float.isInfinite(value)) { if (value == Float.NEGATIVE_INFINITY) { FunctionHelper.writeCharSequence("-", dOutInner); } FunctionHelper.writeCharSequence("INF", dOutInner); } else if (Float.isNaN(value)) { FunctionHelper.writeCharSequence("NaN", dOutInner); } else { dOut.write(returnTag); dOut.writeUTF(Float.toString(value)); return; } sendStringDataOutput(dOut); } @Override public void convertGDay(XSDatePointable datep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); // Default FunctionHelper.writeChar('-', dOutInner); // Year FunctionHelper.writeChar('-', dOutInner); // Month FunctionHelper.writeChar('-', dOutInner); // Day FunctionHelper.writeNumberWithPadding(datep.getDay(), 2, dOutInner); // Timezone FunctionHelper.writeTimezoneAsString(datep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertGMonth(XSDatePointable datep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); // Default FunctionHelper.writeChar('-', dOutInner); // Year FunctionHelper.writeChar('-', dOutInner); // Month FunctionHelper.writeNumberWithPadding(datep.getMonth(), 2, dOutInner); // Timezone FunctionHelper.writeTimezoneAsString(datep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertGMonthDay(XSDatePointable datep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); // Default FunctionHelper.writeChar('-', dOutInner); // Year FunctionHelper.writeChar('-', dOutInner); // Month FunctionHelper.writeNumberWithPadding(datep.getMonth(), 2, dOutInner); FunctionHelper.writeChar('-', dOutInner); // Day FunctionHelper.writeNumberWithPadding(datep.getDay(), 2, dOutInner); // Timezone FunctionHelper.writeTimezoneAsString(datep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertGYear(XSDatePointable datep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); // Year FunctionHelper.writeNumberWithPadding(datep.getYear(), 4, dOutInner); // Timezone FunctionHelper.writeTimezoneAsString(datep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertGYearMonth(XSDatePointable datep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); // Year FunctionHelper.writeNumberWithPadding(datep.getYear(), 4, dOutInner); FunctionHelper.writeChar('-', dOutInner); // Month FunctionHelper.writeNumberWithPadding(datep.getMonth(), 2, dOutInner); // Timezone FunctionHelper.writeTimezoneAsString(datep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertHexBinary(XSBinaryPointable binaryp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); for (int index = 0; index < binaryp.getBinaryLength(); ++index) { int bi = binaryp.getByteArray()[binaryp.getBinaryStart() + index] & 0xff; FunctionHelper.writeChar(hex[(bi >> 4)], dOutInner); FunctionHelper.writeChar(hex[(bi & 0xf)], dOutInner); } sendStringDataOutput(dOut); } @Override public void convertInteger(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.getLong(), 1, dOutInner); sendStringDataOutput(dOut); } @Override public void convertNotation(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { dOut.write(returnTag); dOut.write(stringp.getByteArray(), stringp.getStartOffset(), stringp.getLength()); } @Override public void convertQName(XSQNamePointable qnamep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); if (qnamep.getPrefixUTFLength() > 0) { dOutInner.write(qnamep.getByteArray(), qnamep.getStartOffset() + qnamep.getUriLength() + 2, qnamep.getPrefixUTFLength()); FunctionHelper.writeChar(':', dOutInner); } dOutInner.write(qnamep.getByteArray(), qnamep.getStartOffset() + qnamep.getUriLength() + qnamep.getPrefixLength() + 2, qnamep.getLocalNameUTFLength()); sendStringDataOutput(dOut); } @Override public void convertString(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { dOut.write(returnTag); dOut.write(stringp.getByteArray(), stringp.getStartOffset(), stringp.getLength()); } @Override public void convertTime(XSTimePointable timep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeTimeAsString(timep, dOutInner); FunctionHelper.writeTimezoneAsString(timep, dOutInner); sendStringDataOutput(dOut); } @Override public void convertUntypedAtomic(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { convertString(stringp, dOut); } @Override public void convertYMDuration(IntegerPointable intp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); int yearMonth = intp.getInteger(); if (yearMonth == 0) { FunctionHelper.writeCharSequence("P0M", dOutInner); } else { if (yearMonth < 0) { FunctionHelper.writeChar('-', dOutInner); yearMonth *= -1; } FunctionHelper.writeChar('P', dOutInner); // Year if (yearMonth >= 12) { FunctionHelper.writeNumberWithPadding(yearMonth / 12, 1, dOutInner); FunctionHelper.writeChar('Y', dOutInner); } // Month if (yearMonth % 12 > 0) { FunctionHelper.writeNumberWithPadding(yearMonth % 12, 1, dOutInner); FunctionHelper.writeChar('M', dOutInner); } } sendStringDataOutput(dOut); } /** * Derived Numeric Datatypes */ public void convertByte(BytePointable bytep, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(bytep.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertInt(IntegerPointable intp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(intp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertLong(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertNegativeInteger(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertNonNegativeInteger(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertNonPositiveInteger(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertPositiveInteger(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertShort(ShortPointable shortp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(shortp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertUnsignedByte(ShortPointable shortp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(shortp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertUnsignedInt(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertUnsignedLong(LongPointable longp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(longp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } public void convertUnsignedShort(IntegerPointable intp, DataOutput dOut) throws SystemException, IOException { abvsInner.reset(); FunctionHelper.writeNumberWithPadding(intp.longValue(), 1, dOutInner); sendStringDataOutput(dOut); } /** * Derived String Data Types */ @Override public void convertEntity(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertID(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertIDREF(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertLanguage(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertName(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertNCName(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertNMToken(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertNormalizedString(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } @Override public void convertToken(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException { // TODO Add check to verify string consists of limited character set. convertString(stringp, dOut); } private void sendStringDataOutput(DataOutput dOut) throws SystemException, IOException { dOut.write(returnTag); dOut.write((byte) ((abvsInner.getLength() >>> 8) & 0xFF)); dOut.write((byte) ((abvsInner.getLength() >>> 0) & 0xFF)); dOut.write(abvsInner.getByteArray(), abvsInner.getStartOffset(), abvsInner.getLength()); } public void decimalToScientificNotn(XSDecimalPointable decp, DataOutput dOut) throws SystemException, IOException { byte decimalPlace = decp.getDecimalPlace(); long value = decp.getDecimalValue(); byte nDigits = decp.getDigitCount(); abvsInner.reset(); if (!FunctionHelper.isNumberPostive(value)) { // Negative result, but the rest of the calculations can be based on a positive value. FunctionHelper.writeChar('-', dOutInner); value *= -1; } if (value == 0) { FunctionHelper.writeChar('0', dOutInner); } else { long pow10 = (long) Math.pow(10, nDigits - 1); FunctionHelper.writeNumberWithPadding((value / pow10), 0, dOutInner); FunctionHelper.writeChar('.', dOutInner); long mod = value % pow10; FunctionHelper.writeNumberWithPadding(mod, (nDigits - 1), dOutInner); FunctionHelper.writeChar('E', dOutInner); long power = (nDigits - 1) - decimalPlace; FunctionHelper.writeNumberWithPadding(power, 0, dOutInner); } sendStringDataOutput(dOut); } }