summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/parseurl.nim110
-rw-r--r--lib/pure/uri.nim37
-rw-r--r--lib/pure/url.nim213
3 files changed, 147 insertions, 213 deletions
diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim
new file mode 100644
index 000000000..357d1df0f
--- /dev/null
+++ b/lib/pure/parseurl.nim
@@ -0,0 +1,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)
+  
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
new file mode 100644
index 000000000..ee1226a35
--- /dev/null
+++ b/lib/pure/uri.nim
@@ -0,0 +1,37 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## **Note**: This module will be deprecated in the future and merged into a
+## new ``url`` module.
+
+import strutils
+type
+  TUrl* = distinct string
+
+proc `$`*(url: TUrl): string = return string(url)
+
+proc `/`*(a, b: TUrl): TUrl =
+  ## Joins two URLs together, separating them with / if needed.
+  var urlS = $a
+  var bS = $b
+  if urlS == "": return b
+  if urlS[urlS.len-1] != '/':
+    urlS.add('/')
+  if bS[0] == '/':
+    urlS.add(bS.substr(1))
+  else:
+    urlS.add(bs)
+  result = TUrl(urlS)
+
+proc add*(url: var TUrl, a: TUrl) =
+  ## Appends url to url.
+  url = url / a
+
+when isMainModule:
+  assert($("http://".TUrl / "localhost:5000".TUrl) == "http://localhost:5000")
diff --git a/lib/pure/url.nim b/lib/pure/url.nim
deleted file mode 100644
index fa7533886..000000000
--- a/lib/pure/url.nim
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-#
-#            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.
-
-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 skip(i: var int, skippedChars: string) = 
-  inc(i, skippedChars.len)
-
-proc readScheme(url: var TUrl, temp: string) =
-  url.scheme = temp
-
-proc readAuthority(url: var TUrl, temp: string) =
-  let colon = temp.find(':')
-  if colon >= 0:
-    url.password = temp.substr(colon+1)
-    url.username = temp.substr(0, colon-1)
-
-proc readHostAndPort(url: var TUrl, temp: string) =
-  let colon = temp.find(':')
-  if colon >= 0:
-    url.port = temp.substr(colon+1)
-    url.hostname = temp.substr(0, colon-1)
-
-proc readUntilPath(self: var TUrl, url: string): int =
-  var temp = ""
-  var i = 0
-  let relative = url[i] == '/'
-  if not relative:
-    while True:
-      if url[i] == ':':
-        if url[i+1] == '/' and url[i+2] == '/':
-          self.readScheme(temp)
-          i.skip("://")
-          temp.setlen(0)
-      if url[i] == '@':
-        self.readAuthority(temp)
-        i.skip("@")
-        temp.setlen(0)
-      
-      if url[i] == '/' or url[i] == '\0':
-        self.readHostAndPort(temp)
-        temp.setlen(0)
-        break
-      
-      temp.add(url[i])
-      inc(i)
-
-  if url[i] == '/': 
-    i.skip("/")
-  return i
-
-proc readPath(url: var TUrl, path: string) =
-  var temp = ""
-  var i = 0
-  while True:
-    if path[i] == '?':
-      url.path = temp
-      temp.setlen(0)
-    if path[i] == '#':
-      if temp[0] == '?':
-        url.query = temp
-      else:
-        url.path = temp
-      temp.setlen(0)
-      
-    if path[i] == '\0':
-      if temp[0] == '?':
-        url.query = temp
-      elif temp[0] == '#':
-        url.anchor = temp
-      else:
-        url.path = temp
-      break
-    temp.add(path[i])
-    inc(i)
-
-proc parseUrl*(url: string): TUrl =
-  result.scheme = ""
-  result.username = ""
-  result.password = ""
-  result.hostname = ""
-  result.port = ""
-  result.path = ""
-  result.query = ""
-  result.anchor = ""
-  
-  let lastIndex = result.readUntilPath(url)
-  let path = url[lastIndex..url.len]
-  result.readPath(path)
-    
-
-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)
-
-proc nvl(a: string, b: string): string =
-  if a == "":
-    return b
-  return a
-
-proc `/`*(a, b: TUrl): TUrl =
-  result.scheme = nvl(a.scheme, b.scheme)
-  result.username = nvl(a.username, b.username)
-  result.password = nvl(a.password, b.password)
-  result.hostname = nvl(a.hostname, b.hostname)
-  result.port = nvl(a.port, b.port)
-  result.path = nvl(a.path, b.path)
-  result.query = nvl(a.query, b.query)
-  result.anchor = nvl(a.anchor, b.anchor)
-  
-when isMainModule:
-  import unittest
-
-  test "parse full URL":
-    let url = parseUrl("http://localhost:5000/path?message1=Nimrod&message2=+is+cool!#anchor")
-    check url.username == ""
-    check url.password == ""
-    check url.scheme == "http"
-    check url.hostname == "localhost"
-    check url.port == "5000"
-    check url.path == "path"
-    check url.query == "?message1=Nimrod&message2=+is+cool!"
-    check url.anchor == "#anchor"
-
-  test "parse full URL with username and password":
-    let url = parseUrl("http://username:password@localhost:5000/path?message1=Nimrod&message2=+is+cool!#anchor")
-    check url.username == "username"
-    check url.password == "password"
-    check url.scheme == "http"
-    check url.hostname == "localhost"
-    check url.port == "5000"
-    check url.path == "path"
-    check url.query == "?message1=Nimrod&message2=+is+cool!"
-    check url.anchor == "#anchor"
-
-  test "parse URL fragment localhost:5000":
-    let url = parseUrl("localhost:5000")
-    check url.username == ""
-    check url.password == ""
-    check url.scheme == ""
-    check url.hostname == "localhost"
-    check url.port == "5000"
-    check url.path == ""
-    check url.query == ""
-    check url.anchor == ""
-
-  test "parse URL fragment: /path?message1=Nimrod&message2=+is+cool!#anchor":
-    let url = parseUrl("/path?message1=Nimrod&message2=+is+cool!#anchor")
-    check url.username == ""
-    check url.password == ""
-    check url.scheme == ""
-    check url.hostname == ""
-    check url.port == ""
-    check url.path == "path"
-    check url.query == "?message1=Nimrod&message2=+is+cool!"
-    check url.anchor == "#anchor"
-
-  test "parse URL fragment: http://":
-    let url = parseUrl("http://")
-    check url.scheme == "http"
-    check url.username == ""
-    check url.password == ""
-    check url.hostname == ""
-    check url.port == ""
-    check url.path == ""
-    check url.query == ""
-    check url.anchor == ""
-
-  test "url concatenation":
-    let url1 = parseUrl("http://localhost:5000")
-    let url2 = parseUrl("/path?message1=Nimrod&message2=+is+cool!#anchor")
-    let url = url1 / url2
-    check url.username == ""
-    check url.password == ""
-    check url.scheme == "http"
-    check url.hostname == "localhost"
-    check url.port == "5000"
-    check url.path == "path"
-    check url.query == "?message1=Nimrod&message2=+is+cool!"
-    check url.anchor == "#anchor"