dsrc isn't necessary for this repo
[client-tools.git] / src / external / 3rd / library / perforce / include / spec.h
blobf1d221aa8efcb4b67a7ddc3e8eec3522d59dd4c2
1 /*
2 * Copyright 1995, 2003 Perforce Software. All rights reserved.
3 */
5 /*
6 * Spec.h - spec manipulation
8 * Description:
10 * A 'spec' is one of those dumb ascii forms that user edits
11 * to specify various information -- clients, labels, etc.
13 * The Spec class is a spec definition, indicating what fields
14 * there are and their format. For formatting and parsing,
15 * Spec::Format() and Spec::Parse() expect a subclassed
16 * SpecData object, with SpecData::Get() and SpecData::Put()
17 * defined for moving data between the actual object and the spec.
19 * The Spec object contains SpecElems to describe each element
20 * of a spec.
22 * A Spec can be encoded into a simple string for passing between
23 * processes. Spec::Encode() and Spec::Decode() do this. They
24 * are built for interoperability. Namely, Decode() ignores fields
25 * it doesn't understand.
27 * Finally, a Spec is also be represented as a 'jobspec': this is
28 * actually a form (formatted by Spec) that describes another Spec
29 * (in jobspec's case, a job's Spec). The SpecData that does this
30 * is part of the jobspec code, but that uses Spec::Add(), Get()
31 * and SpecElem::Fmt*() and Set*() for low level construction/
32 * examination of the spec.
34 * Spec definition strings:
36 * A Spec is described by a definition string, parsed by
37 * Spec::Encode() and regenerated (if needed) by Spec::Decode().
38 * Each item on the form is describe by a substring separated by
39 * other items by ";;". That substring contains a number of codes
40 * separated by ";". Each code is one of the following:
42 * type:X field type
44 * type:word single line with N words each
45 * type:wlist list of lines with N words each
46 * type:select single line with a word selected from a list
47 * type:line single line of arbitrary data
48 * type:llist list of lines of arbitrary data
49 * type:date single line with a date on it
50 * type:text block of text spanning any number of lines
51 * type:bulk text that doesn't get indexed (for jobs)
53 * opt:X how optional the field is
55 * opt:optional not required
56 * opt:default required, and has a default
57 * opt:required required, but no default
58 * opt:once read-only; set automatically before user gets it
59 * opt:always read-only; field set automatically after user
61 * code:X a unique numeric code identifying the field
62 * len:X advisory length for displaying field
63 * pre=X preset value for opt:once, opt:always
64 * ro old name for opt:always
65 * rq old name for opt:required
66 * seq:X advisory sequence for display field
67 * val:X /-separated list of values for type:select
68 * words:X the number of words for a word/wlist field
70 * fmt:X advisory format for displaying field
72 * fmt:none normal (full width)
73 * fmt:L left half only
74 * fmt:R right half only; if follows L goes on same line
75 * fmt:I indented
77 * Class Defined:
79 * Spec - the definition of a spec, for parsing and formatting
80 * SpecElem - the definition of a single item type in a spec
81 * SpecData - a spec-specific formatter/parser helper
82 * SpecWords -- array of words in a spec value, allowing surrounding "'s
83 * SpecDataTable -- a SpecData interface to a StrDict
85 * Virtual methods, to be defined by caller:
87 * SpecData::Get() - get a data value for stuffing into a spec
88 * SpecData::Set() - set a data value parsed from a spec
90 * Public methods:
92 * Spec::Add() -- add a single SpecElem manually, with default values
93 * Spec::Decode() -- decode a spec definition from a string
94 * Spec::Encode() -- encode a spec definition in a transmittable string
95 * Spec::Find() -- find a SpecElem in the spec
96 * Spec::Get() -- find n'th SpecElem in the spec
97 * Spec::GetComment() -- return the spec's comment string
98 * Spec::Format() -- turn SpecData into a spec string
99 * Spec::Parse() -- parse a spec string into SpecData
100 * Spec::ParseNoValid() -- parse without validating 'select' items
101 * Spec::SetComment() -- set the spec's comment string
103 * SpecElem::FmtOpt() - format the SpecOpt for jobspec
104 * SpecElem::FmtType() - format the SpecType for jobspec
105 * SpecElem::FmtFmt() - format the SpecFmt for jobspec
106 * SpecElem::Is*() - ask various questions about the SpecType
107 * SpecElem::SetOpt() - parse the SpecOpt from a jobspec
108 * SpecElem::SetType() - format the SpecOpt for a jobspec
109 * SpecElem::Compare() - compare SpecElems from different specs
112 #ifndef _spec_h_
113 #define _spec_h_
115 class VarArray;
116 class SpecData;
117 class SpecElem;
118 class StrBufDict;
120 const int SpecWordsMax = 10; // for SDT_WORD, WLIST, SELECT
122 enum SpecType {
123 SDT_WORD, // single line, N words
124 SDT_WLIST, // multiple lines, N words
125 SDT_SELECT, // SDT_WORD from a list of words
126 SDT_LINE, // single line of text (arbitrary words)
127 SDT_LLIST, // multiple lines of text (arbitrary words)
128 SDT_DATE, // SDT_LINE that is a date
129 SDT_TEXT, // block of text,
130 SDT_BULK // SDT_TEXT not indexed
133 enum SpecOpt {
134 SDO_OPTIONAL, // not required, user updatable, no default
135 SDO_DEFAULT, // not required, user updatable, default provided
136 SDO_REQUIRED, // required, user updatable, default provided
137 SDO_ONCE, // required, not updatable, set once after creation
138 SDO_ALWAYS, // required, not updatable, set after every update
139 SDO_KEY // required, not updatable, set once before creation
142 enum SpecFmt {
143 SDF_NORMAL, // no hint given
144 SDF_LEFT, // left half only
145 SDF_RIGHT, // right half only; if follows LEFT goes on same line
146 SDF_INDENT // indented
149 class Spec {
151 public:
152 Spec();
153 Spec( const char *encoded, const char *cmt );
154 ~Spec();
156 // Using the Spec -- formatting and parsing forms
158 StrBuf * Format( SpecData *data )
159 { StrBuf *s = new StrBuf; Format( data, s ); return s; }
161 void Format( SpecData *data, StrBuf *result );
162 void Format( SpecData *data, StrDict *result );
164 void Parse( const char *buf, SpecData *data, Error *e, int valid );
166 void Parse( const char *buf, SpecData *data, Error *e )
167 { Parse( buf, data, e, 1 ); }
168 void ParseNoValid( const char *buf, SpecData *data, Error *e )
169 { Parse( buf, data, e, 0 ); }
171 // Manipulating the Spec itself -- building and examining it
173 SpecElem * Add( const StrPtr &tag );
174 SpecElem * Get( int i );
175 SpecElem * Find( const StrPtr &tag, Error *e = 0 );
176 SpecElem * Find( int code, Error *e = 0 );
177 int Count();
179 void Decode( StrPtr *encoded, Error *e );
180 void Encode( StrBuf *encoded );
182 const StrPtr * GetComment() { return &comment; }
183 void SetComment( const StrPtr &c ) { comment = c; }
185 SpecElem * Add( char *t ) { return Add( StrRef( t ) ); }
187 private:
189 StrRef comment;
190 VarArray *elems;
191 StrBuf decoderBuffer;
194 class SpecElem {
196 public:
198 // Type access
200 int IsDate() { return type == SDT_DATE; }
201 int IsSelect() { return type == SDT_SELECT; }
202 int IsText() { return type == SDT_TEXT
203 || type == SDT_BULK; }
204 int IsList() { return type == SDT_WLIST
205 || type == SDT_LLIST; }
206 int IsWords() { return type == SDT_WORD
207 || type == SDT_WLIST
208 || type == SDT_SELECT; }
209 int IsSingle() { return type == SDT_WORD
210 || type == SDT_SELECT
211 || type == SDT_LINE
212 || type == SDT_DATE; }
214 int CheckValue( StrBuf &value );
216 // Opt access
218 int IsRequired() { return opt == SDO_REQUIRED
219 || opt == SDO_KEY; }
221 int IsReadOnly() { return opt == SDO_ONCE
222 || opt == SDO_ALWAYS
223 || opt == SDO_KEY; }
225 // Fmt access
227 SpecFmt GetFmt() { return fmt; }
228 int GetSeq() { return seq; }
230 // Type building -- so jobspec can create a spec
232 const char * FmtOpt();
233 const char * FmtType();
234 const char * FmtFmt();
235 void SetSeq( int s ) { seq = s; }
236 void SetOpt( const char *optName, Error *e );
237 void SetFmt( const char *fmtName, Error *e );
238 void SetType( const char *s, Error *e );
240 int Compare( const SpecElem &other );
242 public: // only to SpecData's subclasses
244 SpecType type; // how it is formatted
245 StrBuf tag; // name of the field
246 StrBuf preset; // default preset value
247 StrBuf values; // what values can be had
248 int code; // what it's use it
249 StrBuf subCode; // user's code
250 char nWords; // how many words on the line
251 short maxLength; // advisory
252 SpecOpt opt; // how field is updated
254 private:
255 friend class Spec;
257 void Decode( StrRef *s, Error *e );
258 void Encode( StrBuf *s, int code );
260 // gui hints
262 SpecFmt fmt; // format code
263 int seq; // display sequence number
265 // reference back to Get(index)
267 int index;
270 class SpecWords : public StrBuf
272 public:
273 int Split();
274 void Join( int wc );
275 const char *wv[ SpecWordsMax + 1 ];
278 class SpecData {
280 public:
281 virtual ~SpecData() {}
282 // Extract data from or build data into user's data structure.
283 // Spec::Format() calls Get(); Spec::Parse() calls Set().
285 // One of the two sets of Get/Set must be replaced in the subclass.
287 // This interface assumes whole lines. Its default implementation
288 // calls the word-oriented Get/Set and Joins/Splits them into
289 // whole lines.
291 virtual StrPtr *GetLine( SpecElem *sd, int x, const char **cmt );
292 virtual void SetLine( SpecElem *sd, int x, const StrPtr *val,
293 Error *e );
295 // This interface has words-oriented lines split apart.
296 // The const version casts and calls the non-const version,
297 // for compatibility.
299 // The non-const one has a bogus default implementation.
301 virtual int Get( SpecElem *sd, int x, const char **wv, const char **cmt );
302 virtual void Set( SpecElem *sd, int x, const char **wv, Error *e );
304 virtual int Get( SpecElem *sd, int x, char **wv, char **cmt );
305 virtual void Set( SpecElem *sd, int x, char **wv, Error *e );
307 protected:
309 SpecWords tVal;
313 class SpecDataTable : public SpecData {
315 public:
316 SpecDataTable();
317 virtual ~SpecDataTable();
319 virtual StrPtr *GetLine( SpecElem *sd, int x, const char **cmt );
320 virtual void SetLine( SpecElem *sd, int x, const StrPtr *val,
321 Error *e );
323 StrDict * Dict() { return table; }
325 private:
327 StrDict *table;
331 #endif /* _spec_h_ */