/* * Copyright 1995, 2000 Perforce Software. All rights reserved. * * This file is part of Perforce - the FAST SCM System. */ /* * specdata.cc -- SpecWords, SpecData, SpecDataTable */ # include <stdhdrs.h> # include <charman.h> # include <debug.h> # include <strbuf.h> # include <strdict.h> # include <strtable.h> # include <error.h> # include <errorlog.h> # include "spec.h" # include <msgdb.h> /* * SpecWords -- array of words in a spec value, allowing surrounding "'s */ int SpecWords::Split() { int wc = 0; char *buf = Text(); while( wc < SpecWordsMax ) { // Skip blanks while( isAspace( buf ) ) buf++; if( !*buf ) break; // First letter of new word if( *buf == '"' ) { // quoted wv[ wc++ ] = ++buf; while( *buf && *buf != '"' ) buf++; } else { // Non-quoted wv[ wc++ ] = buf; while( *buf && !isAspace( buf ) ) buf++; } if( !*buf ) break; // First blank after word *buf++ = '\0'; } wv[ wc ] = 0; return wc; } void SpecWords::Join( int wc ) { // To handle single line comments, there are no values // returned in **words, just **cmts, check for any null // values and return a null string. for( int i = 0; i < wc; i++ ) { if( !wv[i] ) { *this << ""; return; } } for( int i = 0; i < wc; i++ ) { if( i ) *this << " "; // quote if spaces or null if( !*wv[i] || strchr( wv[i], ' ' ) || strchr( wv[i], '#' ) ) *this << "\"" << wv[i] << "\""; else *this << wv[i]; } } /* * SpecData -- default Get()/Set() that do line splitting/joining */ StrPtr * SpecData::GetLine( SpecElem *sd, int x, const char **cmt ) { if( !Get( sd, x, tVal.wv, cmt ) ) return 0; if( sd->IsWords() ) { tVal.Clear(); // join the maximum number of words. if( sd->maxWords && tVal.wv[sd->maxWords-1] ) tVal.Join( sd->maxWords ); else tVal.Join( sd->nWords ); } else { tVal.Set( tVal.wv[0] ); } return &tVal; } void SpecData::SetLine( SpecElem *sd, int x, const StrPtr *val, Error *e ) { if( sd->IsWords() ) { tVal.Set( *val ); int wordCount = tVal.Split(); int wordMax = sd->maxWords ? sd->maxWords : sd->nWords; if( wordCount < sd->nWords || wordCount > wordMax) { e->Set( MsgDb::FieldWords ) << sd->tag; return; } } else { tVal.wv[0] = val->Text(); } Set( sd, x, tVal.wv, e ); } void SpecData::SetComment( SpecElem *sd, int x, const StrPtr *val, int nl, Error *e ) { tVal.wv[0] = val->Text(); Comment( sd, x, tVal.wv, nl, e ); } int SpecData::Get( SpecElem *sd, int x, const char **wv, const char **cmt ) { return Get( sd, x, (char **)wv, (char **)cmt ); } void SpecData::Set( SpecElem *sd, int x, const char **wv, Error *e ) { Set( sd, x, (char **)wv, e ); } void SpecData::Comment( SpecElem *sd, int x, const char **wv, int nl, Error *e ) { Comment( sd, x, (char **)wv, nl, e ); } int SpecData::Get( SpecElem *sd, int x, char **wv, char **cmt ) { AssertError.Set( E_FATAL, "SpecData::Get called!" ); AssertLog.Abort( &AssertError ); return 0; } void SpecData::Set( SpecElem *sd, int x, char **wv, Error *e ) { e->Set( E_FATAL, "SpecData::Set called!" ); } void SpecData::Comment( SpecElem *sd, int x, char **wv, int nl, Error *e ) { // No message, comments will be ignored. } /* * SpecDataTable -- a SpecData interface to a StrDict */ SpecDataTable::SpecDataTable( StrDict *dict ) { if( dict ) { table = dict; privateTable = 0; } else { table = new StrBufDict; privateTable = 1; } } SpecDataTable::~SpecDataTable() { if( privateTable ) delete table; } StrPtr * SpecDataTable::GetLine( SpecElem *sd, int x, const char **cmt ) { *cmt = 0; if( sd->IsList() ) return table->GetVar( sd->tag, x ); else return table->GetVar( sd->tag ); } void SpecDataTable::SetLine( SpecElem *sd, int x, const StrPtr *val, Error *e ) { if( sd->IsList() ) table->SetVar( sd->tag, x, *val ); else table->SetVar( sd->tag, *val ); } void SpecDataTable::SetComment( SpecElem *sd, int x, const StrPtr *val, int nl, Error *e ) { StrBuf name; name << sd->tag << "Comment"; if( sd->IsList() ) table->SetVar( name, x - (nl ? 0 : 1), *val ); else table->SetVar( name, *val ); }