<commit_before>import strutils

proc relativePathToPath*(path, toPath: string): string =
    # Returns a relative path to `toPath` which is equivalent of absolute `path`
    # E.g. given `path` = "/a/b/c/d/e" and `toPath` = "/a/b/c/f/g"
    # result = "../../f/g"

    let pc = path.split({'/', '\\'})
    let tpc = toPath.split({'/', '\\'})

    let ln = min(pc.len, tpc.len)
    var cp = 0
    while cp < ln:
        if pc[cp] != tpc[cp]: break
        inc cp

    var ccp = pc.len - cp
    result = ""
    while ccp > 0:
        result &= "../"
        dec ccp
    while cp < tpc.len:
        result &= tpc[cp]
        if cp != tpc.len - 1:
            result &= "/"
        inc cp

proc normalizePath*(path: var string) =
    let ln = path.len
    var j = 0
    var i = 0

    template isSep(c: char): bool = c == '/' or c == '\\'
    template rollback() =
        dec j
        if j < 0:
            raise newException(Exception, "Path is too relative: " & path)
        while j > 0:
            if path[j].isSep: break
            dec j

    while i < ln:
        var copyChar = true
        if path[i].isSep:
            if ln > i + 1:
                if path[i + 1] == '.':
                    if ln > i + 2:
                        if path[i + 2] == '.':
                            rollback()
                            copyChar = false
                            i += 3
                            if j == 0: inc i
                        elif path[i + 2].isSep:
                            copyChar = false
                            i += 2
        if copyChar:
            path[j] = path[i]
            when defined(windows):
                if path[j] == '/': path[j] = '\\'
            else:
                if path[j] == '\\': path[j] = '/'

            inc j
            inc i
    path.setLen(j)

proc isSubpathOf*(child, parent: string): bool =
    if child.len < parent.len: return false
    let ln = parent.len
    var i = 0
    while i < ln:
        if parent[i] != child[i]: return false
        inc i
    return i == child.len or child[i] == '/' or parent[i - 1] == '/'

when defined(js):
    proc getCurrentHref*(): string =
        var s: cstring
        {.emit: """<commit_msg>Added toAbsolutePath<commit_after>import strutils, ospaths

proc relativePathToPath*(path, toPath: string): string =
    # Returns a relative path to `toPath` which is equivalent of absolute `path`
    # E.g. given `path` = "/a/b/c/d/e" and `toPath` = "/a/b/c/f/g"
    # result = "../../f/g"

    let pc = path.split({'/', '\\'})
    let tpc = toPath.split({'/', '\\'})

    let ln = min(pc.len, tpc.len)
    var cp = 0
    while cp < ln:
        if pc[cp] != tpc[cp]: break
        inc cp

    var ccp = pc.len - cp
    result = ""
    while ccp > 0:
        result &= "../"
        dec ccp
    while cp < tpc.len:
        result &= tpc[cp]
        if cp != tpc.len - 1:
            result &= "/"
        inc cp

proc normalizePath*(path: var string) =
    let ln = path.len
    var j = 0
    var i = 0

    template isSep(c: char): bool = c == '/' or c == '\\'
    template rollback() =
        dec j
        if j < 0:
            raise newException(Exception, "Path is too relative: " & path)
        while j > 0:
            if path[j].isSep: break
            dec j

    while i < ln:
        var copyChar = true
        if path[i].isSep:
            if ln > i + 1:
                if path[i + 1] == '.':
                    if ln > i + 2:
                        if path[i + 2] == '.':
                            rollback()
                            copyChar = false
                            i += 3
                            if j == 0: inc i
                        elif path[i + 2].isSep:
                            copyChar = false
                            i += 2
        if copyChar:
            path[j] = path[i]
            when defined(windows):
                if path[j] == '/': path[j] = '\\'
            else:
                if path[j] == '\\': path[j] = '/'

            inc j
            inc i
    path.setLen(j)

proc isSubpathOf*(child, parent: string): bool =
    if child.len < parent.len: return false
    let ln = parent.len
    var i = 0
    while i < ln:
        if parent[i] != child[i]: return false
        inc i
    return i == child.len or child[i] == '/' or parent[i - 1] == '/'

proc toAbsolutePath*(relativeOrAbsolutePath, basePath: string): string =
    if isAbsolute(relativeOrAbsolutePath): return relativeOrAbsolutePath
    result = basePath / relativeOrAbsolutePath
    normalizePath(result)

when defined(js):
    proc getCurrentHref*(): string =
        var s: cstring
        {.emit: """
{'fraction_non_alphanumeric': 0.13833907056798622, 'fraction_numerical': 0.007314974182444062, 'mean_word_length': 1.2666991711360311, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7275967', 'n_tokens_mistral': 1531, 'n_tokens_neox': 1449, 'n_words': 445}