tripwire-open-source/src/db/hierdatabase.h

286 lines
11 KiB
C++

//
// The developer of the original code and/or files is Tripwire, Inc.
// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire,
// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights
// reserved.
//
// This program is free software. The contents of this file are subject
// to the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version. You may redistribute it and/or modify it
// only in compliance with the GNU General Public License.
//
// This program is distributed in the hope that it will be useful.
// However, this program is distributed AS-IS WITHOUT ANY
// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
// FOR A PARTICULAR PURPOSE. Please see the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// Nothing in the GNU General Public License or any other license to use
// the code or files shall permit you to use Tripwire's trademarks,
// service marks, or other intellectual property without Tripwire's
// prior written consent.
//
// If you have any questions, please contact Tripwire, Inc. at either
// info@tripwire.org or www.tripwire.org.
//
///////////////////////////////////////////////////////////////////////////////
// hierdatabase.h
//
#ifndef __HIERDATABASE_H
#define __HIERDATABASE_H
#ifndef __BLOCKRECORDFILE_H
#include "blockrecordfile.h"
#endif
#ifndef __HIERDBNODE_H
#include "hierdbnode.h"
#endif
#ifndef __ERROR_H
#include "core/error.h"
#endif
#ifndef __HIERDBPATH_H
#include "hierdbpath.h"
#endif
#if HAVE_STRINGS_H // RTEMS needs this for strcasecmp
# include <strings.h>
#endif
class cHierDatabaseIter;
class cErrorBucket;
TSS_EXCEPTION( eHierDatabase, eError );
TSS_EXCEPTION( eHierDbInternal, eHierDatabase ); // not used
TSS_EXCEPTION( eHierDbDupeName, eHierDatabase );
//
// TODO -- store some header info with the root node -- at least whether the db is case-sensitive or not
// and what the delimiting character is
//
//-----------------------------------------------------------------------------
// cHierDatabase -- a hierarchical database class
//-----------------------------------------------------------------------------
class cHierDatabase : public cBlockRecordFile
{
public:
cHierDatabase( bool bCaseSensitive = true, TCHAR delChar = _T('/') );
// NOTE -- these two parameters are only used if the database is being created; otherwise, they
// are overwritten when Open() is called.
virtual ~cHierDatabase();
//
// overrides from base class
//
virtual void Open ( const TSTRING& fileName, int numPages = 5, bool bTruncate = false ); //throw (eArchive, eHierDatabase)
virtual void Open ( cBidirArchive* pArch, int numPages = 5 ); //throw (eArchive, eHierDatabase)
// for the second Open(), this class owns the destruction of the archive
//TODO -- make numPages the last parameter
bool IsCaseSensitive() const { return mbCaseSensitive; }
TCHAR GetDelimitingChar() const { return mDelimitingChar; }
enum { INVALID_INDEX = -1 };
typedef cHierDatabaseIter iterator;
typedef cBlockRecordFile inherited;
private:
cHierAddr mRootArrayAddr; // this is the address of the top-level array
bool mbCaseSensitive;
TCHAR mDelimitingChar;
cHierDatabase ( const cHierDatabase& rhs ); //not impl
void operator= ( const cHierDatabase& rhs ); //not impl
void OpenImpl ( bool bTruncate ); //throw (eArchive, eHierDatabase)
// both Open() methods call this to initialize the class after calling
// inherited::Open()
friend class cHierDatabaseIter;
};
//-----------------------------------------------------------------------------
// cHierDatabaseIter -- the iterator class
//-----------------------------------------------------------------------------
class cHierDatabaseIter
{
public:
cHierDatabaseIter( cHierDatabase* pDb ); //throw (eArchive)
~cHierDatabaseIter();
//
// copying
//
cHierDatabaseIter ( const cHierDatabaseIter& rhs );
cHierDatabaseIter& operator=( const cHierDatabaseIter& rhs );
//
// name characteristics -- these are alternatives to specifying in the ctor
//
void SetCaseSensitive ( bool bCaseSensitive );
bool IsCaseSensitive ( void ) const;
void SetDelimitingChar ( TCHAR c );
TCHAR GetDelimitingChar ( void ) const;
//
// traverse up and down the hierarchy
//
bool AtRoot() const; //throw (eHierDatabase)
bool CanDescend() const;
void Descend() ;
void Ascend() ;
//
// traverse my peers (objects in the same directory as me)
//
void SeekBegin();
bool Done() const;
void Next();
bool SeekTo(const TCHAR* pName);
// seeks to the named peer; returns false and is positioned in an undefined
// place if it can't find the peer.
// it is either case sensitive or insensitive, depending on what was passed to the
// ctor.
void SeekToRoot(); //throw (eArchive)
// positions the iterator at the root node
void Refresh(); //throw (eArchive, eHierDatabase)
// refresh the iterator's contents in case the db has changed since we first entered
// this directory.
// note that this will move the iterator back to the beginning of the array
//
// getting at the entry's data...
//
const TCHAR* GetName() const;
const TSTRING GetCwd() const;
//
// creating arrays and entries (ie directories and files)
//
void CreateChildArray(); //throw (eArchive, eHierDatabase)
void CreateEntry ( const TSTRING& name );//throw (eArchive, eHierDatabase)
// after the entry is added, this iterator points at it.
// if the entry already exists in the database, an error is added to pError.
//
// getting and setting the data associated with a given entry
//
int8* GetData(int32& length) const; //throw (eArchive, eHierDatabase)
// returns the data associated with the current entry; this asserts that the iterator is
// not done and the current entry has data associated with it
bool HasData() const ;
// returns true if the current entry has data
void SetData(int8* pData, int32 length); //throw (eArchive, eHierDatabase)
void RemoveData(); //throw (eArchive, eHierDatabase)
// removes the data associated with the current entry; this asserts that the current
// entry actually _has_ data
//
// deleting arrays and entries
//
void DeleteEntry(); //throw (eArchive, eHierDatabase)
// deletes the currently pointed-at entry; this assumes that Done() is not true, and
// advances to the next node.
bool ChildArrayEmpty(); //throw (eArchive, eHierDatabase)
// returns true if the node's child array is empty
void DeleteChildArray(); //throw (eArchive, eHierDatabase)
// this method deletes the child array of the current object. This method asserts that
// Done() is not true, that the current node has a child, and that the child array is
// empty (TODO -- perhaps in the future we will want to make the equivalant of "rm -rf"
//
// util function for sorting/searching
//
bool CompareForUpperBound( const cHierEntry& he, const TCHAR* pchName ) const;
// compares shortname of FCO to pchName. returns < == or > 0 as strcmp does.
protected:
cHierAddr GetCurrentAddr() const;
// returns the address of the current cHierEntry by examining either the previous pNext pointer or the
// array info pointer if the first entry is current. This asserts (! Done())
//-------------------------------------------------------------------------
// member data
//-------------------------------------------------------------------------
// TODO -- maybe this should be a fully insulated class?
// TODO -- maybe this should be a set to reduce insert and lookup time?
typedef std::vector<cHierEntry> EntryArray;
cHierDatabase* mpDb; // the database
EntryArray mEntries; // vector of entries for the current level
cHierArrayInfo mInfo;
cHierAddr mInfoAddr;
EntryArray::iterator mIter; // my current position in the array
cHierDbPath mCurPath; // The current working directory.
//-------------------------------------------------------------------------
// helper methods
//-------------------------------------------------------------------------
void LoadArrayAt(const cHierAddr& addr); //throw (eArchive, eHierDatabase)
// initializes the iterator so that it is pointing at the array named by addr.
int Compare( const TCHAR* pc1, const TCHAR* pc2 ) const;
// this acts just like strcmp, but takes into account whether the database is case-sensitive or not.
EntryArray::iterator UpperBound( const TCHAR* pchName );
// same as std::upper_bound except it calls CompareForUpperBound() to
// do its comparison.
};
//#############################################################################
// inline implementation
//#############################################################################
inline void cHierDatabaseIter::Refresh()
{
cHierAddr infoAddr = mInfoAddr;
LoadArrayAt( infoAddr );
}
inline void cHierDatabaseIter::SetCaseSensitive ( bool bCaseSensitive )
{
mCurPath.SetCaseSensitive( bCaseSensitive );
}
inline bool cHierDatabaseIter::IsCaseSensitive( void ) const
{
return mCurPath.IsCaseSensitive();
}
inline void cHierDatabaseIter::SetDelimitingChar( TCHAR c )
{
mCurPath.SetDelimiter( c );
}
inline TCHAR cHierDatabaseIter::GetDelimitingChar( void ) const
{
return mCurPath.GetDelimiter();
}
///////////////////////////////////////////////////////////////////////////////
// Compare
///////////////////////////////////////////////////////////////////////////////
inline int cHierDatabaseIter::Compare( const TCHAR* pc1, const TCHAR* pc2 ) const
{
if( mCurPath.IsCaseSensitive() )
{
return ( _tcscmp( pc1, pc2 ) );
}
else
{
return ( _tcsicmp( pc1, pc2 ) );
}
}
#endif //__HIERDATABASE_H