All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.aws.smithy.kotlin.runtime.serde.xml.deserialization.StringTextStream.kt Maven / Gradle / Ivy

Go to download

XML serialization and deserialization for Smithy services generated by smithy-kotlin

There is a newer version: 1.3.31
Show newest version
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */
package aws.smithy.kotlin.runtime.serde.xml.deserialization

import aws.smithy.kotlin.runtime.InternalApi
import aws.smithy.kotlin.runtime.serde.DeserializationException
import kotlin.math.max
import kotlin.math.min

private val nonAscii = """[^\x20-\x7E]""".toRegex()

/**
 * A stream of text characters that can be processed sequentially. This stream maintains a current position (i.e.,
 * offset in the string) from which all reading operations begin. The stream is advanced by `read` operations. The
 * stream is **not** advanced by `peek` operations.
 * @param source The source text for this stream.
 */
@InternalApi
public class StringTextStream(private val source: String) {
    private val end = source.length
    private var offset = 0

    /**
     * Advance the position by the given [length]. Throws an exception if this would advance beyond the end of the
     * stream.
     * @param length The length by which to advance the stream position.
     */
    public fun advance(length: Int, errCondition: String) {
        checkBounds(length, errCondition)
        offset += length
    }

    /**
     * Advances the position if the given [text] is next in the stream. Otherwise, the offset is not updated.
     * @param text The text to look for at the current offset.
     * @return True if the given [text] was found and the offset was advanced; otherwise, false.
     */
    public fun advanceIf(text: String): Boolean =
        if (source.startsWith(text, offset)) {
            offset += text.length
            true
        } else {
            false
        }

    /**
     * Advances the position until a whitespace character is found (i.e., one of ' ', '\r', '\n', '\t').
     */
    public fun advanceUntilSpace() {
        while (offset < end) {
            val ch = source[offset]
            if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t') return
            offset++
        }
    }

    /**
     * Advances the position until a non-whitespace character is found (i.e., not one of ' ', '\r', '\n', '\t').
     */
    public fun advanceWhileSpace() {
        while (offset < end) {
            val ch = source[offset]
            if (ch != ' ' && ch != '\r' && ch != '\n' && ch != '\t') return
            offset++
        }
    }

    /**
     * Checks whether the bounds of the stream would be exceeded by advancing the given number of characters and, if so,
     * throws an exception.
     * @param length The amount beyond the current position to check.
     * @param errCondition The condition to include in an error message if necessary.
     */
    @Suppress("NOTHING_TO_INLINE")
    private inline fun checkBounds(length: Int, errCondition: String) {
        if (offset + length > end) error("Unexpected end-of-doc while $errCondition")
    }

    /**
     * Throws a [DeserializationException] with the given message and location string. Automatically includes the
     * current offset and a preview of the surrounding characters. For example:
     * ```
     * DeserializationException: Error msg
     * At offset 123 (showing range 120-126):
     * !




© 2015 - 2025 Weber Informatics LLC | Privacy Policy