]> git.saurik.com Git - redis.git/blob - client-libraries/tcl/redis.tcl
6cc713d2fbc4aea898ea6171af7d55cd51b06371
[redis.git] / client-libraries / tcl / redis.tcl
1 # Tcl clinet library - used by test-redis.tcl script for now
2 # Copyright (C) 2009 Salvatore Sanfilippo
3 # Released under the BSD license like Redis itself
4 #
5 # Example usage:
6 #
7 # set r [redis 127.0.0.1 6379]
8 # $r lpush mylist foo
9 # $r lpush mylist bar
10 # $r lrange mylist 0 -1
11 # $r close
12
13 package provide redis 0.1
14
15 namespace eval redis {}
16 set ::redis::id 0
17 array set ::redis::fd {}
18 array set ::redis::bulkarg {}
19
20 # Flag commands requiring last argument as a bulk write operation
21 foreach redis_bulk_cmd {
22 set setnx rpush lpush lset lrem sadd srem sismember echo
23 } {
24 set ::redis::bulkarg($redis_bulk_cmd) {}
25 }
26 unset redis_bulk_cmd
27
28 proc redis {{server 127.0.0.1} {port 6379}} {
29 set fd [socket $server $port]
30 fconfigure $fd -translation binary
31 set id [incr ::redis::id]
32 set ::redis::fd($id) $fd
33 interp alias {} ::redis::redisHandle$id {} ::redis::__dispatch__ $id
34 }
35
36 proc ::redis::__dispatch__ {id method args} {
37 set fd $::redis::fd($id)
38 if {[info command ::redis::__method__$method] eq {}} {
39 set cmd "$method "
40 if {[info exists ::redis::bulkarg($method)]} {
41 append cmd [join [lrange $args 0 end-1]]
42 append cmd " [string length [lindex $args end]]\r\n"
43 append cmd [lindex $args end]
44 } else {
45 append cmd [join $args]
46 }
47 ::redis::redis_writenl $fd $cmd
48 ::redis::redis_read_reply $fd
49 } else {
50 uplevel 1 [list ::redis::__method__$method $id $fd] $args
51 }
52 }
53
54 proc ::redis::__method__close {id fd} {
55 catch {close $fd}
56 catch {unset ::redis::fd($id)}
57 catch {interp alias {} ::redis::redisHandle$id {}}
58 }
59
60 proc ::redis::__method__channel {id fd} {
61 return $fd
62 }
63
64 proc ::redis::redis_write {fd buf} {
65 puts -nonewline $fd $buf
66 }
67
68 proc ::redis::redis_writenl {fd buf} {
69 redis_write $fd $buf
70 redis_write $fd "\r\n"
71 flush $fd
72 }
73
74 proc ::redis::redis_readnl {fd len} {
75 set buf [read $fd $len]
76 read $fd 2 ; # discard CR LF
77 return $buf
78 }
79
80 proc ::redis::redis_bulk_read {fd} {
81 set count [redis_read_line $fd]
82 if {$count == -1} return {}
83 set buf [redis_readnl $fd $count]
84 return $buf
85 }
86
87 proc ::redis::redis_multi_bulk_read fd {
88 set count [redis_read_line $fd]
89 if {$count == -1} return {}
90 set l {}
91 for {set i 0} {$i < $count} {incr i} {
92 lappend l [redis_read_reply $fd]
93 }
94 return $l
95 }
96
97 proc ::redis::redis_read_line fd {
98 string trim [gets $fd]
99 }
100
101 proc ::redis::redis_read_reply fd {
102 set type [read $fd 1]
103 switch -exact -- $type {
104 : -
105 + {redis_read_line $fd}
106 - {return -code error [redis_read_line $fd]}
107 $ {redis_bulk_read $fd}
108 * {redis_multi_bulk_read $fd}
109 default {return -code error "Bad protocl, $type as reply type byte"}
110 }
111 }