summary refs log tree commit diff stats
path: root/lib/pure/parseurl.nim
blob: 357d1df0ff1c1e4f4d6ce2aa21a2cc2696bdab08 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#
#
#            Nimrod's Runtime Library
#        (c) Copyright 2014 Dominik Picheta
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## Parses & constructs URLs.
##
## **Note**: This module will be deprecated in the future and merged into a
## new ``url`` module.

import strutils

type
  TUrl* = tuple[      ## represents a *Uniform Resource Locator* (URL)
                      ## any optional component is "" if it does not exist
    scheme, username, password, 
    hostname, port, path, query, anchor: string]
    
proc parseUrl*(url: string): TUrl =
  var i = 0

  var scheme, username, password: string = ""
  var hostname, port, path, query, anchor: string = ""

  var temp = ""
  
  if url[i] != '/': # url isn't a relative path
    while True:
      # Scheme
      if url[i] == ':':
        if url[i+1] == '/' and url[i+2] == '/':
          scheme = temp
          temp.setlen(0)
          inc(i, 3) # Skip the //
      # Authority(username, password)
      if url[i] == '@':
        username = temp
        let colon = username.find(':')
        if colon >= 0:
          password = username.substr(colon+1)
          username = username.substr(0, colon-1)
        temp.setlen(0)
        inc(i) #Skip the @ 
      # hostname(subdomain, domain, port)
      if url[i] == '/' or url[i] == '\0':
        hostname = temp
        let colon = hostname.find(':')
        if colon >= 0:
          port = hostname.substr(colon+1)
          hostname = hostname.substr(0, colon-1)
        
        temp.setlen(0)
        break
      
      temp.add(url[i])
      inc(i)

  if url[i] == '/': inc(i) # Skip the '/'
  # Path
  while True:
    if url[i] == '?':
      path = temp
      temp.setlen(0)
    if url[i] == '#':
      if temp[0] == '?':
        query = temp
      else:
        path = temp
      temp.setlen(0)
      
    if url[i] == '\0':
      if temp[0] == '?':
        query = temp
      elif temp[0] == '#':
        anchor = temp
      else:
        path = temp
      break
      
    temp.add(url[i])
    inc(i)
    
  return (scheme, username, password, hostname, port, path, query, anchor)

proc `$`*(u: TUrl): string =
  ## turns the URL `u` into its string representation.
  result = ""
  if u.scheme.len > 0:
    result.add(u.scheme)
    result.add("://")
  if u.username.len > 0:
    result.add(u.username)
    if u.password.len > 0:
      result.add(":")
      result.add(u.password)
    result.add("@")
  result.add(u.hostname)
  if u.port.len > 0: 
    result.add(":")
    result.add(u.port)
  if u.path.len > 0: 
    result.add("/")
    result.add(u.path)
  result.add(u.query)
  result.add(u.anchor)
  
ass="n">assert typePos > 0 var typeStr = renderType(n[typePos]) if typeStr.len < 1 and n[typePos+1].kind != nkEmpty: # Try with the last node, maybe its a default value. let typ = n[typePos+1].typ if not typ.isNil: typeStr = typeToString(typ, preferExported) if typeStr.len < 1: return for i in 0 ..< typePos: found.add(typeStr) else: found.add($n) #internalError(n.info, "renderParamTypes(found,n) with " & $n.kind) proc renderParamTypes*(n: PNode, sep = defaultParamSeparator): string = ## Returns the types contained in `n` joined by `sep`. ## ## This proc expects to be passed as `n` the parameters of any callable. The ## string output is meant for the HTML renderer. If there are no parameters, ## the empty string is returned. The parameters will be joined by `sep` but ## other characters may appear too, like ``[]`` or ``|``. result = "" var found: seq[string] = @[] renderParamTypes(found, n) if found.len > 0: result = found.join(sep)