summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/impure/db_mysql.nim22
-rw-r--r--[-rwxr-xr-x]lib/pure/httpserver.nim (renamed from lib/devel/httpserver.nim)39
-rwxr-xr-xlib/pure/pegs.nim2
-rwxr-xr-xlib/pure/re.nim211
4 files changed, 192 insertions, 82 deletions
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
index ee37a88c3..9c427ae3b 100755
--- a/lib/impure/db_mysql.nim
+++ b/lib/impure/db_mysql.nim
@@ -50,22 +50,22 @@ proc dbQuote(s: string): string =
     else: add(result, c)
   add(result, '\'')
 
-proc dbFormat(formatstr: string, args: openarray[string]): string =
+proc dbFormat(formatstr: TSqlQuery, args: openarray[string]): string =
   result = ""
   var a = 0
-  for c in items(formatstr):
+  for c in items(string(formatstr)):
     if c == '?':
       add(result, dbQuote(args[a]))
       inc(a)
     else: 
       add(result, c)
   
-proc TryQuery*(db: TDbConn, query: string, args: openarray[string]): bool =
+proc TryQuery*(db: TDbConn, query: TSqlQuery, args: openarray[string]): bool =
   ## tries to execute the query and returns true if successful, false otherwise.
   var q = dbFormat(query, args)
   return mysqlRealQuery(db, q, q.len) == 0'i32
 
-proc Query*(db: TDbConn, query: string, args: openarray[string]) =
+proc Query*(db: TDbConn, query: TSqlQuery, args: openarray[string]) =
   ## executes the query and raises EDB if not successful.
   var q = dbFormat(query, args)
   if mysqlRealQuery(db, q, q.len) != 0'i32: dbError(db)
@@ -79,7 +79,7 @@ proc properFreeResult(sqlres: PMYSQL_RES, row: cstringArray) =
     while mysqlFetchRow(sqlres) != nil: nil
   mysqlFreeResult(sqlres)
   
-iterator FastRows*(db: TDbConn, query: string,
+iterator FastRows*(db: TDbConn, query: TSqlQuery,
                    args: openarray[string]): TRow =
   ## executes the query and iterates over the result dataset. This is very 
   ## fast, but potenially dangerous: If the for-loop-body executes another
@@ -99,7 +99,7 @@ iterator FastRows*(db: TDbConn, query: string,
       yield result
     properFreeResult(sqlres, row)
 
-proc GetAllRows*(db: TDbConn, query: string, 
+proc GetAllRows*(db: TDbConn, query: TSqlQuery, 
                  args: openarray[string]): seq[TRow] =
   ## executes the query and returns the whole result dataset.
   result = @[]
@@ -118,12 +118,12 @@ proc GetAllRows*(db: TDbConn, query: string,
       inc(j)
     mysqlFreeResult(sqlres)
 
-iterator Rows*(db: TDbConn, query: string, 
+iterator Rows*(db: TDbConn, query: TSqlQuery, 
                args: openarray[string]): TRow =
   ## same as `FastRows`, but slower and safe.
   for r in items(GetAllRows(db, query, args)): yield r
 
-proc GetValue*(db: TDbConn, query: string, 
+proc GetValue*(db: TDbConn, query: TSqlQuery, 
                args: openarray[string]): string = 
   ## executes the query and returns the result dataset's the first column 
   ## of the first row. Returns "" if the dataset contains no rows. This uses
@@ -133,7 +133,7 @@ proc GetValue*(db: TDbConn, query: string,
     result = row[0]
     break
 
-proc TryInsertID*(db: TDbConn, query: string, 
+proc TryInsertID*(db: TDbConn, query: TSqlQuery, 
                   args: openarray[string]): int64 =
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row or -1 in case of an error.
@@ -143,13 +143,13 @@ proc TryInsertID*(db: TDbConn, query: string,
   else:
     result = mysql_insert_id(db)
   
-proc InsertID*(db: TDbConn, query: string, args: openArray[string]): int64 = 
+proc InsertID*(db: TDbConn, query: TSqlQuery, args: openArray[string]): int64 = 
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row.
   result = TryInsertID(db, query, args)
   if result < 0: dbError(db)
 
-proc QueryAffectedRows*(db: TDbConn, query: string, 
+proc QueryAffectedRows*(db: TDbConn, query: TSqlQuery, 
                         args: openArray[string]): int64 = 
   ## runs the query (typically "UPDATE") and returns the
   ## number of affected rows
diff --git a/lib/devel/httpserver.nim b/lib/pure/httpserver.nim
index 61d95cc2e..2c85d8137 100755..100644
--- a/lib/devel/httpserver.nim
+++ b/lib/pure/httpserver.nim
@@ -8,6 +8,20 @@
 #
 
 ## This module implements a simple HTTP-Server. 
+##
+## Example: 
+##
+## .. code-block:: nimrod
+##  import strutils, sockets, httpserver
+##  
+##  var counter = 0
+##  proc handleRequest(client: TSocket, path, query: string): bool {.procvar.} =
+##    inc(counter)
+##    client.send("Hallo for the $#th time." % $counter & wwwNL)
+##    return false # do not stop processing
+##  
+##  run(handleRequest, TPort(80))
+##
 
 import strutils, os, osproc, strtabs, streams, sockets
 
@@ -180,15 +194,18 @@ type
     client*: TSocket      ## the socket to write the file data to
     path*, query*: string ## path and query the client requested
     
-proc open*(s: var TServer, port = TPort(0)) = 
+proc open*(s: var TServer, port = TPort(80)) = 
   ## creates a new server at port `port`. If ``port == 0`` a free port is
   ## aquired that can be accessed later by the ``port`` proc.
   s.socket = socket(AF_INET)
   if s.socket == InvalidSocket: OSError()
-  bindAddr(s.socket)
+  bindAddr(s.socket, port)
   listen(s.socket)
   
-  s.port = getSockName(s.socket)
+  if port == TPort(0):
+    s.port = getSockName(s.socket)
+  else:
+    s.port = port
   s.client = InvalidSocket
   s.path = ""
   s.query = ""
@@ -220,7 +237,7 @@ proc close*(s: TServer) =
   close(s.socket)
 
 proc run*(handleRequest: proc (client: TSocket, path, query: string): bool, 
-          port = TPort(0)) =
+          port = TPort(80)) =
   ## encapsulates the server object and main loop
   var s: TServer
   open(s, port)
@@ -231,18 +248,6 @@ proc run*(handleRequest: proc (client: TSocket, path, query: string): bool,
     close(s.client)
   close(s)
 
-when false:
-  proc main =  
-    var (server, port) = startup()
-    echo("httpserver running on port ", int16(port))
-    
-    while true:
-      var client = accept(server)
-      if client == InvalidSocket: OSError()
-      acceptRequest(client)
-      close(client)
-    close(server)
-
 when isMainModule:
   var counter = 0
   proc handleRequest(client: TSocket, path, query: string): bool {.procvar.} =
@@ -250,5 +255,5 @@ when isMainModule:
     client.send("Hallo, Andreas for the $#th time." % $counter & wwwNL)
     return false # do not stop processing
   
-  run(handleRequest)
+  run(handleRequest, TPort(80))
 
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 488e42c7d..5ba0351ad 100755
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/pure/re.nim b/lib/pure/re.nim
index cef7c85ac..fbe4179ce 100755
--- a/lib/pure/re.nim
+++ b/lib/pure/re.nim
@@ -9,27 +9,170 @@
 
 ## Regular expression support for Nimrod. Consider using the pegs module
 ## instead.
+## Currently this module is implemented by providing a wrapper around the
+## `PRCE (Perl-Compatible Regular Expressions) <http://www.pcre.org>`_
+## C library. This means that your application will depend on the PRCE
+## library's licence when using this module, which should not be a problem
+## though.
+## PRCE's licence follows:
+##
+## .. include:: ../doc/regexprs.txt
+##
+
+import
+  pcre, strutils
 
-{.compile: "tre/tre_all.c".}
-
-from strutils import addf
+const
+  MaxSubpatterns* = 10
+    ## defines the maximum number of subpatterns that can be captured.
+    ## More subpatterns cannot be captured!
 
 type
-  TRegExDesc {.pure, final.} = object
-    re_nsub: int    # Number of parenthesized subexpressions.
-    value: pointer  # For internal use only.
-  
-  TRegEx* = ref TRegExDesc ## a compiled regular expression  
+  TRegExOptions* = enum  ## options for regular expressions
+    reIgnoreCase = 0,    ## do caseless matching
+    reMultiLine = 1,     ## ``^`` and ``$`` match newlines within data 
+    reDotAll = 2,        ## ``.`` matches anything including NL
+    reExtended = 3,      ## ignore whitespace and ``#`` comments
+    
+    
+    PCRE_ANCHORED* = 0x00000010
+    PCRE_DOLLAR_ENDONLY* = 0x00000020
+    PCRE_EXTRA* = 0x00000040
+    PCRE_NOTBOL* = 0x00000080
+    PCRE_NOTEOL* = 0x00000100
+    PCRE_UNGREEDY* = 0x00000200
+    PCRE_NOTEMPTY* = 0x00000400
+    PCRE_UTF8* = 0x00000800
+    PCRE_NO_AUTO_CAPTURE* = 0x00001000
+    
+    
+  TRegExDesc {.pure, final.}  = object 
+    h: PPcre
+    
+  TRegEx* = ref TRegExDesc ## a compiled regular expression
+    
   EInvalidRegEx* = object of EInvalidValue
     ## is raised if the pattern is no valid regular expression.
-    
-  TRegMatch {.pure.} = object
-    so, eo: cint
 
-const
-  MaxSubpatterns* = 10
-    ## defines the maximum number of subpatterns that can be captured.
-    ## More subpatterns cannot be captured!
+proc rawCompile(pattern: string, flags: cint): PPcre =
+  var
+    msg: CString
+    offset: int
+    com = pcreCompile(pattern, flags, addr(msg), addr(offset), nil)
+  if com == nil:
+    var e: ref EInvalidRegEx
+    new(e)
+    e.msg = $msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n"
+    raise e
+  return com
+
+proc finalizeRegEx(x: TRegEx) = dealloc(x.h)
+
+proc re*(s: string): TRegEx =
+  ## Constructor of regular expressions. Note that Nimrod's
+  ## extended raw string literals supports this syntax ``re"[abc]"`` as
+  ## a short form for ``re(r"[abc]")``.
+  new(result, finalizeRegEx)
+  result.h = rawCompile(s, 
+  
+  var err = int(regncomp(addr(result^), s, s.len,
+                cint(REG_EXTENDED or REG_NEWLINE)))
+  if err != 0:
+    var e: ref EInvalidRegEx
+    new(e)
+    e.msg = ErrorMessages[err]
+    raise e
+
+proc xre*(pattern: string): TRegEx = 
+  ## deletes whitespace from a pattern that is not escaped or in a character
+  ## class. Then it constructs a regular expresion object via `re`.
+  ## This is modelled after Perl's ``/x`` modifier. 
+  var p = ""
+  var i = 0
+  while i < pattern.len: 
+    case pattern[i]
+    of ' ', '\t': 
+      inc i
+    of '\\': 
+      add p, '\\'
+      add p, pattern[i+1]
+      inc i, 2
+    of '[': 
+      while pattern[i] != ']' and pattern[i] != '\0': 
+        add p, pattern[i]
+        inc i
+    else: 
+      add p, pattern[i]
+      inc i
+  result = re(p)
+
+proc matchOrFind(s: string, pattern: PPcre, matches: var openarray[string],
+                 start: cint): cint =
+  var
+    rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
+    res = int(pcreExec(pattern, nil, s, len(s), start, 0,
+      cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3))
+  dealloc(pattern)
+  if res < 0: return res
+  for i in 0..res-1:
+    var
+      a = rawMatches[i * 2]
+      b = rawMatches[i * 2 + 1]
+    if a >= 0'i32: matches[i] = copy(s, a, int(b)-1)
+    else: matches[i] = ""
+  return res
+
+proc matchOrFind(s: string, pattern: PPcre, start: cint): cint =
+  var
+    rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
+    res = pcreExec(pattern, nil, s, len(s), start, 0,
+                   cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
+  dealloc(pattern)
+  return res
+
+proc match(s, pattern: string, matches: var openarray[string],
+           start: int = 0): bool =
+  return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED),
+                     matches, start) >= 0'i32
+
+proc matchLen(s, pattern: string, matches: var openarray[string],
+              start: int = 0): int =
+  return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED), matches, start)
+
+proc find(s, pattern: string, matches: var openarray[string],
+          start: int = 0): bool =
+  return matchOrFind(s, rawCompile(pattern, PCRE_MULTILINE),
+                     matches, start) >= 0'i32
+
+proc match(s, pattern: string, start: int = 0): bool =
+  return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED), start) >= 0'i32
+
+proc find(s, pattern: string, start: int = 0): bool =
+  return matchOrFind(s, rawCompile(pattern, PCRE_MULTILINE), start) >= 0'i32
+
+template `=~` *(s, pattern: expr): expr = 
+  ## This calls ``match`` with an implicit declared ``matches`` array that 
+  ## can be used in the scope of the ``=~`` call: 
+  ## 
+  ## .. code-block:: nimrod
+  ##
+  ##   if line =~ r"\s*(\w+)\s*\=\s*(\w+)": 
+  ##     # matches a key=value pair:
+  ##     echo("Key: ", matches[1])
+  ##     echo("Value: ", matches[2])
+  ##   elif line =~ r"\s*(\#.*)":
+  ##     # matches a comment
+  ##     # note that the implicit ``matches`` array is different from the
+  ##     # ``matches`` array of the first branch
+  ##     echo("comment: ", matches[1])
+  ##   else:
+  ##     echo("syntax error")
+  ##
+  when not definedInScope(matches):
+    var matches: array[0..maxSubPatterns-1, string]
+  match(s, pattern, matches)
+
+
 
 proc regnexec(preg: ptr TRegExDesc, s: cstring, len, nmatch: int,
               pmatch: ptr array [0..maxSubpatterns-1, TRegMatch],
@@ -75,44 +218,6 @@ const
     "Invalid use of repetition operators"
   ]
 
-proc finalizeRegEx(x: TRegEx) = regfree(addr(x^))
-
-proc re*(s: string): TRegEx =
-  ## Constructor of regular expressions. Note that Nimrod's
-  ## extended raw string literals supports this syntax ``re"[abc]"`` as
-  ## a short form for ``re(r"[abc]")``.
-  new(result, finalizeRegEx)
-  var err = int(regncomp(addr(result^), s, s.len,
-                cint(REG_EXTENDED or REG_NEWLINE)))
-  if err != 0:
-    var e: ref EInvalidRegEx
-    new(e)
-    e.msg = ErrorMessages[err]
-    raise e
-
-proc xre*(pattern: string): TRegEx = 
-  ## deletes whitespace from a pattern that is not escaped or in a character
-  ## class. Then it constructs a regular expresion object via `re`.
-  ## This is modelled after Perl's ``/x`` modifier. 
-  var p = ""
-  var i = 0
-  while i < pattern.len: 
-    case pattern[i]
-    of ' ', '\t': 
-      inc i
-    of '\\': 
-      add p, '\\'
-      add p, pattern[i+1]
-      inc i, 2
-    of '[': 
-      while pattern[i] != ']' and pattern[i] != '\0': 
-        add p, pattern[i]
-        inc i
-    else: 
-      add p, pattern[i]
-      inc i
-  result = re(p)
-
 proc rawmatch(s: string, pattern: TRegEx, matches: var openarray[string],
               start: int): tuple[first, last: int] =
   var