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

commonMain.dsv.dsvCommon.kt Maven / Gradle / Ivy

/*
 * Copyright (c) 2018-2021. data2viz sàrl.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package io.data2viz.dsv

import io.data2viz.dsv.Dsv.Token.*

public class Dsv(

    private val delimiterCode: Char = ',') {

    internal sealed class Token {
        class EOF : Token()
        class EOL : Token()
        class TextToken(val content: String) : Token()
    }

    public fun parseRows(text: String): List> {

        val rows = mutableListOf>()
        val N = text.length
        var I = 0
        var n = 0
        val EOL = EOL()
        var eol = false
        var eof = false
        val regexp by lazy { Regex("\"\"") }

        fun token(): Token {
            if (eof || I >= N) return EOF()
            if (eol) {
                eol = false
                return EOL
            }

            val j = I
            var c: Char

//            var i, j = I, c;
//            if (text.charCodeAt(j) === QUOTE) {
//                while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE);
//                if ((i = I) >= N) eof = true;
//                else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true;
//                else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; }
//                return text.slice(j + 1, i - 1).replace(/""/g, "\"");
//            }

            // Unescape quotes
            if (text[j] == '"') {
                while (I++ < N && text[I] != '"' || (++I < N && text[I] == '"')) {}

                // Find next delimiter or newline
                val i = I
                if (I >= N) eof = true
                else {
                    c = text[I++]
                    if (c == '\n') eol = true
                    else if (c == '\r') {
                        eol = true
                        if (text[I] == '\n') ++I
                    }
                }
                return TextToken(text.substring(j + 1, i - 1).replace(regexp, "\""))
            }

            while (I < N) {
                var k = 1
                c = text[I++]
                if (c == '\n') {
                    eol = true
                } else if (c == '\r') {
                    eol = true; if (text[I] == '\n') {
                        ++I; ++k
                    }
                } else if (c != delimiterCode) {
                    continue
                }
                return TextToken(text.substring(j, I - k))
            }

            // special case: last token before EOF
            return TextToken(text.substring(j))
        }

        var t = token()
        while (t !is EOF) {
            val row = mutableListOf()
            while (t is TextToken) {
                row += t.content
                t = token()
            }
            rows += row
            t = token()
        }
        return rows.toList()
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy