"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@midwayjs/core");
const Span_1 = require("./Span");
class CharacterStream {
    constructor(source, start, end) {
        this.spanStart = 0;
        if (start == undefined) {
            start = 0;
        }
        if (end == undefined) {
            end = source.length;
        }
        if (start > end) {
            throw new core_1.MidwayCommonError('Start must be <= end.');
        }
        if (start < 0) {
            throw new core_1.MidwayCommonError('Start must be >= 0.');
        }
        if (start > Math.max(0, source.length - 1)) {
            throw new core_1.MidwayCommonError('Start outside of string.');
        }
        if (end > source.length) {
            throw new core_1.MidwayCommonError('End outside of string.');
        }
        this.source = source;
        this.index = start;
        this.end = end;
    }
    /**
     * 截取字符串
     *
     * @param startIndex 开始位置
     * @param endIndex   结束位置
     */
    substring(startIndex, endIndex) {
        return this.source.substring(startIndex, endIndex);
    }
    /**
     * 是否有下一个字符
     **/
    hasMore() {
        return this.index < this.end;
    }
    /**
     * 根据开始位置、结束位置返回Span
     */
    getSpan(start, end) {
        return new Span_1.default(this.source, start, end);
    }
    /**
     * 返回下一个字符
     **/
    consume() {
        if (!this.hasMore()) {
            throw new core_1.MidwayCommonError('No more characters in stream.');
        }
        return this.source.charAt(this.index++);
    }
    /**
     * 返回是否是以给定的字符串开头
     */
    match(needle, consume) {
        const needleLength = needle.length;
        if (needleLength + this.index > this.end) {
            return false;
        }
        for (let i = 0, j = this.index; i < needleLength; i++, j++) {
            if (this.index >= this.end) {
                return false;
            }
            if (needle.charAt(i) != this.source.charAt(j)) {
                return false;
            }
        }
        if (consume) {
            this.index += needleLength;
        }
        return true;
    }
    /**
     * 匹配任意字符串
     *
     * @param strs 任意字符串
     * @return
     */
    matchAny(consume, ...strs) {
        for (const str of strs) {
            if (this.match(str, consume)) {
                return true;
            }
        }
        return false;
    }
    /**
     * 返回是否是数字
     **/
    matchDigit(consume) {
        if (this.index >= this.end) {
            return false;
        }
        const c = this.source.charAt(this.index);
        if (Number.isNaN(c)) {
            if (consume) {
                this.index++;
            }
            return true;
        }
        return false;
    }
    /**
     * 跳过一行
     */
    skipLine() {
        while (this.index < this.end) {
            if (this.source.charAt(this.index++) == '\n') {
                break;
            }
        }
    }
    /**
     * 直到给定的字符串之前全部跳过
     */
    skipUntil(chars) {
        while (this.index < this.end) {
            let matched = true;
            for (let i = 0, len = chars.length; i < len && this.index + i < this.end; i++) {
                if (chars.charAt(i) != this.source.charAt(this.index + i)) {
                    matched = false;
                    break;
                }
            }
            this.index += matched ? chars.length : 1;
            if (matched) {
                return true;
            }
        }
        return false;
    }
    /**
     * 跳过空白字符
     */
    skipWhiteSpace() {
        while (this.index < this.end) {
            const c = this.source.charAt(this.index);
            if (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
                this.index++;
            }
            else {
                break;
            }
        }
    }
    /**
     * 记录当前位置为Span的开始位置
     **/
    startSpan() {
        this.spanStart = this.index;
    }
    /**
     * 根据当前位置 - offset 返回 Span
     */
    endSpan(offset = 0) {
        return new Span_1.default(this.source, this.spanStart, this.index + offset);
    }
    endSpan1(start, end) {
        return new Span_1.default(this.source, start, end);
    }
    /**
     * 返回当前位置
     **/
    getPosition() {
        return this.index;
    }
    /**
     * 重置当前位置
     */
    reset(position) {
        this.index = position;
    }
}
exports.default = CharacterStream;
