Skip to content

Commit 1b75b01

Browse files
committed
Tweak number parsing
1 parent fb8f0c4 commit 1b75b01

File tree

1 file changed

+36
-12
lines changed

1 file changed

+36
-12
lines changed

src/Connection/ImapTokenizer.php

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,8 @@ public function nextToken(): ?Token
121121
return $this->readLiteral();
122122
}
123123

124-
// Check for number.
125-
if (ctype_digit($char)) {
126-
return $this->readNumber();
127-
}
128-
129-
// Otherwise, parse an atom.
130-
return $this->readAtom();
124+
// Otherwise, parse a number or atom.
125+
return $this->readNumberOrAtom();
131126
}
132127

133128
/**
@@ -306,14 +301,44 @@ protected function readLiteral(): Literal
306301
return new Literal($literal);
307302
}
308303

304+
/**
305+
* Reads a number or atom token.
306+
*/
307+
protected function readNumberOrAtom(): Token
308+
{
309+
$position = $this->position;
310+
311+
// First char must be a digit to even consider a number.
312+
if (! ctype_digit($this->buffer[$position] ?? '')) {
313+
return $this->readAtom();
314+
}
315+
316+
// Walk forward to find the end of the digit run.
317+
while (ctype_digit($this->buffer[$position] ?? '')) {
318+
$position++;
319+
320+
$this->ensureBuffer($position - $this->position + 1);
321+
}
322+
323+
$next = $this->buffer[$position] ?? null;
324+
325+
// If next is EOF or a delimiter, it's a Number.
326+
if ($next === null || $this->isDelimiter($next)) {
327+
return $this->readNumber();
328+
}
329+
330+
// Otherwise it's an Atom.
331+
return $this->readAtom();
332+
}
333+
309334
/**
310335
* Reads a number token.
311336
*
312-
* Numbers are sequences of digits.
337+
* A number consists of one or more digit characters and represents a numeric value.
313338
*/
314339
protected function readNumber(): Number
315340
{
316-
$value = '';
341+
$start = $this->position;
317342

318343
while (true) {
319344
$this->ensureBuffer(1);
@@ -328,12 +353,10 @@ protected function readNumber(): Number
328353
break;
329354
}
330355

331-
$value .= $char;
332-
333356
$this->advance();
334357
}
335358

336-
return new Number($value);
359+
return new Number(substr($this->buffer, $start, $this->position - $start));
337360
}
338361

339362
/**
@@ -347,6 +370,7 @@ protected function readAtom(): Atom
347370

348371
while (true) {
349372
$this->ensureBuffer(1);
373+
350374
$char = $this->currentChar();
351375

352376
if ($char === null) {

0 commit comments

Comments
 (0)