Пример #1
0
 public function parse(DateTimeParseContext $context, $parseText, $position)
 {
     $length = strlen($parseText);
     if ($position < 0 || $position > $length) {
         throw new \OutOfRangeException();
     }
     $style = $context->isStrict() ? $this->textStyle : null;
     $chrono = $context->getEffectiveChronology();
     $it = null;
     if ($chrono === null || $chrono == IsoChronology::INSTANCE()) {
         $it = $this->provider->getTextIterator($this->field, $style, $context->getLocale());
     } else {
         $it = $this->provider->getTextIterator2($chrono, $this->field, $style, $context->getLocale());
     }
     if ($it !== null) {
         foreach ($it as $key => $value) {
             // fix numeric indices
             $key = strval($key);
             if ($context->subSequenceEquals($key, 0, $parseText, $position, strlen($key))) {
                 return $context->setParsedField($this->field, $value, $position, $position + strlen($key));
             }
         }
         if ($context->isStrict()) {
             return ~$position;
         }
     }
     return $this->numberPrinterParser()->parse($context, $parseText, $position);
 }
 public function parse(DateTimeParseContext $context, $text, $position)
 {
     // cache context before changed by decorated parser
     $strict = $context->isStrict();
     // parse
     if ($position > strlen($text) || $position < 0) {
         throw new \OutOfRangeException();
     }
     if ($position === strlen($text)) {
         return ~$position;
         // no more characters in the string
     }
     $endPos = $position + $this->padWidth;
     if ($endPos > strlen($text)) {
         if ($strict) {
             return ~$position;
             // not enough characters in the string to meet the parse width
         }
         $endPos = strlen($text);
     }
     $pos = $position;
     while ($pos < $endPos && $context->charEquals($text[$pos], $this->padChar)) {
         $pos++;
     }
     $text = substr($text, 0, $endPos);
     $resultPos = $this->printerParser->parse($context, $text, $pos);
     if ($resultPos !== $endPos && $strict) {
         return ~($position + $pos);
         // parse of decorated field didn't parse to the end
     }
     return $resultPos;
 }
Пример #3
0
 public function parse(DateTimeParseContext $context, $text, $position)
 {
     $length = strlen($text);
     if ($position === $length) {
         return ~$position;
     }
     if ($position < 0 || $position >= $length) {
         throw new \OutOfRangeException();
     }
     $sign = $text[$position];
     $negative = false;
     $positive = false;
     if ($sign === $context->getDecimalStyle()->getPositiveSign()) {
         if ($this->signStyle->parse(true, $context->isStrict(), $this->minWidth === $this->maxWidth) === false) {
             return ~$position;
         }
         $positive = true;
         $position++;
     } else {
         if ($sign === $context->getDecimalStyle()->getNegativeSign()) {
             if ($this->signStyle->parse(false, $context->isStrict(), $this->minWidth === $this->maxWidth) === false) {
                 return ~$position;
             }
             $negative = true;
             $position++;
         } else {
             if ($this->signStyle == SignStyle::ALWAYS() && $context->isStrict()) {
                 return ~$position;
             }
         }
     }
     $effMinWidth = $context->isStrict() || $this->isFixedWidth($context) ? $this->minWidth : 1;
     $minEndPos = $position + $effMinWidth;
     if ($minEndPos > $length) {
         return ~$position;
     }
     $effMaxWidth = ($context->isStrict() || $this->isFixedWidth($context) ? $this->maxWidth : 9) + Math::max($this->subsequentWidth, 0);
     $total = 0;
     $totalBig = null;
     $pos = $position;
     for ($pass = 0; $pass < 2; $pass++) {
         $maxEndPos = Math::min($pos + $effMaxWidth, $length);
         while ($pos < $maxEndPos) {
             $ch = $text[$pos++];
             $digit = $context->getDecimalStyle()->convertToDigit($ch);
             if ($digit < 0) {
                 $pos--;
                 if ($pos < $minEndPos) {
                     return ~$position;
                     // need at least min width digits
                 }
                 break;
             }
             if ($pos - $position > 18) {
                 if ($totalBig === null) {
                     $totalBig = \gmp_init($total);
                 }
                 $totalBig = \gmp_add(\gmp_mul($totalBig, "10"), \gmp_init($digit));
             } else {
                 $total = $total * 10 + $digit;
             }
         }
         if ($this->subsequentWidth > 0 && $pass === 0) {
             // re-parse now we know the correct width
             $parseLen = $pos - $position;
             $effMaxWidth = Math::max($effMinWidth, $parseLen - $this->subsequentWidth);
             $pos = $position;
             $total = 0;
             $totalBig = null;
         } else {
             break;
         }
     }
     if ($negative) {
         if ($totalBig !== null) {
             if (\gmp_cmp($totalBig, "0") === 0 && $context->isStrict()) {
                 return ~($position - 1);
                 // minus zero not allowed
             }
             $totalBig = \gmp_neg($totalBig);
         } else {
             if ($total === 0 && $context->isStrict()) {
                 return ~($position - 1);
                 // minus zero not allowed
             }
             $total = -$total;
         }
     } else {
         if ($this->signStyle == SignStyle::EXCEEDS_PAD() && $context->isStrict()) {
             $parseLen = $pos - $position;
             if ($positive) {
                 if ($parseLen <= $this->minWidth) {
                     return ~($position - 1);
                     // '+' only parsed if minWidth exceeded
                 }
             } else {
                 if ($parseLen > $this->minWidth) {
                     return ~$position;
                     // '+' must be parsed if minWidth exceeded
                 }
             }
         }
     }
     if ($totalBig !== null) {
         if (gmp_cmp($totalBig, "-9223372036854775808") < 0 || gmp_cmp($totalBig, "9223372036854775807") > 0) {
             // overflow, parse 1 less digit
             $totalBig = gmp_div($totalBig, "10");
             $pos--;
         }
         return $this->setValue($context, gmp_intval($totalBig), $position, $pos);
     }
     return $this->setValue($context, $total, $position, $pos);
 }
 public function parse(DateTimeParseContext $context, $text, $position)
 {
     $effectiveMin = $context->isStrict() ? $this->minWidth : 0;
     $effectiveMax = $context->isStrict() ? $this->maxWidth : 9;
     $length = strlen($text);
     if ($position === $length) {
         // valid if whole field is optional, invalid if minimum width
         return $effectiveMin > 0 ? ~$position : $position;
     }
     if ($this->decimalPoint) {
         if ($text[$position] != $context->getDecimalStyle()->getDecimalSeparator()) {
             // valid if whole field is optional, invalid if minimum width
             return $effectiveMin > 0 ? ~$position : $position;
         }
         $position++;
     }
     $minEndPos = $position + $effectiveMin;
     if ($minEndPos > $length) {
         return ~$position;
         // need at least min width digits
     }
     $maxEndPos = Math::min($position + $effectiveMax, $length);
     $total = 0;
     // can use int because we are only parsing up to 9 digits
     $pos = $position;
     while ($pos < $maxEndPos) {
         $ch = $text[$pos++];
         $digit = $context->getDecimalStyle()->convertToDigit($ch);
         if ($digit < 0) {
             if ($pos < $minEndPos) {
                 return ~$position;
                 // need at least min width digits
             }
             $pos--;
             break;
         }
         $total = $total * 10 + $digit;
     }
     $div = 1 . str_repeat('0', 9 - ($pos - $position));
     $fraction = gmp_mul($total, $div);
     $value = $this->convertFromFraction($fraction);
     return $context->setParsedField($this->field, $value, $position, $pos);
 }
 /**
  * For a ReducedPrinterParser, fixed width is false if the mode is strict,
  * otherwise it is set as for NumberPrinterParser.
  * @param DateTimeParseContext $context the context
  * @return bool if the field is fixed width
  * @see DateTimeFormatterBuilder#appendValueReduced(java.time.temporal.TemporalField, int, int, int)
  */
 public function isFixedWidth(DateTimeParseContext $context)
 {
     if ($context->isStrict() == false) {
         return false;
     }
     return parent::isFixedWidth($context);
 }