/* * Copyright 1995, 1996 Perforce Software. All rights reserved. * * This file is part of Perforce - the FAST SCM System. */ /* * MapTable.h - mapping table interface * * Public Classes: * * MapTable - a mapping table * * Public Methods: * * MapTable::Better( MapTable &other, MapTableT dir ) * Compares the depths of MapTree used for matching to see * which table would provide quicker matching. * * MapTable::Check( MapTableT direction, char *from ) * Does the matching part of Translate(), but not the generating * of the target string. Returns 0 on no match and a MapItem * * on match. * * MapTable::Clear() * Empties the table. * * MapTable::Count() * Returns the number of map entries. * * MapTable::Disambiguate() * Mappings provided by the user (client views, branch views) * can be ambiguous since later mappings can override earlier * ones. Disambiguate() adds explicit exclusion (-) mappings * for any ambiguous mappings, so that Join() and Translate() * don't have to worry about them. * * MapTable::Dump( char *trace ) * Print out the mapping on the standard output. * * MapTable::EmptyReason() * Return what was set by SetReason() or Join(). * * MapTable::Get( int n ) * Gets the n'th map table entry, returning a MapItem *. * * MapTable::GetFlag( MapItem *m ) * Gets MapItem m's map flag. * * MapTable::GetStr( MapItem *m, MapTableT dir ) * Gets MapItem m's map string for dir. * * MapTable::Insert( const StrPtr &lhs, const StrPtr &rhs, MapFlag f ) * Insert a mapping entry. The following wildcards are * supported: %1-%9, *, "...". lhs and rhs must agree * in wildcards. * * MapTable::InsertByPattern( StrBuf &lhs, StrBuf &rhs, MapFlag f ) * Takes two strings and makes a pattern out of them by * replacing the righthand common substrings with ... or * * depending on whether the substrings included a '/'. * Won't replace the first 3 '/'s (i.e. //depot/). * * MapTable::IsEmpty() * Returns 1 if there are no map table entries, or * if all entries are unmappings. * * MapTable::HasOverlays() * Returns 1 if there are + mappings in the table. * * MapTable::IsSingle() * Returns 1 if there exactly one mapping and it contains no * wildcards. * * MapTable::Join( MapTableT d1, MapTable *m2, MapTableT d2, ErrorId *r ) * Joins the d1 side of this mapping against the d2 side of * the mapping in m2, filling in the MapTable. The result is * the revised (limited) lhs and rhs of the map. r is the * emptyReason used if the join turns up empty but neither map * was empty. * * MapTable::Join2( MapTableT d1,MapTable *m2, MapTableT d2, ErrorId *r ) * Joins the mapping in this mapping against the mapping in m2, * filling in the MapTable. The rhs of the map is joined with * the lhs of maps2, and the result is the revised lhs of * m1 and the revised rhs of m2. * * MapTable::JoinCheck( MapTableT dir, const StrPtr &lhs ) * Returns 1 if lhs joined agains the dir of this MapTable * produces any rows, i.e. if this MapTable includes lhs. * * MapTable::Match( char *lhs, char *from ) * Matches the pattern lhs against from. Returns 1 on match * and 0 on no match. Cheesy access to MapHalf::Match(). * * MapTable::Reverse() * Turn the order of the mapping around, to make them appear * if they were appended instead of inserted. * * Maptable::SetReason( char *emptyReason ) * Set reason to be returned by EmptyReason(). The reason * strings are assumed to be global. This reason string is * used by DbPipeMap* (if set) if the map is empty or filtered * out all the incoming rows. * * MapTable::Strings( MapTableT direction ) * Returns a MapStrings object which contains sorted initial * substrings for finding candidates pathnames that will map * through the MapTable. Direction == LHS (0) or RHS (1), * meaning find strings for all lhs or rhs sides of the mapping. * * MapTable::StripMap( MapFlag mapFlag ) * Returns a copy of the MapTable, without any of the mapFlag * entries. * * MapTable::Translate( MapTableT dir, char *from, StrBuf *to ) * Maps 'from' to 'to' returning the MapItem that matched, or 0 * if nothing matches. Direction is LHS (0) if 'from' * matches lhs, and RHS (1) if 'from' matches rhs. * * MapTable::Validate( char *lhs, char *rhs, Error *e ) * Verifies that a mapping has the same wildcards on both * sides. * * MapTable::ValidHalf( MapTableT direction, Error *e ) * Verifies that a mapping has the permitted number of * wildcards. */ class MapItem; class MapJoiner; struct MapParams; class MapStrings; class MapTree; class MapHalf; class StrBuf; class MapItemArray; enum MapTableT { LHS, // do operation on left-hand-side strings RHS // do operation on right-hand-side strings } ; enum MapFlag { MfMap, // map MfUnmap, // -map MfRemap, // +map MfHavemap, // $map MfChangemap, // @map MfAndmap, // &map // empty // empty // empty // empty MfStream1 = 10, // Stream, Paths MfStream2 = 11, // Stream, Remapped MfStream3 = 12, // Stream, Ignored MfStream5 = 14, // Stream, Paths: shared MfStream6 = 15, // Stream, Paths: public MfStream7 = 16, // Stream, Paths: private MfStream8 = 17 // Stream, Paths: excluded } ; class MapTable { public: MapTable(); ~MapTable(); MapTable& operator=( MapTable &f ); int Better( MapTable &other, MapTableT direction ); MapItem * Check( MapTableT direction, const StrPtr &from ); void Clear(); int Count() { return count; } void Disambiguate(); void Dump( const char *trace, int fmt=0 ); void DumpTree( MapTableT dir, const char *trace ); void Insert( const StrPtr &l, const StrPtr &r = StrRef::Null(), MapFlag f = MfMap ); void Insert( const StrPtr &l, int slot, const StrPtr &r = StrRef::Null(), MapFlag f = MfMap ); void Insert( MapTable *table, int fwd = 1, int rev = 0 ); void InsertByPattern( const StrPtr &l, const StrPtr &r, MapFlag f ); int IsEmpty() const { return !hasMaps; } int JoinError() const { return joinError; } int HasOverlays() const { return hasOverlays; } int HasHavemaps() const { return hasHavemaps; } int HasAndmaps() const { return hasAndmaps; } int IsSingle() const; void JoinOptimizer( MapTableT dir2 ); MapTable * Join( MapTableT dir1, MapTable *m2, MapTableT dir2, const ErrorId *reason = 0 ); MapTable * Join2( MapTableT dir1, MapTable *m2, MapTableT dir2, const ErrorId *reason = 0 ); int JoinCheck( MapTableT dir, const StrPtr &lhs ); static int Match( const StrPtr &lhs, const StrPtr &rhs ); static int Match( MapHalf *l, const StrPtr &rhs ); static int ValidDepotMap( const StrPtr &map ); void Reverse(); MapStrings * Strings( MapTableT dir ); MapTable * StripMap( MapFlag mapFlag ); MapTable * Swap( MapTable *m ); int CountByFlag( MapFlag mapFlag ); MapItem * Translate( MapTableT dir, const StrPtr &f, StrBuf &t ); MapItemArray * Explode( MapTableT dir, const StrPtr &f ); void Validate( const StrPtr &l, const StrPtr &r, Error *e ); void ValidHalf( MapTableT dir, Error *e ); int GetHash(); void SetReason( const ErrorId *e ) { emptyReason = e; } const ErrorId * EmptyReason() { return emptyReason; } public: // MapItem access, so we don't have to declare the MapItem here. MapItem * Get( int n ); int GetSlot( MapItem *m ); static MapFlag GetFlag( MapItem *m ); static MapItem * GetNext( MapItem *m ); static const StrPtr * GetStr( MapItem *m, MapTableT direction ); const StrPtr * Get( int n, MapTableT direction ) { return GetStr( Get( n ), direction ); } static int Translate( MapItem *m, MapTableT dir, const StrPtr &f, StrBuf &t ); public: // For internal use. void InsertNoDups( const StrPtr &l, const StrPtr &r, MapFlag flag ); MapItem ** Sort( MapTableT, int streamFlag=0 ); private: void Join( MapTable *m1, MapTableT dir1, MapTable *m2, MapTableT dir2, MapJoiner *j, const ErrorId *reason ); // For building the string table for MapStrings and the // MapTree for Match() and Translate(). void MakeTree( MapTableT ); // count is length of entry chain. // entry is the chain of mappings. // trees is the pair of search trees for Match() and Translate() int count; MapItem * entry; MapTree * trees; const ErrorId * emptyReason; int joinError; // For IsEmpty/HasOverlays/HasHavemaps/hasAndmaps int hasMaps; int hasOverlays; int hasHavemaps; int hasAndmaps; } ;