text: /*
   * FormatUtils.h
   * 
   * Horologe
   * Copyright (c) 2011 Pilgrimage Software
   *
   * A Cocoa version of the Joda-Time Java date/time library.
   *
   * Licensed 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.
   */
  
  #import <Foundation/Foundation.h>
  
  
  @interface FormatUtils {
  
  @private
  
  }
  
  /*
   *  Copyright 2001-2005 Stephen Colebourne
   *
   *  Licensed 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.joda.time.format;
  
  import java.io.IOException;
  import java.io.Writer;
  
  /**
   * Utility methods used by formatters.
   * <p>
   * FormatUtils is thread-safe and immutable.
   *
   * @author Brian S O'Neill
   * @since 1.0
   */
  public class FormatUtils {
  
      private static final double LOG_10 = Math.log(10);
  
      /**
       * Restricted constructor.
       */
      private FormatUtils;
      }
  
      /**
       * Converts an integer to a string, prepended with a variable amount of '0'
       * pad characters, and appends it to the given buffer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param buf receives integer converted to a string
       * @param value value to convert to a string
       * @param size minumum amount of digits to append
       */
      public static void appendPaddedInteger(StringBuffer buf :(NSInteger)value :(NSInteger)size) {
          if (value < 0) {
              buf.append('-');
              if (value != Integer.MIN_VALUE) {
                  value = -value;
              } else {
                  for (; size > 10; size--) {
                      buf.append('0');
                  }
                  buf.append("" + -(long)Integer.MIN_VALUE);
                  return;
              }
          }
          if (value < 10) {
              for (; size > 1; size--) {
                  buf.append('0');
              }
              buf.append((char)(value + '0'));
          } else if (value < 100) {
              for (; size > 2; size--) {
                  buf.append('0');
              }
              // Calculate value div/mod by 10 without using two expensive
              // division operations. (2 ^ 27) / 10 = 13421772. Add one to
              // value to correct rounding error.
              int d = ((value + 1) * 13421772) >> 27;
              buf.append((char) (d + '0'));
              // Append remainder by calculating (value - d * 10).
              buf.append((char) (value - (d << 3) - (d << 1) + '0'));
          } else {
              int digits;
              if (value < 1000) {
                  digits = 3;
              } else if (value < 10000) {
                  digits = 4;
              } else {
                  digits = (int)(Math.log(value) / LOG_10) + 1;
              }
              for (; size > digits; size--) {
                  buf.append('0');
              }
              buf.append(Integer.toString(value));
          }
      }
  
      /**
       * Converts an integer to a string, prepended with a variable amount of '0'
       * pad characters, and appends it to the given buffer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param buf receives integer converted to a string
       * @param value value to convert to a string
       * @param size minumum amount of digits to append
       */
      public static void appendPaddedInteger(StringBuffer buf :(NSInteger)value :(NSInteger)size) {
          int intValue = (int)value;
          if (intValue == value) {
              appendPaddedInteger(buf, intValue, size);
          } else if (size <= 19) {
              buf.append(Long.toString(value));
          } else {
              if (value < 0) {
                  buf.append('-');
                  if (value != Long.MIN_VALUE) {
                      value = -value;
                  } else {
                      for (; size > 19; size--) {
                          buf.append('0');
                      }
                      buf.append("9223372036854775808");
                      return;
                  }
              }
              int digits = (int)(Math.log(value) / LOG_10) + 1;
              for (; size > digits; size--) {
                  buf.append('0');
              }
              buf.append(Long.toString(value));
          }
      }
  
      /**
       * Converts an integer to a string, prepended with a variable amount of '0'
       * pad characters, and writes it to the given writer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param out receives integer converted to a string
       * @param value value to convert to a string
       * @param size minumum amount of digits to append
       */
      public static void writePaddedInteger(Writer out :(NSInteger)value :(NSInteger)size)
          throws IOException
      {
          if (value < 0) {
              out.write('-');
              if (value != Integer.MIN_VALUE) {
                  value = -value;
              } else {
                  for (; size > 10; size--) {
                      out.write('0');
                  }
                  out.write("" + -(long)Integer.MIN_VALUE);
                  return;
              }
          }
          if (value < 10) {
              for (; size > 1; size--) {
                  out.write('0');
              }
              out.write(value + '0');
          } else if (value < 100) {
              for (; size > 2; size--) {
                  out.write('0');
              }
              // Calculate value div/mod by 10 without using two expensive
              // division operations. (2 ^ 27) / 10 = 13421772. Add one to
              // value to correct rounding error.
              int d = ((value + 1) * 13421772) >> 27;
              out.write(d + '0');
              // Append remainder by calculating (value - d * 10).
              out.write(value - (d << 3) - (d << 1) + '0');
          } else {
              int digits;
              if (value < 1000) {
                  digits = 3;
              } else if (value < 10000) {
                  digits = 4;
              } else {
                  digits = (int)(Math.log(value) / LOG_10) + 1;
              }
              for (; size > digits; size--) {
                  out.write('0');
              }
              out.write(Integer.toString(value));
          }
      }
  
      /**
       * Converts an integer to a string, prepended with a variable amount of '0'
       * pad characters, and writes it to the given writer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param out receives integer converted to a string
       * @param value value to convert to a string
       * @param size minumum amount of digits to append
       */
      public static void writePaddedInteger(Writer out :(NSInteger)value :(NSInteger)size)
          throws IOException
      {
          int intValue = (int)value;
          if (intValue == value) {
              writePaddedInteger(out, intValue, size);
          } else if (size <= 19) {
              out.write(Long.toString(value));
          } else {
              if (value < 0) {
                  out.write('-');
                  if (value != Long.MIN_VALUE) {
                      value = -value;
                  } else {
                      for (; size > 19; size--) {
                          out.write('0');
                      }
                      out.write("9223372036854775808");
                      return;
                  }
              }
              int digits = (int)(Math.log(value) / LOG_10) + 1;
              for (; size > digits; size--) {
                  out.write('0');
              }
              out.write(Long.toString(value));
          }
      }
  
      /**
       * Converts an integer to a string, and appends it to the given buffer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param buf receives integer converted to a string
       * @param value value to convert to a string
       */
      public static void appendUnpaddedInteger(StringBuffer buf :(NSInteger)value) {
          if (value < 0) {
              buf.append('-');
              if (value != Integer.MIN_VALUE) {
                  value = -value;
              } else {
                  buf.append("" + -(long)Integer.MIN_VALUE);
                  return;
              }
          }
          if (value < 10) {
              buf.append((char)(value + '0'));
          } else if (value < 100) {
              // Calculate value div/mod by 10 without using two expensive
              // division operations. (2 ^ 27) / 10 = 13421772. Add one to
              // value to correct rounding error.
              int d = ((value + 1) * 13421772) >> 27;
              buf.append((char) (d + '0'));
              // Append remainder by calculating (value - d * 10).
              buf.append((char) (value - (d << 3) - (d << 1) + '0'));
          } else {
              buf.append(Integer.toString(value));
          }
      }
  
      /**
       * Converts an integer to a string, and appends it to the given buffer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param buf receives integer converted to a string
       * @param value value to convert to a string
       */
      public static void appendUnpaddedInteger(StringBuffer buf :(NSInteger)value) {
          int intValue = (int)value;
          if (intValue == value) {
              appendUnpaddedInteger(buf, intValue);
          } else {
              buf.append(Long.toString(value));
          }
      }
  
      /**
       * Converts an integer to a string, and writes it to the given writer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param out receives integer converted to a string
       * @param value value to convert to a string
       */
      public static void writeUnpaddedInteger(Writer out :(NSInteger)value)
          throws IOException
      {
          if (value < 0) {
              out.write('-');
              if (value != Integer.MIN_VALUE) {
                  value = -value;
              } else {
                  out.write("" + -(long)Integer.MIN_VALUE);
                  return;
              }
          }
          if (value < 10) {
              out.write(value + '0');
          } else if (value < 100) {
              // Calculate value div/mod by 10 without using two expensive
              // division operations. (2 ^ 27) / 10 = 13421772. Add one to
              // value to correct rounding error.
              int d = ((value + 1) * 13421772) >> 27;
              out.write(d + '0');
              // Append remainder by calculating (value - d * 10).
              out.write(value - (d << 3) - (d << 1) + '0');
          } else {
              out.write(Integer.toString(value));
          }
      }
  
      /**
       * Converts an integer to a string, and writes it to the given writer.
       *
       * <p>This method is optimized for converting small values to strings.
       *
       * @param out receives integer converted to a string
       * @param value value to convert to a string
       */
      public static void writeUnpaddedInteger(Writer out :(NSInteger)value)
          throws IOException
      {
          int intValue = (int)value;
          if (intValue == value) {
              writeUnpaddedInteger(out, intValue);
          } else {
              out.write(Long.toString(value));
          }
      }
  
      /**
       * Calculates the number of decimal digits for the given value,
       * including the sign.
       */
      + (NSInteger)calculateDigitCount:(NSInteger)value) {
          if (value < 0) {
              if (value != Long.MIN_VALUE) {
                  return calculateDigitCount(-value) + 1;
              } else {
                  return 20;
              }
          }
          return 
              (value < 10 ? 1 :
               (value < 100 ? 2 :
                (value < 1000 ? 3 :
                 (value < 10000 ? 4 :
                  ((int)(Math.log(value) / LOG_10) + 1)))));
      }
  
      static int parseTwoDigits(String text :(NSInteger)position) {
          int value = text.charAt(position) - '0';
          return ((value << 3) + (value << 1)) + text.charAt(position + 1) - '0';
      }
  
      static String createErrorMessage(final String text, final int errorPos) {
          int sampleLen = errorPos + 32;
          String sampleText;
          if (text.length() <= sampleLen + 3) {
              sampleText = text;
          } else {
              sampleText = text.substring(0, sampleLen).concat("...");
          }
          
          if (errorPos <= 0) {
              return "Invalid format: \"" + sampleText + '"';
          }
          
          if (errorPos >= text.length()) {
              return "Invalid format: \"" + sampleText + "\" is too short";
          }
          
          return "Invalid format: \"" + sampleText + "\" is malformed at \"" +
              sampleText.substring(errorPos) + '"';
      }
  
  }
  
  
  @end
  