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

commonMain.org.intellij.markdown.lexer.Compat.kt Maven / Gradle / Ivy

There is a newer version: 0.7.3
Show newest version
package org.intellij.markdown.lexer

import org.intellij.markdown.MarkdownParsingException

object Compat {
    private const val MIN_SUPPLEMENTARY_CODE_POINT = 0x010000
    private const val MIN_HIGH_SURROGATE = '\uD800'
    private const val MIN_LOW_SURROGATE = '\uDC00'

    fun CharSequence.forEachCodePoint(f: (Int) -> Unit) {
        var offset = 0
        while (offset < length) {
            val codePoint = codePointAt(this, offset)
            f(codePoint)
            offset += charCount(codePoint)
        }
    }

    fun codePointToString(c: Int): String {
        return if (charCount(c) == 1) {
            c.toChar().toString()
        }
        else {
            val high = ((c ushr 10) + (MIN_HIGH_SURROGATE.code - (MIN_SUPPLEMENTARY_CODE_POINT ushr 10))).toChar()
            val low = ((c and 0x3ff) + MIN_LOW_SURROGATE.code).toChar()
            charArrayOf(high, low).concatToString()
        }
    }

    fun offsetByCodePoints(seq: CharSequence, index: Int,
                           codePointOffset: Int): Int {
        val length = seq.length
        if (index < 0 || index > length) {
            throw IndexOutOfBoundsException()
        }

        var x = index
        if (codePointOffset >= 0) {
            var i: Int
            i = 0
            while (x < length && i < codePointOffset) {
                if (seq[x++].isHighSurrogate() && x < length &&
                        seq[x].isLowSurrogate()) {
                    x++
                }
                i++
            }
            if (i < codePointOffset) {
                throw IndexOutOfBoundsException()
            }
        } else {
            var i: Int
            i = codePointOffset
            while (x > 0 && i < 0) {
                if (seq[--x].isLowSurrogate() && x > 0 &&
                        seq[x - 1].isHighSurrogate()) {
                    x--
                }
                i++
            }
            if (i < 0) {
                throw IndexOutOfBoundsException()
            }
        }
        return x
    }

    fun codePointBefore(seq: CharSequence, index: Int): Int {
        var index = index
        val c2 = seq[--index]
        if (c2.isLowSurrogate() && index > 0) {
            val c1 = seq[--index]
            if (c1.isHighSurrogate()) {
                return toCodePoint(c1, c2)
            }
        }
        return c2.code
    }

    fun charCount(char: Int): Int {
        return if (char >= MIN_SUPPLEMENTARY_CODE_POINT) 2 else 1
    }

    fun toCodePoint(high: Char, low: Char): Int {
        // Optimized form of:
        // return ((high - MIN_HIGH_SURROGATE) << 10)
        //         + (low - MIN_LOW_SURROGATE)
        //         + MIN_SUPPLEMENTARY_CODE_POINT;
        return (high.code shl 10) + low.code + (MIN_SUPPLEMENTARY_CODE_POINT
                - (Char.MIN_HIGH_SURROGATE.code shl 10)
                - Char.MIN_LOW_SURROGATE.code)
    }

    fun codePointAt(seq: CharSequence, index: Int): Int {
        var index = index
        val c1 = seq[index]
        if (c1.isHighSurrogate() && ++index < seq.length) {
            val c2 = seq[index]
            if (c2.isLowSurrogate()) {
                return toCodePoint(c1, c2)
            }
        }
        return c1.code
    }

    inline fun assert(condition: Boolean, messageProducer: () -> String = { "" }) {
        if (!condition) {
            throw MarkdownParsingException(messageProducer())
        }
    }
}

open class Stack : MutableList by ArrayList() {
    fun push(e: E) {
        add(e)
    }

    fun pop(): E {
        val result = last()
        removeAt(size - 1)
        return result
    }

    fun peek() = last()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy