monotone

monotone Mtn Source Tree

Root/vocab.cc

1// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include <string>
11#include <iostream>
12
13#include "constants.hh"
14#include "hash_map.hh"
15#include "sanity.hh"
16#include "vocab.hh"
17
18using std::string;
19
20// verifiers for various types of data
21
22// the verify() stuff gets a little complicated; there doesn't seem to be a
23// really nice way to achieve what we want with c++'s type system. the
24// problem is this: we want to give verify(file_path) and verify(local_path)
25// access to the internals of file_path and local_path, i.e. make them
26// friends, so they can normalize the file paths they're given. this means
27// that verify() needs to be declared publically, so that the definition of
28// these classes can refer to them. it also means that they -- and all other
29// ATOMIC types -- cannot fall back on a templated version of verify if no
30// other version is defined, because, well, the friend thing and the template
31// thing just don't work out, as far as I can tell. So, every ATOMIC type
32// needs an explicitly defined verify() function, so we have both ATOMIC() and
33// ATOMIC_NOVERIFY() macros, the latter of which defines a type-specific noop
34// verify function. DECORATE and ENCODING, on the other hand, cannot make use
35// of a trick like these, because they are template types themselves, and we
36// want to be able to define verify(hexenc<id>) without defining
37// verify(hexenc<data>) at the same time, for instance. Fortunately, these
38// types never need to be friends with their verify functions (yet...), so we
39// _can_ use a templated fallback function. This templated function is used
40// _only_ by DECORATE and ENCODING; it would be nice to make it take an
41// argument of type T1<T2> to document that, but for some reason that doesn't
42// work either.
43template <typename T>
44static inline void
45verify(T & val)
46{ }
47
48template <typename T>
49static inline void
50verify_full(T & val)
51{ val.ok = true; }
52
53inline void
54verify_full(path_component & val)
55{
56 // FIXME: probably ought to do something here?
57 val.ok = true;
58}
59
60inline void
61verify_full(hexenc<id> & val)
62{
63 if (val().empty())
64 return;
65
66 N(val().size() == constants::idlen,
67 F("hex encoded ID '%s' size != %d") % val % constants::idlen);
68 for (string::const_iterator i = val().begin(); i != val().end(); ++i)
69 {
70 N(is_xdigit(*i),
71F("bad character '%c' in id name '%s'") % *i % val);
72 }
73 val.ok = true;
74}
75
76inline void
77verify_full(ace & val)
78{
79 string::size_type pos = val().find_first_not_of(constants::legal_ace_bytes);
80 N(pos == string::npos,
81 F("bad character '%c' in ace string '%s'") % val().at(pos) % val);
82
83 val.ok = true;
84}
85
86inline void
87verify_full(symbol & val)
88{
89 for (string::const_iterator i = val().begin(); i != val().end(); ++i)
90 {
91 N(is_alnum(*i) || *i == '_',
92F("bad character '%c' in symbol '%s'") % *i % val);
93 }
94
95 val.ok = true;
96}
97
98inline void
99verify_full(cert_name & val)
100{
101 string::size_type pos = val().find_first_not_of(constants::legal_cert_name_bytes);
102 N(pos == string::npos,
103 F("bad character '%c' in cert name '%s'") % val().at(pos) % val);
104
105 val.ok = true;
106}
107
108inline void
109verify_full(rsa_keypair_id & val)
110{
111 string::size_type pos = val().find_first_not_of(constants::legal_key_name_bytes);
112 N(pos == string::npos,
113 F("bad character '%c' in key name '%s'") % val().at(pos) % val);
114
115 val.ok = true;
116}
117
118inline void
119verify_full(netsync_session_key & val)
120{
121 if (val().size() == 0)
122 {
123 val.s.append(constants::netsync_session_key_length_in_bytes, 0);
124 return;
125 }
126
127 N(val().size() == constants::netsync_session_key_length_in_bytes,
128 F("Invalid key length of %d bytes") % val().length());
129
130 val.ok = true;
131}
132
133inline void
134verify_full(netsync_hmac_value & val)
135{
136 if (val().size() == 0)
137 {
138 val.s.append(constants::netsync_hmac_value_length_in_bytes, 0);
139 return;
140 }
141
142 N(val().size() == constants::netsync_hmac_value_length_in_bytes,
143 F("Invalid hmac length of %d bytes") % val().length());
144
145 val.ok = true;
146}
147
148
149// Note that ATOMIC types each keep a static symbol-table object and a
150// counter of activations, and when there is an activation, the
151// members of the ATOMIC type initialize their internal string using a
152// copy of the string found in the symtab. Since some (all?) C++
153// string implementations are copy-on-write, this has the affect
154// of making the ATOMIC(foo) values constructed within a symbol table
155// scope share string storage.
156struct
157symtab_impl
158{
159 typedef hashmap::hash_set<string> hset;
160 hset vals;
161 symtab_impl() : vals() {}
162 void clear() { vals.clear(); }
163 string const & unique(string const & in)
164 {
165 // This produces a pair <iter,bool> where iter points to an
166 // element of the table; the bool indicates whether the element is
167 // new, but we don't actually care. We just want the iter.
168 return *(vals.insert(in).first);
169 }
170};
171
172
173// instantiation of various vocab functions
174
175
176
177#include "vocab_macros.hh"
178#define ENCODING(enc) cc_ENCODING(enc)
179#define DECORATE(dec) cc_DECORATE(dec)
180#define ATOMIC(ty) cc_ATOMIC(ty)
181#define ATOMIC_NOVERIFY(ty) cc_ATOMIC_NOVERIFY(ty)
182
183#ifdef EXTERN
184#undef EXTERN
185#endif
186#define EXTERN
187
188#include "vocab_terms.hh"
189
190#undef EXTERN
191#undef ATOMIC
192#undef DECORATE
193
194
195template
196void dump<rsa_pub_key>(base64<rsa_pub_key> const&, string &);
197
198template
199void dump(revision_id const & r, string &);
200
201template
202void dump(roster_id const & r, string &);
203
204template
205void dump(manifest_id const & r, string &);
206
207template
208void dump(file_id const & r, string &);
209
210template
211void dump(hexenc<id> const & r, string &);
212
213template
214void dump(roster_data const & d, string &);
215
216// the rest is unit tests
217
218#ifdef BUILD_UNIT_TESTS
219#include "unit_tests.hh"
220
221void add_vocab_tests(test_suite * suite)
222{
223 I(suite);
224 // None, ATM.
225}
226
227#endif // BUILD_UNIT_TESTS
228
229// Local Variables:
230// mode: C++
231// fill-column: 76
232// c-file-style: "gnu"
233// indent-tabs-mode: nil
234// End:
235// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status