private boolean expect(String source, ParsePosition pos, char ch) {
   int x = pos.getIndex();
   boolean r = x < source.length() && source.charAt(x) == ch;
   if (r) pos.setIndex(x + 1);
   else pos.setErrorIndex(x);
   return r;
 }
 /**
  * Parses a {@code Number} from the specified string using the rules of this number format.
  *
  * @param string the string to parse.
  * @return the {@code Number} resulting from the parsing.
  * @throws ParseException if an error occurs during parsing.
  */
 public Number parse(String string) throws ParseException {
   ParsePosition pos = new ParsePosition(0);
   Number number = parse(string, pos);
   if (pos.getIndex() == 0) {
     throw new ParseException("Unparseable number: \"" + string + "\"", pos.getErrorIndex());
   }
   return number;
 }
예제 #3
0
 private int parseNumber(int max, String string, int offset, int field, int skew) {
   ParsePosition position = new ParsePosition(offset);
   Number result = parseNumber(max, string, position);
   if (result == null) {
     return -position.getErrorIndex() - 1;
   }
   calendar.set(field, result.intValue() + skew);
   return position.getIndex();
 }
예제 #4
0
 /** Does the parse-work without the mandatory-check */
 private String parse2(String external) throws FmtParseException {
   // trim blanks on both sides
   if (external == null) return "";
   external = external.trim();
   if (external.length() == 0) return "";
   else {
     ParsePosition pp = new ParsePosition(0);
     Date date = null;
     date = dateFormat_.parse(external, pp);
     if (date == null || (pp.getIndex() != external.length() && pp.getIndex() > 0)) {
       throw new FmtParseException("ATSSyntax", getSampleTS());
     }
     return TimeStampUtil.date2Internal(date);
   }
 }
예제 #5
0
  protected void load() throws IOException {

    BufferedReader is = new BufferedReader(new FileReader("ReminderService.txt"));
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy MM dd hh mm");
    String aLine;
    while ((aLine = is.readLine()) != null) {
      ParsePosition pp = new ParsePosition(0);
      Date date = formatter.parse(aLine, pp);
      if (date == null) {
        message("Invalid date in " + aLine);
        continue;
      }
      String mesg = aLine.substring(pp.getIndex());
      l.add(new Item(date, mesg));
    }
  }
예제 #6
0
  public void test(TestHarness harness) {
    ParsePosition pp = new ParsePosition(69);
    harness.check(pp.getIndex(), 69, "getIndex() post-create");

    pp.setIndex(666);
    harness.check(pp.getIndex(), 666, "set/getIndex()");

    harness.check(pp.getErrorIndex(), -1, "getErrorIndex() no error");

    pp.setErrorIndex(65536);
    harness.check(pp.getErrorIndex(), 65536, "set/getErrorIndex()");

    harness.debug(pp.toString());
  }
 @Override
 public Date parse(String i, ParsePosition p) {
   /* delegate to SimpleDateFormat for easy stuff */
   Date d = super.parse(i, p);
   int milliIndex = p.getIndex();
   /* worry about the milliseconds ourselves */
   if (null != d
       && -1 == p.getErrorIndex()
       && milliIndex + 1 < i.length()
       && '.' == i.charAt(milliIndex)) {
     p.setIndex(++milliIndex); // NOTE: ++ to chomp '.'
     Number millis = millisParser.parse(i, p);
     if (-1 == p.getErrorIndex()) {
       int endIndex = p.getIndex();
       d =
           new Date(
               d.getTime()
                   + (long) (millis.doubleValue() * Math.pow(10, (3 - endIndex + milliIndex))));
     }
   }
   return d;
 }
예제 #8
0
  private Number parseNumber(int max, String string, ParsePosition position) {
    int length = string.length();
    int index = position.getIndex();
    if (max > 0 && max < length - index) {
      length = index + max;
    }
    while (index < length && (string.charAt(index) == ' ' || string.charAt(index) == '\t')) {
      ++index;
    }
    if (max == 0) {
      position.setIndex(index);
      Number n = numberFormat.parse(string, position);
      // In RTL locales, NumberFormat might have parsed "2012-" in an ISO date as the
      // negative number -2012.
      // Ideally, we wouldn't have this broken API that exposes a NumberFormat and expects
      // us to use it. The next best thing would be a way to ask the NumberFormat to parse
      // positive numbers only, but icu4c supports negative (BCE) years. The best we can do
      // is try to recognize when icu4c has done this, and undo it.
      if (n != null && n.longValue() < 0) {
        if (numberFormat instanceof DecimalFormat) {
          DecimalFormat df = (DecimalFormat) numberFormat;
          char lastChar = string.charAt(position.getIndex() - 1);
          char minusSign = df.getDecimalFormatSymbols().getMinusSign();
          if (lastChar == minusSign) {
            n = Long.valueOf(-n.longValue()); // Make the value positive.
            position.setIndex(position.getIndex() - 1); // Spit out the negative sign.
          }
        }
      }
      return n;
    }

    int result = 0;
    int digit;
    while (index < length && (digit = Character.digit(string.charAt(index), 10)) != -1) {
      result = result * 10 + digit;
      ++index;
    }
    if (index == position.getIndex()) {
      position.setErrorIndex(index);
      return null;
    }
    position.setIndex(index);
    return Integer.valueOf(result);
  }
  /**
   * This method parses the specified string into a date.
   *
   * @param dateStr The date string to parse.
   * @param pos The input and output parse position
   * @return The parsed date, or <code>null</code> if the string cannot be parsed.
   */
  public Date parse(String dateStr, ParsePosition pos) {
    int fmt_index = 0;
    int fmt_max = pattern.length();

    calendar.clear();
    boolean saw_timezone = false;
    int quote_start = -1;
    boolean is2DigitYear = false;
    try {
      for (; fmt_index < fmt_max; ++fmt_index) {
        char ch = pattern.charAt(fmt_index);
        if (ch == '\'') {
          int index = pos.getIndex();
          if (fmt_index < fmt_max - 1 && pattern.charAt(fmt_index + 1) == '\'') {
            if (!expect(dateStr, pos, ch)) return null;
            ++fmt_index;
          } else quote_start = quote_start < 0 ? fmt_index : -1;
          continue;
        }

        if (quote_start != -1 || ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))) {
          if (!expect(dateStr, pos, ch)) return null;
          continue;
        }

        // We've arrived at a potential pattern character in the
        // pattern.
        int fmt_count = 1;
        while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch) {
          ++fmt_count;
        }

        // We might need to limit the number of digits to parse in
        // some cases.  We look to the next pattern character to
        // decide.
        boolean limit_digits = false;
        if (fmt_index < fmt_max && standardChars.indexOf(pattern.charAt(fmt_index)) >= 0)
          limit_digits = true;
        --fmt_index;

        // We can handle most fields automatically: most either are
        // numeric or are looked up in a string vector.  In some cases
        // we need an offset.  When numeric, `offset' is added to the
        // resulting value.  When doing a string lookup, offset is the
        // initial index into the string array.
        int calendar_field;
        boolean is_numeric = true;
        int offset = 0;
        boolean maybe2DigitYear = false;
        boolean oneBasedHour = false;
        boolean oneBasedHourOfDay = false;
        Integer simpleOffset;
        String[] set1 = null;
        String[] set2 = null;
        switch (ch) {
          case 'd':
            calendar_field = Calendar.DATE;
            break;
          case 'D':
            calendar_field = Calendar.DAY_OF_YEAR;
            break;
          case 'F':
            calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
            break;
          case 'E':
            is_numeric = false;
            offset = 1;
            calendar_field = Calendar.DAY_OF_WEEK;
            set1 = formatData.getWeekdays();
            set2 = formatData.getShortWeekdays();
            break;
          case 'w':
            calendar_field = Calendar.WEEK_OF_YEAR;
            break;
          case 'W':
            calendar_field = Calendar.WEEK_OF_MONTH;
            break;
          case 'M':
            calendar_field = Calendar.MONTH;
            if (fmt_count <= 2) offset = -1;
            else {
              is_numeric = false;
              set1 = formatData.getMonths();
              set2 = formatData.getShortMonths();
            }
            break;
          case 'y':
            calendar_field = Calendar.YEAR;
            if (fmt_count <= 2) maybe2DigitYear = true;
            break;
          case 'K':
            calendar_field = Calendar.HOUR;
            break;
          case 'h':
            calendar_field = Calendar.HOUR;
            oneBasedHour = true;
            break;
          case 'H':
            calendar_field = Calendar.HOUR_OF_DAY;
            break;
          case 'k':
            calendar_field = Calendar.HOUR_OF_DAY;
            oneBasedHourOfDay = true;
            break;
          case 'm':
            calendar_field = Calendar.MINUTE;
            break;
          case 's':
            calendar_field = Calendar.SECOND;
            break;
          case 'S':
            calendar_field = Calendar.MILLISECOND;
            break;
          case 'a':
            is_numeric = false;
            calendar_field = Calendar.AM_PM;
            set1 = formatData.getAmPmStrings();
            break;
          case 'z':
          case 'Z':
            // We need a special case for the timezone, because it
            // uses a different data structure than the other cases.
            is_numeric = false;
            calendar_field = Calendar.ZONE_OFFSET;
            String[][] zoneStrings = formatData.getZoneStrings();
            int zoneCount = zoneStrings.length;
            int index = pos.getIndex();
            boolean found_zone = false;
            simpleOffset = computeOffset(dateStr.substring(index));
            if (simpleOffset != null) {
              found_zone = true;
              saw_timezone = true;
              calendar.set(Calendar.DST_OFFSET, 0);
              offset = simpleOffset.intValue();
            } else {
              for (int j = 0; j < zoneCount; j++) {
                String[] strings = zoneStrings[j];
                int k;
                for (k = 0; k < strings.length; ++k) {
                  if (dateStr.startsWith(strings[k], index)) break;
                }
                if (k != strings.length) {
                  found_zone = true;
                  saw_timezone = true;
                  TimeZone tz = TimeZone.getTimeZone(strings[0]);
                  // Check if it's a DST zone or ordinary
                  if (k == 3 || k == 4) calendar.set(Calendar.DST_OFFSET, tz.getDSTSavings());
                  else calendar.set(Calendar.DST_OFFSET, 0);
                  offset = tz.getRawOffset();
                  pos.setIndex(index + strings[k].length());
                  break;
                }
              }
            }
            if (!found_zone) {
              pos.setErrorIndex(pos.getIndex());
              return null;
            }
            break;
          default:
            pos.setErrorIndex(pos.getIndex());
            return null;
        }

        // Compute the value we should assign to the field.
        int value;
        int index = -1;
        if (is_numeric) {
          numberFormat.setMinimumIntegerDigits(fmt_count);
          if (limit_digits) numberFormat.setMaximumIntegerDigits(fmt_count);
          if (maybe2DigitYear) index = pos.getIndex();
          Number n = numberFormat.parse(dateStr, pos);
          if (pos == null || !(n instanceof Long)) return null;
          value = n.intValue() + offset;
        } else if (set1 != null) {
          index = pos.getIndex();
          int i;
          boolean found = false;
          for (i = offset; i < set1.length; ++i) {
            if (set1[i] != null)
              if (dateStr.toUpperCase().startsWith(set1[i].toUpperCase(), index)) {
                found = true;
                pos.setIndex(index + set1[i].length());
                break;
              }
          }
          if (!found && set2 != null) {
            for (i = offset; i < set2.length; ++i) {
              if (set2[i] != null)
                if (dateStr.toUpperCase().startsWith(set2[i].toUpperCase(), index)) {
                  found = true;
                  pos.setIndex(index + set2[i].length());
                  break;
                }
            }
          }
          if (!found) {
            pos.setErrorIndex(index);
            return null;
          }
          value = i;
        } else value = offset;

        if (maybe2DigitYear) {
          // Parse into default century if the numeric year string has
          // exactly 2 digits.
          int digit_count = pos.getIndex() - index;
          if (digit_count == 2) {
            is2DigitYear = true;
            value += defaultCentury;
          }
        }

        // Calendar uses 0-based hours.
        // I.e. 00:00 AM is midnight, not 12 AM or 24:00
        if (oneBasedHour && value == 12) value = 0;

        if (oneBasedHourOfDay && value == 24) value = 0;

        // Assign the value and move on.
        calendar.set(calendar_field, value);
      }

      if (is2DigitYear) {
        // Apply the 80-20 heuristic to dermine the full year based on
        // defaultCenturyStart.
        int year = calendar.get(Calendar.YEAR);
        if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
          calendar.set(Calendar.YEAR, year + 100);
      }
      if (!saw_timezone) {
        // Use the real rules to determine whether or not this
        // particular time is in daylight savings.
        calendar.clear(Calendar.DST_OFFSET);
        calendar.clear(Calendar.ZONE_OFFSET);
      }
      return calendar.getTime();
    } catch (IllegalArgumentException x) {
      pos.setErrorIndex(pos.getIndex());
      return null;
    }
  }
예제 #10
0
 /**
  * Parses a date from the specified string starting at the index specified by {@code position}. If
  * the string is successfully parsed then the index of the {@code ParsePosition} is updated to the
  * index following the parsed text. On error, the index is unchanged and the error index of {@code
  * ParsePosition} is set to the index where the error occurred.
  *
  * @param string the string to parse using the pattern of this simple date format.
  * @param position input/output parameter, specifies the start index in {@code string} from where
  *     to start parsing. If parsing is successful, it is updated with the index following the
  *     parsed text; on error, the index is unchanged and the error index is set to the index where
  *     the error occurred.
  * @return the date resulting from the parse, or {@code null} if there is an error.
  * @throws IllegalArgumentException if there are invalid characters in the pattern.
  */
 @Override
 public Date parse(String string, ParsePosition position) {
   // Harmony delegates to ICU's SimpleDateFormat, we implement it directly
   boolean quote = false;
   int next, last = -1, count = 0, offset = position.getIndex();
   int length = string.length();
   calendar.clear();
   TimeZone zone = calendar.getTimeZone();
   final int patternLength = pattern.length();
   for (int i = 0; i < patternLength; i++) {
     next = pattern.charAt(i);
     if (next == '\'') {
       if (count > 0) {
         if ((offset = parse(string, offset, (char) last, count)) < 0) {
           return error(position, -offset - 1, zone);
         }
         count = 0;
       }
       if (last == next) {
         if (offset >= length || string.charAt(offset) != '\'') {
           return error(position, offset, zone);
         }
         offset++;
         last = -1;
       } else {
         last = next;
       }
       quote = !quote;
       continue;
     }
     if (!quote
         && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
       if (last == next) {
         count++;
       } else {
         if (count > 0) {
           if ((offset = parse(string, offset, (char) last, -count)) < 0) {
             return error(position, -offset - 1, zone);
           }
         }
         last = next;
         count = 1;
       }
     } else {
       if (count > 0) {
         if ((offset = parse(string, offset, (char) last, count)) < 0) {
           return error(position, -offset - 1, zone);
         }
         count = 0;
       }
       last = -1;
       if (offset >= length || string.charAt(offset) != next) {
         return error(position, offset, zone);
       }
       offset++;
     }
   }
   if (count > 0) {
     if ((offset = parse(string, offset, (char) last, count)) < 0) {
       return error(position, -offset - 1, zone);
     }
   }
   Date date;
   try {
     date = calendar.getTime();
   } catch (IllegalArgumentException e) {
     return error(position, offset, zone);
   }
   position.setIndex(offset);
   calendar.setTimeZone(zone);
   return date;
 }
예제 #11
0
 private int parse(String string, int offset, char format, int count) {
   int index = PATTERN_CHARS.indexOf(format);
   if (index == -1) {
     throw new IllegalArgumentException("Unknown pattern character '" + format + "'");
   }
   int field = -1;
   // TODO: what's 'absolute' for? when is 'count' negative, and why?
   int absolute = 0;
   if (count < 0) {
     count = -count;
     absolute = count;
   }
   switch (index) {
     case ERA_FIELD:
       return parseText(string, offset, formatData.eras, Calendar.ERA);
     case YEAR_FIELD:
       if (count >= 3) {
         field = Calendar.YEAR;
       } else {
         ParsePosition position = new ParsePosition(offset);
         Number result = parseNumber(absolute, string, position);
         if (result == null) {
           return -position.getErrorIndex() - 1;
         }
         int year = result.intValue();
         // A two digit year must be exactly two digits, i.e. 01
         if ((position.getIndex() - offset) == 2 && year >= 0) {
           year += creationYear / 100 * 100;
           if (year < creationYear) {
             year += 100;
           }
         }
         calendar.set(Calendar.YEAR, year);
         return position.getIndex();
       }
       break;
     case STAND_ALONE_MONTH_FIELD: // 'L'
       return parseMonth(string, offset, count, absolute, true);
     case MONTH_FIELD: // 'M'
       return parseMonth(string, offset, count, absolute, false);
     case DATE_FIELD:
       field = Calendar.DATE;
       break;
     case HOUR_OF_DAY1_FIELD: // 'k'
       ParsePosition position = new ParsePosition(offset);
       Number result = parseNumber(absolute, string, position);
       if (result == null) {
         return -position.getErrorIndex() - 1;
       }
       int hour = result.intValue();
       if (hour == 24) {
         hour = 0;
       }
       calendar.set(Calendar.HOUR_OF_DAY, hour);
       return position.getIndex();
     case HOUR_OF_DAY0_FIELD: // 'H'
       field = Calendar.HOUR_OF_DAY;
       break;
     case MINUTE_FIELD:
       field = Calendar.MINUTE;
       break;
     case SECOND_FIELD:
       field = Calendar.SECOND;
       break;
     case MILLISECOND_FIELD:
       field = Calendar.MILLISECOND;
       break;
     case STAND_ALONE_DAY_OF_WEEK_FIELD:
       return parseDayOfWeek(string, offset, true);
     case DAY_OF_WEEK_FIELD:
       return parseDayOfWeek(string, offset, false);
     case DAY_OF_YEAR_FIELD:
       field = Calendar.DAY_OF_YEAR;
       break;
     case DAY_OF_WEEK_IN_MONTH_FIELD:
       field = Calendar.DAY_OF_WEEK_IN_MONTH;
       break;
     case WEEK_OF_YEAR_FIELD:
       field = Calendar.WEEK_OF_YEAR;
       break;
     case WEEK_OF_MONTH_FIELD:
       field = Calendar.WEEK_OF_MONTH;
       break;
     case AM_PM_FIELD:
       return parseText(string, offset, formatData.ampms, Calendar.AM_PM);
     case HOUR1_FIELD: // 'h'
       position = new ParsePosition(offset);
       result = parseNumber(absolute, string, position);
       if (result == null) {
         return -position.getErrorIndex() - 1;
       }
       hour = result.intValue();
       if (hour == 12) {
         hour = 0;
       }
       calendar.set(Calendar.HOUR, hour);
       return position.getIndex();
     case HOUR0_FIELD: // 'K'
       field = Calendar.HOUR;
       break;
     case TIMEZONE_FIELD: // 'z'
       return parseTimeZone(string, offset);
     case RFC_822_TIMEZONE_FIELD: // 'Z'
       return parseTimeZone(string, offset);
   }
   if (field != -1) {
     return parseNumber(absolute, string, offset, field, 0);
   }
   return offset;
 }
예제 #12
0
 private Date error(ParsePosition position, int offset, TimeZone zone) {
   position.setErrorIndex(offset);
   calendar.setTimeZone(zone);
   return null;
 }
예제 #13
0
 private int parseTimeZone(String string, int offset) {
   boolean foundGMT = string.regionMatches(offset, "GMT", 0, 3);
   if (foundGMT) {
     offset += 3;
   }
   char sign;
   if (offset < string.length() && ((sign = string.charAt(offset)) == '+' || sign == '-')) {
     ParsePosition position = new ParsePosition(offset + 1);
     Number result = numberFormat.parse(string, position);
     if (result == null) {
       return -position.getErrorIndex() - 1;
     }
     int hour = result.intValue();
     int raw = hour * 3600000;
     int index = position.getIndex();
     if (index < string.length() && string.charAt(index) == ':') {
       position.setIndex(index + 1);
       result = numberFormat.parse(string, position);
       if (result == null) {
         return -position.getErrorIndex() - 1;
       }
       int minute = result.intValue();
       raw += minute * 60000;
     } else if (hour >= 24) {
       raw = (hour / 100 * 3600000) + (hour % 100 * 60000);
     }
     if (sign == '-') {
       raw = -raw;
     }
     calendar.setTimeZone(new SimpleTimeZone(raw, ""));
     return position.getIndex();
   }
   if (foundGMT) {
     calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
     return offset;
   }
   for (String[] row : formatData.internalZoneStrings()) {
     for (int i = TimeZoneNames.LONG_NAME; i < TimeZoneNames.NAME_COUNT; ++i) {
       if (row[i] == null) {
         // If icu4c doesn't have a name, our array contains a null. Normally we'd
         // work out the correct GMT offset, but we already handled parsing GMT offsets
         continue;
       }
       if (string.regionMatches(true, offset, row[i], 0, row[i].length())) {
         TimeZone zone = TimeZone.getTimeZone(row[TimeZoneNames.OLSON_NAME]);
         if (zone == null) {
           return -offset - 1;
         }
         int raw = zone.getRawOffset();
         if (i == TimeZoneNames.LONG_NAME_DST || i == TimeZoneNames.SHORT_NAME_DST) {
           // Not all time zones use a one-hour difference, so we need to query
           // the TimeZone. (Australia/Lord_Howe is the usual example of this.)
           int dstSavings = zone.getDSTSavings();
           // One problem with TimeZone.getDSTSavings is that it will return 0 if the
           // time zone has stopped using DST, even if we're parsing a date from
           // the past. In that case, assume the default.
           if (dstSavings == 0) {
             // TODO: we should change this to use TimeZone.getOffset(long),
             // but that requires the complete date to be parsed first.
             dstSavings = 3600000;
           }
           raw += dstSavings;
         }
         calendar.setTimeZone(new SimpleTimeZone(raw, ""));
         return offset + row[i].length();
       }
     }
   }
   return -offset - 1;
 }
 public Object[] parse(String sourceStr) throws ParseException {
   ParsePosition pp = new ParsePosition(0);
   Object[] r = parse(sourceStr, pp);
   if (r == null) throw new ParseException("couldn't parse string", pp.getErrorIndex());
   return r;
 }
  /**
   * Parse a string <code>sourceStr</code> against the pattern specified to the MessageFormat
   * constructor.
   *
   * @param sourceStr the string to be parsed.
   * @param pos the current parse position (and eventually the error position).
   * @return the array of parsed objects sorted according to their argument number in the pattern.
   */
  public Object[] parse(String sourceStr, ParsePosition pos) {
    // Check initial text.
    int index = pos.getIndex();
    if (!sourceStr.startsWith(leader, index)) {
      pos.setErrorIndex(index);
      return null;
    }
    index += leader.length();

    Vector results = new Vector(elements.length, 1);
    // Now check each format.
    for (int i = 0; i < elements.length; ++i) {
      Format formatter = null;
      if (elements[i].setFormat != null) formatter = elements[i].setFormat;
      else if (elements[i].format != null) formatter = elements[i].format;

      Object value = null;
      if (formatter instanceof ChoiceFormat) {
        // We must special-case a ChoiceFormat because it might
        // have recursive formatting.
        ChoiceFormat cf = (ChoiceFormat) formatter;
        String[] formats = (String[]) cf.getFormats();
        double[] limits = (double[]) cf.getLimits();
        MessageFormat subfmt = new MessageFormat();
        subfmt.setLocale(locale);
        ParsePosition subpos = new ParsePosition(index);

        int j;
        for (j = 0; value == null && j < limits.length; ++j) {
          subfmt.applyPattern(formats[j]);
          subpos.setIndex(index);
          value = subfmt.parse(sourceStr, subpos);
        }
        if (value != null) {
          index = subpos.getIndex();
          value = new Double(limits[j]);
        }
      } else if (formatter != null) {
        pos.setIndex(index);
        value = formatter.parseObject(sourceStr, pos);
        if (value != null) index = pos.getIndex();
      } else {
        // We have a String format.  This can lose in a number
        // of ways, but we give it a shot.
        int next_index = sourceStr.indexOf(elements[i].trailer, index);
        if (next_index == -1) {
          pos.setErrorIndex(index);
          return null;
        }
        value = sourceStr.substring(index, next_index);
        index = next_index;
      }

      if (value == null || !sourceStr.startsWith(elements[i].trailer, index)) {
        pos.setErrorIndex(index);
        return null;
      }

      if (elements[i].argNumber >= results.size()) results.setSize(elements[i].argNumber + 1);
      results.setElementAt(value, elements[i].argNumber);

      index += elements[i].trailer.length();
    }

    Object[] r = new Object[results.size()];
    results.copyInto(r);
    return r;
  }