packages/core/src/format/parser/PadPrinterParserDecorator.js
/**
* @copyright (c) 2016, Philipp Thürwächter & Pattrick Hüper
* @copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
* @license BSD-3-Clause (see LICENSE in the root directory of this source tree)
*/
import { assert } from '../../assert';
import { DateTimeException } from '../../errors';
/**
* Pads the output to a fixed width.
* @private
*/
export class PadPrinterParserDecorator {
/**
* Constructor.
*
* @param printerParser the printer, not null
* @param padWidth the width to pad to, 1 or greater
* @param padChar the pad character
*/
constructor(printerParser, padWidth, padChar) {
// input checked by DateTimeFormatterBuilder
this._printerParser = printerParser;
this._padWidth = padWidth;
this._padChar = padChar;
}
print(context, buf) {
const preLen = buf.length();
if (this._printerParser.print(context, buf) === false) {
return false;
}
const len = buf.length() - preLen;
if (len > this._padWidth) {
throw new DateTimeException(
`Cannot print as output of ${len} characters exceeds pad width of ${this._padWidth}`);
}
for (let i = 0; i < this._padWidth - len; i++) {
buf.insert(preLen, this._padChar);
}
return true;
}
parse(context, text, position) {
// cache context before changed by decorated parser
const strict = context.isStrict();
const caseSensitive = context.isCaseSensitive();
// parse
assert(!(position > text.length));
assert(position >= 0);
if (position === text.length) {
return ~position; // no more characters in the string
}
let endPos = position + this._padWidth;
if (endPos > text.length) {
if (strict) {
return ~position; // not enough characters in the string to meet the parse width
}
endPos = text.length;
}
let pos = position;
while (pos < endPos &&
(caseSensitive ? text[pos] === this._padChar : context.charEquals(text[pos], this._padChar))) {
pos++;
}
text = text.substring(0, endPos);
const 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;
}
toString() {
return `Pad(${this._printerParser},${this._padWidth}${(this._padChar === ' ' ? ')' : `,'${this._padChar}')`)}`;
}
}