// Path: core/src/main/java/fixio/fixprotocol/fields/FixedPointNumber.java
// public class FixedPointNumber extends Number {
// 
//     /**
//      * Negative or positive scaled value decimal value: <code>scaledValue := value * (10^scale)</code>
//      */
//     private final long scaledValue;
// 
//     /**
//      * If zero or positive, the scale is the number of digits to the right of the decimal point.
//      */
//     private final byte scale;
// 
//     protected FixedPointNumber(byte[] bytes, int offset, int length) {
//         int index = offset;
//         long scaled = 0;
//         int sign = 1;
//         switch (bytes[offset]) {
//             case '-':
//                 sign = -1;
//                 index++;
//                 break;
//             case '+':
//                 sign = +1;
//                 index++;
//                 break;
//             default:
//         }
//         boolean hasScale = false;
//         byte scale = 0;
//         for (int i = index; i < offset + length; i++) {
//             if (bytes[index] == '.') {
//                 hasScale = true;
//             } else {
//                 int digit = (bytes[index] - '0');
//                 scaled = scaled * 10 + digit;
//                 if (hasScale) {
//                     scale++;
//                 }
//             }
//             index++;
//         }
// 
//         scaledValue = scaled * sign;
//         this.scale = scale;
//     }
// 
//     public FixedPointNumber(long scaledValue) {
//         this.scaledValue = scaledValue;
//         this.scale = 0;
//     }
// 
//     public FixedPointNumber(long scaledValue, byte scale) {
//         assert (scale >= 0) : "Scale should not be negative";
//         this.scaledValue = scaledValue;
//         this.scale = scale;
//     }
// 
//     public FixedPointNumber(double value, int precision) {
//         this.scale = (byte) precision;
//         long factor = (long) Math.pow(10.0, scale);
//         scaledValue = Math.round(value * factor);
//     }
// 
//     public FixedPointNumber(String s) {
//         this(s.getBytes(), 0, s.length());
//     }
// 
//     @Override
//     public int intValue() {
//         return (int) (longValue());
//     }
// 
//     @Override
//     public long longValue() {
//         if (scale == 0) {
//             return scaledValue;
//         }
//         return scaledValue / ((long) Math.pow(10.0, scale));
//     }
// 
//     @Override
//     @Deprecated
//     public float floatValue() {
//         return (float) doubleValue();
//     }
// 
//     @Override
//     public double doubleValue() {
//         double factor = Math.pow(10.0, scale);
//         return scaledValue / factor;
//     }
// 
//     public long getScaledValue() {
//         return scaledValue;
//     }
// 
//     public byte getScale() {
//         return scale;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o)
//             return true;
//         if (o == null || !(o instanceof FixedPointNumber))
//             return false;
//         final FixedPointNumber that = (FixedPointNumber) o;
//         return scale == that.scale && scaledValue == that.scaledValue;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = (int) (scaledValue ^ (scaledValue >>> 32));
//         result = 31 * result + (int) scale;
//         return result;
//     }
// 
//     private String insertPointBefore(int idx) {
//         StringBuilder sb = new StringBuilder("0.");
//         for (int i = idx; i < 0; i++) {
//             sb.append("0");
//         }
//         return sb.toString();
//     }
// 
//     @Override
//     public String toString() {
//         if (scale == 0 || scaledValue == 0) {
//             return String.valueOf(scaledValue);
//         }
//         int factor = (int) Math.pow(10.0, scale);
//         long beforePoint = scaledValue / factor;
// 
//         long afterPoint = Math.abs(scaledValue - beforePoint * factor);
//         if (beforePoint == 0 && scaledValue < 0) {
//             return "-0." + afterPoint;
//         } else {
//             String scaledStr = String.valueOf(scaledValue);
//             int idx = scaledStr.length() - scale;
//             String insertPoint;
//             if (idx <= 0) {
//                 insertPoint = insertPointBefore(idx);
//                 idx = 0;
//             } else {
//                 insertPoint = ".";
//             }
//             return new StringBuilder(scaledStr)
//                     .insert(idx, insertPoint)
//                     .toString();
//         }
//     }
// }


import fixio.fixprotocol.fields.FixedPointNumber;
/*
 * Copyright 2014 The FIX.io Project
 *
 * The FIX.io Project 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 fixio.fixprotocol;


/**
 * Represent a ordered list of fields.
 * <p>
 * Provides methods to add new fields.
 * </p>
 */
interface FieldListBuilder<T> {

    T add(FieldType field, String value);

    T add(FieldType field, char value);

    T add(int tagNum, String value);

    T add(DataType type, int tagNum, String value);

    T add(FieldType field, int value);

    T add(int tagNum, int value);

    T add(DataType type, int tagNum, int value);

    T add(FieldType field, long value);

    T add(int tagNum, long value);

    T add(DataType type, int tagNum, long value);

// Path: core/src/main/java/fixio/fixprotocol/fields/FixedPointNumber.java
// public class FixedPointNumber extends Number {
// 
//     /**
//      * Negative or positive scaled value decimal value: <code>scaledValue := value * (10^scale)</code>
//      */
//     private final long scaledValue;
// 
//     /**
//      * If zero or positive, the scale is the number of digits to the right of the decimal point.
//      */
//     private final byte scale;
// 
//     protected FixedPointNumber(byte[] bytes, int offset, int length) {
//         int index = offset;
//         long scaled = 0;
//         int sign = 1;
//         switch (bytes[offset]) {
//             case '-':
//                 sign = -1;
//                 index++;
//                 break;
//             case '+':
//                 sign = +1;
//                 index++;
//                 break;
//             default:
//         }
//         boolean hasScale = false;
//         byte scale = 0;
//         for (int i = index; i < offset + length; i++) {
//             if (bytes[index] == '.') {
//                 hasScale = true;
//             } else {
//                 int digit = (bytes[index] - '0');
//                 scaled = scaled * 10 + digit;
//                 if (hasScale) {
//                     scale++;
//                 }
//             }
//             index++;
//         }
// 
//         scaledValue = scaled * sign;
//         this.scale = scale;
//     }
// 
//     public FixedPointNumber(long scaledValue) {
//         this.scaledValue = scaledValue;
//         this.scale = 0;
//     }
// 
//     public FixedPointNumber(long scaledValue, byte scale) {
//         assert (scale >= 0) : "Scale should not be negative";
//         this.scaledValue = scaledValue;
//         this.scale = scale;
//     }
// 
//     public FixedPointNumber(double value, int precision) {
//         this.scale = (byte) precision;
//         long factor = (long) Math.pow(10.0, scale);
//         scaledValue = Math.round(value * factor);
//     }
// 
//     public FixedPointNumber(String s) {
//         this(s.getBytes(), 0, s.length());
//     }
// 
//     @Override
//     public int intValue() {
//         return (int) (longValue());
//     }
// 
//     @Override
//     public long longValue() {
//         if (scale == 0) {
//             return scaledValue;
//         }
//         return scaledValue / ((long) Math.pow(10.0, scale));
//     }
// 
//     @Override
//     @Deprecated
//     public float floatValue() {
//         return (float) doubleValue();
//     }
// 
//     @Override
//     public double doubleValue() {
//         double factor = Math.pow(10.0, scale);
//         return scaledValue / factor;
//     }
// 
//     public long getScaledValue() {
//         return scaledValue;
//     }
// 
//     public byte getScale() {
//         return scale;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o)
//             return true;
//         if (o == null || !(o instanceof FixedPointNumber))
//             return false;
//         final FixedPointNumber that = (FixedPointNumber) o;
//         return scale == that.scale && scaledValue == that.scaledValue;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = (int) (scaledValue ^ (scaledValue >>> 32));
//         result = 31 * result + (int) scale;
//         return result;
//     }
// 
//     private String insertPointBefore(int idx) {
//         StringBuilder sb = new StringBuilder("0.");
//         for (int i = idx; i < 0; i++) {
//             sb.append("0");
//         }
//         return sb.toString();
//     }
// 
//     @Override
//     public String toString() {
//         if (scale == 0 || scaledValue == 0) {
//             return String.valueOf(scaledValue);
//         }
//         int factor = (int) Math.pow(10.0, scale);
//         long beforePoint = scaledValue / factor;
// 
//         long afterPoint = Math.abs(scaledValue - beforePoint * factor);
//         if (beforePoint == 0 && scaledValue < 0) {
//             return "-0." + afterPoint;
//         } else {
//             String scaledStr = String.valueOf(scaledValue);
//             int idx = scaledStr.length() - scale;
//             String insertPoint;
//             if (idx <= 0) {
//                 insertPoint = insertPointBefore(idx);
//                 idx = 0;
//             } else {
//                 insertPoint = ".";
//             }
//             return new StringBuilder(scaledStr)
//                     .insert(idx, insertPoint)
//                     .toString();
//         }
//     }
// }


// Path: core/src/main/java/fixio/fixprotocol/FieldListBuilder.java
import fixio.fixprotocol.fields.FixedPointNumber;

/*
 * Copyright 2014 The FIX.io Project
 *
 * The FIX.io Project 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 fixio.fixprotocol;


/**
 * Represent a ordered list of fields.
 * <p>
 * Provides methods to add new fields.
 * </p>
 */
interface FieldListBuilder<T> {

    T add(FieldType field, String value);

    T add(FieldType field, char value);

    T add(int tagNum, String value);

    T add(DataType type, int tagNum, String value);

    T add(FieldType field, int value);

    T add(int tagNum, int value);

    T add(DataType type, int tagNum, int value);

    T add(FieldType field, long value);

    T add(int tagNum, long value);

    T add(DataType type, int tagNum, long value);

    T add(FieldType field, FixedPointNumber value);