class Url

class Url

lib/url.tya:2

Url provides the url/Url standard library API.

Source
# Url provides the url/Url standard library API.
class Url
  # Url.value stores instance state.
  # @type Nil
  value: nil

  # Url.initialize stores a URL or query value.
  # @param value String value value.
  # @return Self the initialized object.
  initialize: value = nil ->
    self.value = value

  # Url.build provides the url/Url standard library operation.
  # @param parts Array parts value.
  # @return Any the resulting value.
  build: parts = nil ->
    self.format(parts)

  # Url.contains_colon? provides the url/Url standard library operation.
  # @param text String text value.
  # @return Boolean whether the condition is true.
  contains_colon?: text ->
    i = 0
    while i < text.byte_len()
      if text[i] == ":"
        return true
      i = i + 1
    false

  # Url.decimal? provides the url/Url standard library operation.
  # @param text String text value.
  # @return Boolean whether the condition is true.
  decimal?: text ->
    if text == ""
      return false
    i = 0
    while i < text.byte_len()
      c = ord(text[i])
      if c < 48 or c > 57
        return false
      i = i + 1
    true

  # Url.decode provides the url/Url standard library operation.
  # @param text String text value.
  # @return String the resulting value.
  decode: text = nil ->
    if text == nil
      text = self.value
    n = text.byte_len()
    out = ""
    i = 0
    while i < n
      c = text[i]
      if c == "%"
        if i + 2 >= n
          raise error("url.decode: truncated percent-escape")
        hi = Url(nil).decode_hex(text[i + 1])
        lo = Url(nil).decode_hex(text[i + 2])
        out = out + chr(hi * 16 + lo)
        i = i + 3
      else
        out = out + c
        i = i + 1
    out

  # Url.decode_hex provides the url/Url standard library operation.
  # @param c Any c value.
  # @return Any the resulting value.
  decode_hex: c ->
    code = ord(c)
    if code >= 48 and code <= 57
      return code - 48
    if code >= 65 and code <= 70
      return code - 55
    if code >= 97 and code <= 102
      return code - 87
    raise error("url.decode: invalid percent-escape")

  # Url.decode_query provides the url/Url standard library operation.
  # @param text String text value.
  # @return Any the resulting value.
  decode_query: text = nil ->
    if text == nil
      text = self.value
    out = []
    if text == ""
      return out
    raw_pairs = text.split("&")
    for raw in raw_pairs
      if raw != ""
        eq_idx = -1
        n = raw.byte_len()
        i = 0
        while i < n and eq_idx < 0
          if raw[i] == "="
            eq_idx = i
          i = i + 1
        if eq_idx < 0
          k = Url(nil).decode_query_value(raw)
          out.push([k, ""])
        else
          k_raw = ""
          v_raw = ""
          i = 0
          while i < eq_idx
            k_raw = k_raw + raw[i]
            i = i + 1
          i = eq_idx + 1
          while i < n
            v_raw = v_raw + raw[i]
            i = i + 1
          out.push(
            [Url(nil).decode_query_value(k_raw), Url(nil).decode_query_value(v_raw)]
          )
    out

  # Url.decode_query_value provides the url/Url standard library operation.
  # @param text String text value.
  # @return Any the resulting value.
  decode_query_value: text ->
    n = text.byte_len()
    out = ""
    i = 0
    while i < n
      c = text[i]
      if c == "+"
        out = out + " "
        i = i + 1
      elseif c == "%"
        if i + 2 >= n
          raise error("url.decode_query: truncated percent-escape")
        hi = Url(nil).decode_hex(text[i + 1])
        lo = Url(nil).decode_hex(text[i + 2])
        out = out + chr(hi * 16 + lo)
        i = i + 3
      else
        out = out + c
        i = i + 1
    out

  # Url.encode provides the url/Url standard library operation.
  # @param text String text value.
  # @return String the resulting value.
  encode: text = nil ->
    if text == nil
      text = self.value
    n = text.byte_len()
    out = ""
    i = 0
    while i < n
      c = text[i]
      code = ord(c)
      if Url(nil).is_unreserved(code)
        out = out + c
      else
        hi = Url(nil).hex_digit(code / 16.to_i())
        lo = Url(nil).hex_digit(code % 16)
        out = out + "%" + hi + lo
      i = i + 1
    out

  # Url.encode_query provides the url/Url standard library operation.
  # @param pairs Any pairs value.
  # @return Any the resulting value.
  encode_query: pairs = nil ->
    if pairs == nil
      pairs = self.value
    parts_a = []
    if pairs.has("kind")
      raise error("url.encode_query: pass a dict or array of [key, value] pairs")
    names = pairs.keys()
    if names.len() > 0
      for k in names
        v = pairs[k]
        encoded_k = Url(nil).encode(k)
        encoded_v = Url(nil).encode(v)
        parts_a.push("{encoded_k}={encoded_v}")
    parts_a.join("&")

  # Url.encode_query_pairs provides the url/Url standard library operation.
  # @param pairs Any pairs value.
  # @return Any the resulting value.
  encode_query_pairs: pairs ->
    parts_a = []
    for pair in pairs
      k = pair[0]
      v = pair[1]
      encoded_k = Url(nil).encode(k)
      encoded_v = Url(nil).encode(v)
      parts_a.push("{encoded_k}={encoded_v}")
    parts_a.join("&")

  # Url.format provides the url/Url standard library operation.
  # @param parts Array parts value.
  # @return Any the resulting value.
  format: parts = nil ->
    if parts == nil
      parts = self.value
    out = ""
    if parts.has("scheme") and parts["scheme"] != ""
      out = out + parts["scheme"] + ":"
    has_host = parts.has("host") and parts["host"] != ""
    has_user = parts.has("user") and parts["user"] != ""
    if has_host or has_user
      out = out + "//"
      if has_user
        out = out + parts["user"]
        if parts.has("password") and parts["password"] != ""
          out = out + ":" + parts["password"]
        out = out + "@"
      if has_host
        if (
          Url(nil).contains_colon?(parts["host"]) and not parts["host"].starts_with("[")
        )
          out = out + "[" + parts["host"] + "]"
        else
          out = out + parts["host"]
      if parts.has("port") and parts["port"] != ""
        out = out + ":" + parts["port"]
    if parts.has("path") and parts["path"] != ""
      out = out + parts["path"]
    if parts.has("query") and parts["query"] != ""
      out = out + "?" + parts["query"]
    if parts.has("fragment") and parts["fragment"] != ""
      out = out + "#" + parts["fragment"]
    out

  # Url.hex_digit provides the url/Url standard library operation.
  # @param d Any d value.
  # @return Any the resulting value.
  hex_digit: d ->
    if d < 10
      return chr(48 + d)
    chr(55 + d)

  # Url.is_unreserved provides the url/Url standard library operation.
  # @param code Int code value.
  # @return Boolean the resulting value.
  is_unreserved: code ->
    if code >= 65 and code <= 90
      return true
    if code >= 97 and code <= 122
      return true
    if code >= 48 and code <= 57
      return true
    if code == 45 or code == 46 or code == 95 or code == 126
      return true
    false

  # Url.merge_path provides the url/Url standard library operation.
  # @param base_path String base path value.
  # @param ref_path String ref path value.
  # @return String the resulting value.
  merge_path: base_path, ref_path ->
    idx = -1
    i = 0
    while i < base_path.byte_len()
      if base_path[i] == "/"
        idx = i
      i = i + 1
    if idx < 0
      return ref_path
    base_path.slice(0, idx + 1) + ref_path

  # Url.normalize provides the url/Url standard library operation.
  # @param text String text value.
  # @return String the resulting value.
  normalize: text = nil ->
    if text == nil
      text = self.value
    p = Url(nil).parse(text)
    p["scheme"] = p["scheme"].lower()
    p["host"] = p["host"].lower()
    p["path"] = Url(nil).normalize_path(p["path"])
    Url(nil).format(p)

  # Url.normalize_path provides the url/Url standard library operation.
  # @param path String path value.
  # @return String the resulting value.
  normalize_path: path ->
    absolute = path.starts_with("/")
    trailing = path.ends_with("/") and path != "/"
    parts = path.split("/")
    stack = []
    for part in parts
      if part == "" or part == "."
        nil
      elseif part == ".."
        if stack.len() > 0
          stack.pop()
      else
        stack.push(part)
    out = stack.join("/")
    if absolute
      out = "/" + out
    if out == "" and absolute
      out = "/"
    if trailing and not out.ends_with("/")
      out = out + "/"
    out

  # Url.parse provides the url/Url standard library operation.
  # @param text String text value.
  # @return Any the resulting value.
  parse: text = nil ->
    if text == nil
      text = self.value
    n = text.byte_len()
    out =
      scheme: ""
      user: ""
      password: ""
      host: ""
      port: ""
      path: ""
      query: ""
      fragment: ""
      has_query: false
      has_authority: false
    i = 0
    scheme_end = -1
    j = 0
    while j < n and scheme_end < 0
      c = text[j]
      if c == ":"
        scheme_end = j
      elseif c == "/" or c == "?" or c == "#"
        j = n
      j = j + 1
    if scheme_end >= 0
      scheme_text = ""
      k = 0
      while k < scheme_end
        scheme_text = scheme_text + text[k]
        k = k + 1
      out["scheme"] = scheme_text
      i = scheme_end + 1
    has_authority = false
    if i + 1 < n and text[i] == "/" and text[i + 1] == "/"
      has_authority = true
      i = i + 2
    if has_authority
      out["has_authority"] = true
      auth_end = i
      while (
        auth_end < n and text[auth_end] != "/" and text[auth_end] != "?" and text[auth_end] != "#"
      )
        auth_end = auth_end + 1
      auth_text = ""
      k = i
      while k < auth_end
        auth_text = auth_text + text[k]
        k = k + 1
      i = auth_end
      at_idx = -1
      ai = 0
      auth_n = auth_text.byte_len()
      while ai < auth_n
        if auth_text[ai] == "@"
          at_idx = ai
        ai = ai + 1
      userinfo = ""
      hostport = auth_text
      if at_idx >= 0
        k = 0
        while k < at_idx
          userinfo = userinfo + auth_text[k]
          k = k + 1
        hostport = ""
        k = at_idx + 1
        while k < auth_n
          hostport = hostport + auth_text[k]
          k = k + 1
      if userinfo != ""
        colon_idx = -1
        ci = 0
        ui_n = userinfo.byte_len()
        while ci < ui_n
          if userinfo[ci] == ":"
            colon_idx = ci
            ci = ui_n
          ci = ci + 1
        if colon_idx < 0
          out["user"] = userinfo
        else
          user_part = ""
          pass_part = ""
          k = 0
          while k < colon_idx
            user_part = user_part + userinfo[k]
            k = k + 1
          k = colon_idx + 1
          while k < ui_n
            pass_part = pass_part + userinfo[k]
            k = k + 1
          out["user"] = user_part
          out["password"] = pass_part
      hp_n = hostport.byte_len()
      if hp_n > 0 and hostport[0] == "["
        close_idx = -1
        ci = 1
        while ci < hp_n and close_idx < 0
          if hostport[ci] == "]"
            close_idx = ci
          ci = ci + 1
        if close_idx < 0
          raise error("url.parse: invalid IPv6 host")
        out["host"] = hostport.slice(1, close_idx)
        if close_idx + 1 < hp_n
          if hostport[close_idx + 1] != ":"
            raise error("url.parse: invalid host")
          port_part = hostport.slice(close_idx + 2, hp_n)
          if not Url(nil).decimal?(port_part)
            raise error("url.parse: invalid port")
          out["port"] = port_part
      else
        colon_idx = -1
        ci = 0
        while ci < hp_n
          if hostport[ci] == ":"
            colon_idx = ci
            ci = hp_n
          ci = ci + 1
        if colon_idx < 0
          out["host"] = hostport
        else
          host_part = hostport.slice(0, colon_idx)
          port_part = hostport.slice(colon_idx + 1, hp_n)
          if not Url(nil).decimal?(port_part)
            raise error("url.parse: invalid port")
          out["host"] = host_part
          out["port"] = port_part
    path_end = i
    while path_end < n and text[path_end] != "?" and text[path_end] != "#"
      path_end = path_end + 1
    path_text = ""
    k = i
    while k < path_end
      path_text = path_text + text[k]
      k = k + 1
    out["path"] = path_text
    Url(nil).validate_percent(path_text)
    i = path_end
    if i < n and text[i] == "?"
      out["has_query"] = true
      i = i + 1
      query_end = i
      while query_end < n and text[query_end] != "#"
        query_end = query_end + 1
      query_text = ""
      k = i
      while k < query_end
        query_text = query_text + text[k]
        k = k + 1
      out["query"] = query_text
      Url(nil).validate_percent(query_text)
      i = query_end
    if i < n and text[i] == "#"
      i = i + 1
      frag_text = ""
      while i < n
        frag_text = frag_text + text[i]
        i = i + 1
      out["fragment"] = frag_text
      Url(nil).validate_percent(frag_text)
    out

  # Url.query_dict provides the url/Url standard library operation.
  # @param query Any query value.
  # @return Dict the resulting value.
  query_dict: query ->
    pairs = query
    if query.class == String
      pairs = Url(nil).decode_query(query)
    out = {}
    for pair in pairs
      k = pair[0]
      v = pair[1]
      if out.has(k)
        old = out[k]
        if old.class == Array
          old.push(v)
        else
          out[k] = [old, v]
      else
        out[k] = v
    out

  # Url.resolve provides the url/Url standard library operation.
  # @param base Any base value.
  # @param ref Any ref value.
  # @return Any the resulting value.
  resolve: base, ref ->
    b = Url(nil).parse(base)
    r = Url(nil).parse(ref)
    if r["scheme"] != ""
      return Url(nil).normalize(Url(nil).format(r))
    out =
      scheme: b["scheme"]
      user: ""
      password: ""
      host: ""
      port: ""
      path: ""
      query: ""
      fragment: r["fragment"]
    if r["has_authority"]
      out["user"] = r["user"]
      out["password"] = r["password"]
      out["host"] = r["host"]
      out["port"] = r["port"]
      out["path"] = Url(nil).normalize_path(r["path"])
      out["query"] = r["query"]
    else
      out["user"] = b["user"]
      out["password"] = b["password"]
      out["host"] = b["host"]
      out["port"] = b["port"]
      if r["path"] == ""
        out["path"] = b["path"]
        if r["has_query"]
          out["query"] = r["query"]
        else
          out["query"] = b["query"]
      elseif r["path"].starts_with("/")
        out["path"] = Url(nil).normalize_path(r["path"])
        out["query"] = r["query"]
      else
        out["path"] = Url(nil).normalize_path(
          Url(nil).merge_path(b["path"], r["path"])
        )
        out["query"] = r["query"]
    Url(nil).format(out)

  # Url.validate_percent provides the url/Url standard library operation.
  # @param text String text value.
  # @return Boolean the resulting value.
  validate_percent: text ->
    n = text.byte_len()
    i = 0
    while i < n
      if text[i] == "%"
        if i + 2 >= n
          raise error("url.decode: truncated percent-escape")
        Url(nil).decode_hex(text[i + 1])
        Url(nil).decode_hex(text[i + 2])
        i = i + 3
      else
        i = i + 1
    nil

Instance Variables

value

Url.value

lib/url.tya:5

Url.value stores instance state.

Source
  # Url.value stores instance state.
  # @type Nil
  value: nil

Methods

build

Url.build(parts = nil)

lib/url.tya:16

Url.build provides the url/Url standard library operation.

Source
  # Url.build provides the url/Url standard library operation.
  # @param parts Array parts value.
  # @return Any the resulting value.
  build: parts = nil ->
    self.format(parts)

contains_colon?

Url.contains_colon?(text)

lib/url.tya:22

Url.contains_colon? provides the url/Url standard library operation.

Source
  # Url.contains_colon? provides the url/Url standard library operation.
  # @param text String text value.
  # @return Boolean whether the condition is true.
  contains_colon?: text ->
    i = 0
    while i < text.byte_len()
      if text[i] == ":"
        return true
      i = i + 1
    false

decimal?

Url.decimal?(text)

lib/url.tya:33

Url.decimal? provides the url/Url standard library operation.

Source
  # Url.decimal? provides the url/Url standard library operation.
  # @param text String text value.
  # @return Boolean whether the condition is true.
  decimal?: text ->
    if text == ""
      return false
    i = 0
    while i < text.byte_len()
      c = ord(text[i])
      if c < 48 or c > 57
        return false
      i = i + 1
    true

decode

Url.decode(text = nil)

lib/url.tya:47

Url.decode provides the url/Url standard library operation.

Source
  # Url.decode provides the url/Url standard library operation.
  # @param text String text value.
  # @return String the resulting value.
  decode: text = nil ->
    if text == nil
      text = self.value
    n = text.byte_len()
    out = ""
    i = 0
    while i < n
      c = text[i]
      if c == "%"
        if i + 2 >= n
          raise error("url.decode: truncated percent-escape")
        hi = Url(nil).decode_hex(text[i + 1])
        lo = Url(nil).decode_hex(text[i + 2])
        out = out + chr(hi * 16 + lo)
        i = i + 3
      else
        out = out + c
        i = i + 1
    out

decode_hex

Url.decode_hex(c)

lib/url.tya:70

Url.decode_hex provides the url/Url standard library operation.

Source
  # Url.decode_hex provides the url/Url standard library operation.
  # @param c Any c value.
  # @return Any the resulting value.
  decode_hex: c ->
    code = ord(c)
    if code >= 48 and code <= 57
      return code - 48
    if code >= 65 and code <= 70
      return code - 55
    if code >= 97 and code <= 102
      return code - 87
    raise error("url.decode: invalid percent-escape")

decode_query

Url.decode_query(text = nil)

lib/url.tya:83

Url.decode_query provides the url/Url standard library operation.

Source
  # Url.decode_query provides the url/Url standard library operation.
  # @param text String text value.
  # @return Any the resulting value.
  decode_query: text = nil ->
    if text == nil
      text = self.value
    out = []
    if text == ""
      return out
    raw_pairs = text.split("&")
    for raw in raw_pairs
      if raw != ""
        eq_idx = -1
        n = raw.byte_len()
        i = 0
        while i < n and eq_idx < 0
          if raw[i] == "="
            eq_idx = i
          i = i + 1
        if eq_idx < 0
          k = Url(nil).decode_query_value(raw)
          out.push([k, ""])
        else
          k_raw = ""
          v_raw = ""
          i = 0
          while i < eq_idx
            k_raw = k_raw + raw[i]
            i = i + 1
          i = eq_idx + 1
          while i < n
            v_raw = v_raw + raw[i]
            i = i + 1
          out.push(
            [Url(nil).decode_query_value(k_raw), Url(nil).decode_query_value(v_raw)]
          )
    out

decode_query_value

Url.decode_query_value(text)

lib/url.tya:121

Url.decode_query_value provides the url/Url standard library operation.

Source
  # Url.decode_query_value provides the url/Url standard library operation.
  # @param text String text value.
  # @return Any the resulting value.
  decode_query_value: text ->
    n = text.byte_len()
    out = ""
    i = 0
    while i < n
      c = text[i]
      if c == "+"
        out = out + " "
        i = i + 1
      elseif c == "%"
        if i + 2 >= n
          raise error("url.decode_query: truncated percent-escape")
        hi = Url(nil).decode_hex(text[i + 1])
        lo = Url(nil).decode_hex(text[i + 2])
        out = out + chr(hi * 16 + lo)
        i = i + 3
      else
        out = out + c
        i = i + 1
    out

encode

Url.encode(text = nil)

lib/url.tya:145

Url.encode provides the url/Url standard library operation.

Source
  # Url.encode provides the url/Url standard library operation.
  # @param text String text value.
  # @return String the resulting value.
  encode: text = nil ->
    if text == nil
      text = self.value
    n = text.byte_len()
    out = ""
    i = 0
    while i < n
      c = text[i]
      code = ord(c)
      if Url(nil).is_unreserved(code)
        out = out + c
      else
        hi = Url(nil).hex_digit(code / 16.to_i())
        lo = Url(nil).hex_digit(code % 16)
        out = out + "%" + hi + lo
      i = i + 1
    out

encode_query

Url.encode_query(pairs = nil)

lib/url.tya:166

Url.encode_query provides the url/Url standard library operation.

Source
  # Url.encode_query provides the url/Url standard library operation.
  # @param pairs Any pairs value.
  # @return Any the resulting value.
  encode_query: pairs = nil ->
    if pairs == nil
      pairs = self.value
    parts_a = []
    if pairs.has("kind")
      raise error("url.encode_query: pass a dict or array of [key, value] pairs")
    names = pairs.keys()
    if names.len() > 0
      for k in names
        v = pairs[k]
        encoded_k = Url(nil).encode(k)
        encoded_v = Url(nil).encode(v)
        parts_a.push("{encoded_k}={encoded_v}")
    parts_a.join("&")

encode_query_pairs

Url.encode_query_pairs(pairs)

lib/url.tya:184

Url.encode_query_pairs provides the url/Url standard library operation.

Source
  # Url.encode_query_pairs provides the url/Url standard library operation.
  # @param pairs Any pairs value.
  # @return Any the resulting value.
  encode_query_pairs: pairs ->
    parts_a = []
    for pair in pairs
      k = pair[0]
      v = pair[1]
      encoded_k = Url(nil).encode(k)
      encoded_v = Url(nil).encode(v)
      parts_a.push("{encoded_k}={encoded_v}")
    parts_a.join("&")

format

Url.format(parts = nil)

lib/url.tya:197

Url.format provides the url/Url standard library operation.

Source
  # Url.format provides the url/Url standard library operation.
  # @param parts Array parts value.
  # @return Any the resulting value.
  format: parts = nil ->
    if parts == nil
      parts = self.value
    out = ""
    if parts.has("scheme") and parts["scheme"] != ""
      out = out + parts["scheme"] + ":"
    has_host = parts.has("host") and parts["host"] != ""
    has_user = parts.has("user") and parts["user"] != ""
    if has_host or has_user
      out = out + "//"
      if has_user
        out = out + parts["user"]
        if parts.has("password") and parts["password"] != ""
          out = out + ":" + parts["password"]
        out = out + "@"
      if has_host
        if (
          Url(nil).contains_colon?(parts["host"]) and not parts["host"].starts_with("[")
        )
          out = out + "[" + parts["host"] + "]"
        else
          out = out + parts["host"]
      if parts.has("port") and parts["port"] != ""
        out = out + ":" + parts["port"]
    if parts.has("path") and parts["path"] != ""
      out = out + parts["path"]
    if parts.has("query") and parts["query"] != ""
      out = out + "?" + parts["query"]
    if parts.has("fragment") and parts["fragment"] != ""
      out = out + "#" + parts["fragment"]
    out

hex_digit

Url.hex_digit(d)

lib/url.tya:232

Url.hex_digit provides the url/Url standard library operation.

Source
  # Url.hex_digit provides the url/Url standard library operation.
  # @param d Any d value.
  # @return Any the resulting value.
  hex_digit: d ->
    if d < 10
      return chr(48 + d)
    chr(55 + d)

initialize

Url.initialize(value = nil)

lib/url.tya:10

Url.initialize stores a URL or query value.

Source
  # Url.initialize stores a URL or query value.
  # @param value String value value.
  # @return Self the initialized object.
  initialize: value = nil ->
    self.value = value

is_unreserved

Url.is_unreserved(code)

lib/url.tya:240

Url.is_unreserved provides the url/Url standard library operation.

Source
  # Url.is_unreserved provides the url/Url standard library operation.
  # @param code Int code value.
  # @return Boolean the resulting value.
  is_unreserved: code ->
    if code >= 65 and code <= 90
      return true
    if code >= 97 and code <= 122
      return true
    if code >= 48 and code <= 57
      return true
    if code == 45 or code == 46 or code == 95 or code == 126
      return true
    false

merge_path

Url.merge_path(base_path, ref_path)

lib/url.tya:255

Url.merge_path provides the url/Url standard library operation.

Source
  # Url.merge_path provides the url/Url standard library operation.
  # @param base_path String base path value.
  # @param ref_path String ref path value.
  # @return String the resulting value.
  merge_path: base_path, ref_path ->
    idx = -1
    i = 0
    while i < base_path.byte_len()
      if base_path[i] == "/"
        idx = i
      i = i + 1
    if idx < 0
      return ref_path
    base_path.slice(0, idx + 1) + ref_path

normalize

Url.normalize(text = nil)

lib/url.tya:269

Url.normalize provides the url/Url standard library operation.

Source
  # Url.normalize provides the url/Url standard library operation.
  # @param text String text value.
  # @return String the resulting value.
  normalize: text = nil ->
    if text == nil
      text = self.value
    p = Url(nil).parse(text)
    p["scheme"] = p["scheme"].lower()
    p["host"] = p["host"].lower()
    p["path"] = Url(nil).normalize_path(p["path"])
    Url(nil).format(p)

normalize_path

Url.normalize_path(path)

lib/url.tya:281

Url.normalize_path provides the url/Url standard library operation.

Source
  # Url.normalize_path provides the url/Url standard library operation.
  # @param path String path value.
  # @return String the resulting value.
  normalize_path: path ->
    absolute = path.starts_with("/")
    trailing = path.ends_with("/") and path != "/"
    parts = path.split("/")
    stack = []
    for part in parts
      if part == "" or part == "."
        nil
      elseif part == ".."
        if stack.len() > 0
          stack.pop()
      else
        stack.push(part)
    out = stack.join("/")
    if absolute
      out = "/" + out
    if out == "" and absolute
      out = "/"
    if trailing and not out.ends_with("/")
      out = out + "/"
    out

parse

Url.parse(text = nil)

lib/url.tya:306

Url.parse provides the url/Url standard library operation.

Source
  # Url.parse provides the url/Url standard library operation.
  # @param text String text value.
  # @return Any the resulting value.
  parse: text = nil ->
    if text == nil
      text = self.value
    n = text.byte_len()
    out =
      scheme: ""
      user: ""
      password: ""
      host: ""
      port: ""
      path: ""
      query: ""
      fragment: ""
      has_query: false
      has_authority: false
    i = 0
    scheme_end = -1
    j = 0
    while j < n and scheme_end < 0
      c = text[j]
      if c == ":"
        scheme_end = j
      elseif c == "/" or c == "?" or c == "#"
        j = n
      j = j + 1
    if scheme_end >= 0
      scheme_text = ""
      k = 0
      while k < scheme_end
        scheme_text = scheme_text + text[k]
        k = k + 1
      out["scheme"] = scheme_text
      i = scheme_end + 1
    has_authority = false
    if i + 1 < n and text[i] == "/" and text[i + 1] == "/"
      has_authority = true
      i = i + 2
    if has_authority
      out["has_authority"] = true
      auth_end = i
      while (
        auth_end < n and text[auth_end] != "/" and text[auth_end] != "?" and text[auth_end] != "#"
      )
        auth_end = auth_end + 1
      auth_text = ""
      k = i
      while k < auth_end
        auth_text = auth_text + text[k]
        k = k + 1
      i = auth_end
      at_idx = -1
      ai = 0
      auth_n = auth_text.byte_len()
      while ai < auth_n
        if auth_text[ai] == "@"
          at_idx = ai
        ai = ai + 1
      userinfo = ""
      hostport = auth_text
      if at_idx >= 0
        k = 0
        while k < at_idx
          userinfo = userinfo + auth_text[k]
          k = k + 1
        hostport = ""
        k = at_idx + 1
        while k < auth_n
          hostport = hostport + auth_text[k]
          k = k + 1
      if userinfo != ""
        colon_idx = -1
        ci = 0
        ui_n = userinfo.byte_len()
        while ci < ui_n
          if userinfo[ci] == ":"
            colon_idx = ci
            ci = ui_n
          ci = ci + 1
        if colon_idx < 0
          out["user"] = userinfo
        else
          user_part = ""
          pass_part = ""
          k = 0
          while k < colon_idx
            user_part = user_part + userinfo[k]
            k = k + 1
          k = colon_idx + 1
          while k < ui_n
            pass_part = pass_part + userinfo[k]
            k = k + 1
          out["user"] = user_part
          out["password"] = pass_part
      hp_n = hostport.byte_len()
      if hp_n > 0 and hostport[0] == "["
        close_idx = -1
        ci = 1
        while ci < hp_n and close_idx < 0
          if hostport[ci] == "]"
            close_idx = ci
          ci = ci + 1
        if close_idx < 0
          raise error("url.parse: invalid IPv6 host")
        out["host"] = hostport.slice(1, close_idx)
        if close_idx + 1 < hp_n
          if hostport[close_idx + 1] != ":"
            raise error("url.parse: invalid host")
          port_part = hostport.slice(close_idx + 2, hp_n)
          if not Url(nil).decimal?(port_part)
            raise error("url.parse: invalid port")
          out["port"] = port_part
      else
        colon_idx = -1
        ci = 0
        while ci < hp_n
          if hostport[ci] == ":"
            colon_idx = ci
            ci = hp_n
          ci = ci + 1
        if colon_idx < 0
          out["host"] = hostport
        else
          host_part = hostport.slice(0, colon_idx)
          port_part = hostport.slice(colon_idx + 1, hp_n)
          if not Url(nil).decimal?(port_part)
            raise error("url.parse: invalid port")
          out["host"] = host_part
          out["port"] = port_part
    path_end = i
    while path_end < n and text[path_end] != "?" and text[path_end] != "#"
      path_end = path_end + 1
    path_text = ""
    k = i
    while k < path_end
      path_text = path_text + text[k]
      k = k + 1
    out["path"] = path_text
    Url(nil).validate_percent(path_text)
    i = path_end
    if i < n and text[i] == "?"
      out["has_query"] = true
      i = i + 1
      query_end = i
      while query_end < n and text[query_end] != "#"
        query_end = query_end + 1
      query_text = ""
      k = i
      while k < query_end
        query_text = query_text + text[k]
        k = k + 1
      out["query"] = query_text
      Url(nil).validate_percent(query_text)
      i = query_end
    if i < n and text[i] == "#"
      i = i + 1
      frag_text = ""
      while i < n
        frag_text = frag_text + text[i]
        i = i + 1
      out["fragment"] = frag_text
      Url(nil).validate_percent(frag_text)
    out

query_dict

Url.query_dict(query)

lib/url.tya:472

Url.query_dict provides the url/Url standard library operation.

Source
  # Url.query_dict provides the url/Url standard library operation.
  # @param query Any query value.
  # @return Dict the resulting value.
  query_dict: query ->
    pairs = query
    if query.class == String
      pairs = Url(nil).decode_query(query)
    out = {}
    for pair in pairs
      k = pair[0]
      v = pair[1]
      if out.has(k)
        old = out[k]
        if old.class == Array
          old.push(v)
        else
          out[k] = [old, v]
      else
        out[k] = v
    out

resolve

Url.resolve(base, ref)

lib/url.tya:494

Url.resolve provides the url/Url standard library operation.

Source
  # Url.resolve provides the url/Url standard library operation.
  # @param base Any base value.
  # @param ref Any ref value.
  # @return Any the resulting value.
  resolve: base, ref ->
    b = Url(nil).parse(base)
    r = Url(nil).parse(ref)
    if r["scheme"] != ""
      return Url(nil).normalize(Url(nil).format(r))
    out =
      scheme: b["scheme"]
      user: ""
      password: ""
      host: ""
      port: ""
      path: ""
      query: ""
      fragment: r["fragment"]
    if r["has_authority"]
      out["user"] = r["user"]
      out["password"] = r["password"]
      out["host"] = r["host"]
      out["port"] = r["port"]
      out["path"] = Url(nil).normalize_path(r["path"])
      out["query"] = r["query"]
    else
      out["user"] = b["user"]
      out["password"] = b["password"]
      out["host"] = b["host"]
      out["port"] = b["port"]
      if r["path"] == ""
        out["path"] = b["path"]
        if r["has_query"]
          out["query"] = r["query"]
        else
          out["query"] = b["query"]
      elseif r["path"].starts_with("/")
        out["path"] = Url(nil).normalize_path(r["path"])
        out["query"] = r["query"]
      else
        out["path"] = Url(nil).normalize_path(
          Url(nil).merge_path(b["path"], r["path"])
        )
        out["query"] = r["query"]
    Url(nil).format(out)

validate_percent

Url.validate_percent(text)

lib/url.tya:539

Url.validate_percent provides the url/Url standard library operation.

Source
  # Url.validate_percent provides the url/Url standard library operation.
  # @param text String text value.
  # @return Boolean the resulting value.
  validate_percent: text ->
    n = text.byte_len()
    i = 0
    while i < n
      if text[i] == "%"
        if i + 2 >= n
          raise error("url.decode: truncated percent-escape")
        Url(nil).decode_hex(text[i + 1])
        Url(nil).decode_hex(text[i + 2])
        i = i + 3
      else
        i = i + 1
    nil