/* * Copyright 1995, 1996 Perforce Software. All rights reserved. */ /* * Spec.h - spec manipulation * * Description: * * A 'spec' is one of those dumb ascii forms that user edits * to specify various information -- clients, labels, etc. * * The Spec class is a spec definition, indicating what fields * there are and their format. For formatting and parsing, * Spec::Format() and Spec::Parse() expect a subclassed * SpecData object, with SpecData::Get() and SpecData::Put() * defined for moving data between the actual object and the spec. * * The Spec object contains SpecElems to describe each element * of a spec. * * A Spec can be encoded into a simple string for passing between * processes. Spec::Encode() and Spec::Decode() do this. They * are built for interoperability. Namely, Decode() ignores fields * it doesn't understand. * * Finally, a Spec is also be represented as a 'jobspec': this is * actually a form (formatted by Spec) that describes another Spec * (in jobspec's case, a job's Spec). The SpecData that does this * is part of the jobspec code, but that uses Spec::Add(), Get() * and SpecElem::Fmt*() and Set*() for low level construction/ * examination of the spec. * * Class Defined: * * Spec - the definition of a spec, for parsing and formatting * SpecElem - the definition of a single item type in a spec * SpecData - a spec-specific formatter/parser helper * SpecWords -- array of words in a spec value, allowing surrounding "'s * SpecDataTable -- a SpecData interface to a StrDict * * Virtual methods, to be defined by caller: * * SpecData::Get() - get a data value for stuffing into a spec * SpecData::Set() - set a data value parsed from a spec * * Public methods: * * Spec::Add() -- add a single SpecElem manually, with default values * Spec::Decode() -- decode a spec definition from a string * Spec::Encode() -- encode a spec definition in a transmittable string * Spec::Find() -- find a SpecElem in the spec * Spec::Get() -- find n'th SpecElem in the spec * Spec::GetComment() -- return the spec's comment string * Spec::Format() -- turn SpecData into a spec string * Spec::Parse() -- parse a spec string into SpecData * Spec::ParseNoValid() -- parse without validating 'select' items * Spec::SetComment() -- set the spec's comment string * * SpecElem::FmtOpt() - format the SpecOpt for jobspec * SpecElem::FmtType() - format the SpecType for jobspec * SpecElem::Is*() - ask various questions about the SpecType * SpecElem::SetOpt() - parse the SpecOpt from a jobspec * SpecElem::SetType() - format the SpecOpt for a jobspec */ #ifndef _spec_h_ #define _spec_h_ class VarArray; class SpecData; class SpecElem; class StrBufDict; const int SpecWordsMax = 10; // for SDT_WORD, WLIST, SELECT enum SpecType { SDT_WORD, // single line, N words SDT_WLIST, // multiple lines, N words SDT_SELECT, // SDT_WORD from a list of words SDT_LINE, // single line of text (arbitrary words) SDT_LLIST, // multiple lines of text (arbitrary words) SDT_DATE, // SDT_LINE that is a date SDT_TEXT, // block of text, SDT_BULK // SDT_TEXT not indexed } ; enum SpecOpt { SDO_OPTIONAL, // not required, user updatable, no default SDO_DEFAULT, // not required, user updatable, default provided SDO_REQUIRED, // required, user updatable, default provided SDO_ONCE, // required, not updatable, set once and SDO_ALWAYS // required, not updatable, set after every update } ; class Spec { public: Spec(); Spec( const char *encoded, const char *cmt ); ~Spec(); // Using the Spec -- formatting and parsing forms StrBuf * Format( SpecData *data ) { StrBuf *s = new StrBuf; Format( data, s ); return s; } void Format( SpecData *data, StrBuf *result ); void Format( SpecData *data, StrDict *result ); void Parse( char *buf, SpecData *data, Error *e, int valid ); void Parse( char *buf, SpecData *data, Error *e ) { Parse( buf, data, e, 1 ); } void ParseNoValid( char *buf, SpecData *data, Error *e ) { Parse( buf, data, e, 0 ); } // Manipulating the Spec itself -- building and examining it SpecElem * Add( const StrPtr &tag ); SpecElem * Get( int i ); SpecElem * Find( const StrPtr &tag, Error *e = 0 ); SpecElem * Find( int code, Error *e = 0 ); int Count(); void Decode( StrPtr *encoded, Error *e ); void Encode( StrBuf *encoded ); const StrPtr * GetComment() { return &comment; } void SetComment( const StrPtr &c ) { comment = c; } SpecElem * Add( char *t ) { return Add( StrRef( t ) ); } private: StrRef comment; VarArray *elems; StrBuf decoderBuffer; } ; class SpecElem { public: // Type access int IsDate() { return type == SDT_DATE; } int IsSelect() { return type == SDT_SELECT; } int IsText() { return type == SDT_TEXT || type == SDT_BULK; } int IsList() { return type == SDT_WLIST || type == SDT_LLIST; } int IsWords() { return type == SDT_WORD || type == SDT_WLIST || type == SDT_SELECT; } int IsSingle() { return type == SDT_WORD || type == SDT_SELECT || type == SDT_LINE || type == SDT_DATE; } int CheckValue( StrBuf &value ); // Opt access int IsRequired() { return opt == SDO_REQUIRED || opt == SDO_ONCE || opt == SDO_ALWAYS; } int IsReadOnly() { return opt == SDO_ONCE || opt == SDO_ALWAYS; } // Type building -- so jobspec can create a spec const char * FmtOpt(); const char * FmtType(); void SetOpt( const char *optName, Error *e ); void SetType( const char *s, Error *e ); public: // only to SpecData's subclasses SpecType type; // how it is formatted StrBuf tag; // name of the field StrBuf preset; // default preset value StrBuf values; // what values can be had int code; // what it's use it StrBuf subCode; // user's code char nWords; // how many words on the line short maxLength; // advisory SpecOpt opt; // how field is updated // historical -- derived from opt char required; // whether it can be blank char isReadOnly; // if the user can change it ever private: friend class Spec; void Decode( StrRef *s, Error *e ); void Encode( StrBuf *s, int code ); int index; // reference back to Get(index) } ; class SpecWords : public StrBuf { public: int Split(); void Join( int wc ); const char *wv[ SpecWordsMax + 1 ]; } ; class SpecData { public: virtual ~SpecData() {} // Extract data from or build data into user's data structure. // Spec::Format() calls Get(); Spec::Parse() calls Set(). // One of the two sets of Get/Set must be replaced in the subclass. // This interface assumes whole lines. Its default implementation // calls the word-oriented Get/Set and Joins/Splits them into // whole lines. virtual StrPtr *GetLine( SpecElem *sd, int x, const char **cmt ); virtual void SetLine( SpecElem *sd, int x, const StrPtr *val, Error *e ); // This interface has words-oriented lines split apart. // The const version casts and calls the non-const version, // for compatibility. // The non-const one has a bogus default implementation. virtual int Get( SpecElem *sd, int x, const char **wv, const char **cmt ); virtual void Set( SpecElem *sd, int x, const char **wv, Error *e ); virtual int Get( SpecElem *sd, int x, char **wv, char **cmt ); virtual void Set( SpecElem *sd, int x, char **wv, Error *e ); protected: SpecWords tVal; } ; class SpecDataTable : public SpecData { public: SpecDataTable(); virtual ~SpecDataTable(); virtual StrPtr *GetLine( SpecElem *sd, int x, const char **cmt ); virtual void SetLine( SpecElem *sd, int x, const StrPtr *val, Error *e ); StrDict * Dict() { return table; } private: StrDict *table; } ; #endif /* _spec_h_ */
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 767 | Paul Krause |
upgrade p4api files to r01.1 ftp://ftp.perforce.com/pub/perforce/r01.1/bin.ntx86/ |
||
#1 | 759 | Paul Krause | files from p4api.tar (reogranized) |