~ubuntu-branches/ubuntu/vivid/juju-core/vivid-updates

« back to all changes in this revision

Viewing changes to src/golang.org/x/net/dict/dict.go

  • Committer: Package Import Robot
  • Author(s): Curtis C. Hovey
  • Date: 2015-09-29 19:43:29 UTC
  • mfrom: (47.1.4 wily-proposed)
  • Revision ID: package-import@ubuntu.com-20150929194329-9y496tbic30hc7vp
Tags: 1.24.6-0ubuntu1~15.04.1
Backport of 1.24.6 from wily. (LP: #1500916, #1497087)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2010 The Go Authors.  All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
// Package dict implements the Dictionary Server Protocol
 
6
// as defined in RFC 2229.
 
7
package dict // import "golang.org/x/net/dict"
 
8
 
 
9
import (
 
10
        "net/textproto"
 
11
        "strconv"
 
12
        "strings"
 
13
)
 
14
 
 
15
// A Client represents a client connection to a dictionary server.
 
16
type Client struct {
 
17
        text *textproto.Conn
 
18
}
 
19
 
 
20
// Dial returns a new client connected to a dictionary server at
 
21
// addr on the given network.
 
22
func Dial(network, addr string) (*Client, error) {
 
23
        text, err := textproto.Dial(network, addr)
 
24
        if err != nil {
 
25
                return nil, err
 
26
        }
 
27
        _, _, err = text.ReadCodeLine(220)
 
28
        if err != nil {
 
29
                text.Close()
 
30
                return nil, err
 
31
        }
 
32
        return &Client{text: text}, nil
 
33
}
 
34
 
 
35
// Close closes the connection to the dictionary server.
 
36
func (c *Client) Close() error {
 
37
        return c.text.Close()
 
38
}
 
39
 
 
40
// A Dict represents a dictionary available on the server.
 
41
type Dict struct {
 
42
        Name string // short name of dictionary
 
43
        Desc string // long description
 
44
}
 
45
 
 
46
// Dicts returns a list of the dictionaries available on the server.
 
47
func (c *Client) Dicts() ([]Dict, error) {
 
48
        id, err := c.text.Cmd("SHOW DB")
 
49
        if err != nil {
 
50
                return nil, err
 
51
        }
 
52
 
 
53
        c.text.StartResponse(id)
 
54
        defer c.text.EndResponse(id)
 
55
 
 
56
        _, _, err = c.text.ReadCodeLine(110)
 
57
        if err != nil {
 
58
                return nil, err
 
59
        }
 
60
        lines, err := c.text.ReadDotLines()
 
61
        if err != nil {
 
62
                return nil, err
 
63
        }
 
64
        _, _, err = c.text.ReadCodeLine(250)
 
65
 
 
66
        dicts := make([]Dict, len(lines))
 
67
        for i := range dicts {
 
68
                d := &dicts[i]
 
69
                a, _ := fields(lines[i])
 
70
                if len(a) < 2 {
 
71
                        return nil, textproto.ProtocolError("invalid dictionary: " + lines[i])
 
72
                }
 
73
                d.Name = a[0]
 
74
                d.Desc = a[1]
 
75
        }
 
76
        return dicts, err
 
77
}
 
78
 
 
79
// A Defn represents a definition.
 
80
type Defn struct {
 
81
        Dict Dict   // Dict where definition was found
 
82
        Word string // Word being defined
 
83
        Text []byte // Definition text, typically multiple lines
 
84
}
 
85
 
 
86
// Define requests the definition of the given word.
 
87
// The argument dict names the dictionary to use,
 
88
// the Name field of a Dict returned by Dicts.
 
89
//
 
90
// The special dictionary name "*" means to look in all the
 
91
// server's dictionaries.
 
92
// The special dictionary name "!" means to look in all the
 
93
// server's dictionaries in turn, stopping after finding the word
 
94
// in one of them.
 
95
func (c *Client) Define(dict, word string) ([]*Defn, error) {
 
96
        id, err := c.text.Cmd("DEFINE %s %q", dict, word)
 
97
        if err != nil {
 
98
                return nil, err
 
99
        }
 
100
 
 
101
        c.text.StartResponse(id)
 
102
        defer c.text.EndResponse(id)
 
103
 
 
104
        _, line, err := c.text.ReadCodeLine(150)
 
105
        if err != nil {
 
106
                return nil, err
 
107
        }
 
108
        a, _ := fields(line)
 
109
        if len(a) < 1 {
 
110
                return nil, textproto.ProtocolError("malformed response: " + line)
 
111
        }
 
112
        n, err := strconv.Atoi(a[0])
 
113
        if err != nil {
 
114
                return nil, textproto.ProtocolError("invalid definition count: " + a[0])
 
115
        }
 
116
        def := make([]*Defn, n)
 
117
        for i := 0; i < n; i++ {
 
118
                _, line, err = c.text.ReadCodeLine(151)
 
119
                if err != nil {
 
120
                        return nil, err
 
121
                }
 
122
                a, _ := fields(line)
 
123
                if len(a) < 3 {
 
124
                        // skip it, to keep protocol in sync
 
125
                        i--
 
126
                        n--
 
127
                        def = def[0:n]
 
128
                        continue
 
129
                }
 
130
                d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}}
 
131
                d.Text, err = c.text.ReadDotBytes()
 
132
                if err != nil {
 
133
                        return nil, err
 
134
                }
 
135
                def[i] = d
 
136
        }
 
137
        _, _, err = c.text.ReadCodeLine(250)
 
138
        return def, err
 
139
}
 
140
 
 
141
// Fields returns the fields in s.
 
142
// Fields are space separated unquoted words
 
143
// or quoted with single or double quote.
 
144
func fields(s string) ([]string, error) {
 
145
        var v []string
 
146
        i := 0
 
147
        for {
 
148
                for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
 
149
                        i++
 
150
                }
 
151
                if i >= len(s) {
 
152
                        break
 
153
                }
 
154
                if s[i] == '"' || s[i] == '\'' {
 
155
                        q := s[i]
 
156
                        // quoted string
 
157
                        var j int
 
158
                        for j = i + 1; ; j++ {
 
159
                                if j >= len(s) {
 
160
                                        return nil, textproto.ProtocolError("malformed quoted string")
 
161
                                }
 
162
                                if s[j] == '\\' {
 
163
                                        j++
 
164
                                        continue
 
165
                                }
 
166
                                if s[j] == q {
 
167
                                        j++
 
168
                                        break
 
169
                                }
 
170
                        }
 
171
                        v = append(v, unquote(s[i+1:j-1]))
 
172
                        i = j
 
173
                } else {
 
174
                        // atom
 
175
                        var j int
 
176
                        for j = i; j < len(s); j++ {
 
177
                                if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' {
 
178
                                        break
 
179
                                }
 
180
                        }
 
181
                        v = append(v, s[i:j])
 
182
                        i = j
 
183
                }
 
184
                if i < len(s) {
 
185
                        c := s[i]
 
186
                        if c != ' ' && c != '\t' {
 
187
                                return nil, textproto.ProtocolError("quotes not on word boundaries")
 
188
                        }
 
189
                }
 
190
        }
 
191
        return v, nil
 
192
}
 
193
 
 
194
func unquote(s string) string {
 
195
        if strings.Index(s, "\\") < 0 {
 
196
                return s
 
197
        }
 
198
        b := []byte(s)
 
199
        w := 0
 
200
        for r := 0; r < len(b); r++ {
 
201
                c := b[r]
 
202
                if c == '\\' {
 
203
                        r++
 
204
                        c = b[r]
 
205
                }
 
206
                b[w] = c
 
207
                w++
 
208
        }
 
209
        return string(b[0:w])
 
210
}