strbuf.h #1

  • //
  • guest/
  • alan_petersen/
  • piper/
  • mac/
  • R2.0/
  • Perforce/
  • p4api/
  • Headers/
  • strbuf.h
  • View
  • Commits
  • Open Download .zip Download (14 KB)
/*
 * Copyright 1995, 1996 Perforce Software.  All rights reserved.
 *
 * This file is part of Perforce - the FAST SCM System.
 */

/*
 * StrBuf.h - multipurpose buffers
 *
 * StrPtr, StrRef, and StrBuf are used throughout the system, as buffers
 * for storing just about any variable length byte data. 
 *
 * StrPtr is a low-cost (no constructor, no destructor, 8 byte) 
 * pointer/length pair to mutable data.  It has a variety of methods
 * to mangle it.
 *
 * StrRef is a kind-of StrPtr that allows the buffer pointer to be set.
 * As StrPtr doesn't allow this, a StrPtr object itself isn't useful.
 *
 * StrNum is a kind-of StrPtr with a temporary buffer whose only purpose
 * is to hold the string representation of an int.
 *
 * StrBuf is a kind-of StrPtr that allocates and extends it own buffer.
 *
 * StrFixed is a kind-of StrPtr that points to a character array that
 * is fixed at construction.
 *
 * Classes:
 *
 *	StrPtr - a pointer/length for arbitrary data
 *	StrRef - StrPtr that can be set
 *	StrBuf - StrPtr of privately allocated data
 *	StrFixed - StrPtr to a fixed length char buffer
 *	StrNum - StrPtr that holds a string of an int
 *	StrHuman - StrPtr that holds a "human-readable" string of an int
 *
 * Methods:
 *
 *	StrPtr::Clear() - set length = 0
 *	StrPtr::Text() - return buffer pointer
 *	StrPtr::Value() - return buffer pointer (old name)
 *	StrPtr::Length() - return buffer length
 *	StrPtr::GetEnd() - return pointer to character past end
 *	StrPtr::Atoi() - convert to integer and return
 *	StrPtr::Atoi64() - convert to P4INT64 and return
 *	StrPtr::Itoa() - format an int given the end of a buffer
 *	StrPtr::Itoa64() - format a P4INT64 given the end of a buffer
 *	StrPtr::SetLength() - set only length
 *	StrPtr::SetEnd() - set length by calculating from start
 *	StrPtr::[] - get a single character
 *	StrPtr::XCompare() - case exact string compare
 *	StrPtr::CCompare() - case folding string compare
 *	StrPtr::SCompare() - case aware string compare -- see strbuf.cc
 *	StrPtr::SEqual() - case aware character compare -- see strbuf.cc
 *	StrPtr::Contains() - finds a substring
 *	StrPtr::== - compare contents with buffer
 *	StrPtr::!= - compare contents with buffer
 *	StrPtr::< - compare contents with buffer
 *	StrPtr::<= - compare contents with buffer
 *	StrPtr::> - compare contents with buffer
 *	StrPtr::>= - compare contents with buffer
 *	StrPtr::StrCpy() - copy string out to a buffer
 *	StrPtr::StrCat() - copy string out to end of a buffer
 *	StrPtr::CaseFolding() - (static) SCompare sorts A < a, a < B
 *	StrPtr::CaseIgnored() - (static) SCompare sorts A == a, a < B
 *	StrPtr::CaseHybrid() - (static) SCompare sorts Ax < ax, aa < AX
 *	StrPtr::SetCaseFolding() - (static) 0=UNIX, 1=NT, 2=HYBRID
 *
 *	---
 *
 *	StrRef::Set() - set pointer/length
 *	StrRef::+= - move pointer/length
 *
 *	---
 *
 *	StrBuf::StringInit() - mimic actions of constructor
 *	StrBuf::Set() - allocate and fill from buffer
 *	StrBuf::Append() - extend and terminate from buffer
 *	StrBuf::Extend() - append contents from buffer
 *	StrBuf::Terminate() - terminate buffer
 *	StrBuf::Alloc() - allocate space in buffer and return pointer
 *	StrBuf::<< - Append contents from buffer or number
 *	StrBuf::Indent() - fill by indenting contents of another buffer
 *	StrBuf::Expand() - expand a string doing %var substitutions
 *	
 */

class StrBuf;

// On 64 bit platforms, the base 'size_t' type is 64 bits, which is much
// more than we need, or can handle. So we use our own size_t type instead;
// it's "p4size_t", defined in stdhdrs.h

// General String Buffer Sizes
# define SIZE_LINESTR     256
# define SIZE_SMALLSTR   1024
# define SIZE_MEDSTR     4096

class StrPtr {

    public:
	// Setting, getting

	char *	Text() const
		{ return buffer; }

	char *	Value() const
		{ return buffer; }

	unsigned char *UText() const
		{ return (unsigned char *)Text(); }

	p4size_t 	Length() const
		{ return length; }

	char *	End() const
		{ return Text() + length; }

	unsigned char *UEnd() const
		{ return UText() + length; }

	int	Atoi() const
		{ return Atoi( buffer ); }

	bool	IsNumeric() const;

	int	EndsWith( const char *s, int l ) const;

	P4INT64	Atoi64() const
		{ return Atoi64( buffer ); }

	void	SetLength() 
		{ length = strlen( buffer ); }

	void	SetLength( p4size_t len )
		{ length = len; }

	void	SetEnd( char *p ) 
		{ length = p - buffer; }

	char	operator[]( p4size_t x ) const
		{ return buffer[x]; }

	// Compare -- p4ftp legacy

	int	Compare( const StrPtr &s ) const
		{ return SCompare( s ); }

	// CCompare/SCompare/XCompare

	int	CCompare( const StrPtr &s ) const
		{ return CCompare( buffer, s.buffer ); }

	int	SCompare( const StrPtr &s ) const
		{ return SCompare( buffer, s.buffer ); }

	int	NCompare( const StrPtr &s ) const
		{ return NCompare( buffer, s.buffer ); }

	static int CCompare( const char *a, const char *b );
	static int SCompare( const char *a, const char *b );
	static int NCompare( const char *a, const char *b );

	static int SCompare( unsigned char a, unsigned char b )
		{
		    return a==b ? 0 : SCompareF( a, b );
		}

	static int SEqual( unsigned char a, unsigned char b )
		{ 
		    switch( a^b ) 
		    { 
		    default: return 0;
		    case 0: return 1;
		    case 'A'^'a': return SEqualF( a, b );
		    }
		}

	int	SCompareN( const StrPtr &s ) const;

	int	XCompare( const StrPtr &s ) const
		{ return strcmp( buffer, s.buffer ); }

	static int XCompare( const char *a, const char *b )
		{ return strcmp( a, b ); }

	int	XCompareN( const StrPtr &s ) const
		{ return strncmp( buffer, s.buffer, length ); }

	// More comparing

	const char *Contains( const StrPtr &s ) const
		{ return strstr( Text(), s.Text() ); }

	bool	operator ==( const char *buf ) const
		{ return strcmp( buffer, buf ) == 0; }

	bool	operator !=( const char *buf ) const
		{ return strcmp( buffer, buf ) != 0; }

	bool	operator <( const char *buf ) const
		{ return strcmp( buffer, buf ) < 0; }

	bool	operator <=( const char *buf ) const
		{ return strcmp( buffer, buf ) <= 0; }

	bool	operator >( const char *buf ) const
		{ return strcmp( buffer, buf ) > 0; }

	bool	operator >=( const char *buf ) const
		{ return strcmp( buffer, buf ) >= 0; }

	bool	operator ==( const StrPtr &s ) const
		{ return strcmp( buffer, s.buffer ) == 0; }

	bool	operator !=( const StrPtr &s ) const
		{ return strcmp( buffer, s.buffer ) != 0; }

	bool	operator <( const StrPtr &s ) const
		{ return strcmp( buffer, s.buffer ) < 0; }

	bool	operator <=( const StrPtr &s ) const
		{ return strcmp( buffer, s.buffer ) <= 0; }

	bool	operator >( const StrPtr &s ) const
		{ return strcmp( buffer, s.buffer ) > 0; }

	bool	operator >=( const StrPtr &s ) const
		{ return strcmp( buffer, s.buffer ) >= 0; }

	// Copying out
	// Includes EOS

	void	StrCpy( char *b ) const
		{ memcpy( b, buffer, length + 1 ); }

	void	StrCat( char *b ) const
		{ memcpy( b + strlen( b ), buffer, length + 1 ); }

	// Formatting and parsing numbers as strings

	static int Atoi( const char *b ) { return atoi( b ); }
	static char *Itoa( int v, char *e ) { return Itoa64( v, e ); }

	static P4INT64 Atoi64( const char *buffer );
	static char *Itoa64( P4INT64 v, char *endbuf );
	static char *Itox( unsigned int v, char *endbuf );

    friend class StrBuf;
    friend class StrRef;

    protected:
	char	*buffer;
	p4size_t	length;

    public:

	// Case sensitive server?

	static bool CaseFolding()
		{ return caseUse != ST_UNIX; }

	static bool CaseIgnored()
		{ return caseUse == ST_WINDOWS; }

	static bool CaseHybrid()
		{ return caseUse == ST_HYBRID; }

	static void SetCaseFolding( int c )
		{ caseUse = (CaseUse)c; foldingSet = true; }

	static bool CaseFoldingAlreadySet()
		{ return foldingSet; }

	enum CaseUse { ST_UNIX, ST_WINDOWS, ST_HYBRID };

	static CaseUse CaseUsage() { return caseUse; }

    private:

	static CaseUse caseUse;
	static bool foldingSet;

	static int SEqualF( unsigned char a, unsigned char b );
	static int SCompareF( unsigned char a, unsigned char b );

	static int NCompareLeft( const unsigned char *a, 
	                         const unsigned char *b );
	static int NCompareRight( const unsigned char *a, 
	                          const unsigned char *b );
} ;

class StrRef : public StrPtr {

    public:

		StrRef() {}

		StrRef( const StrRef &s )
		{ Set( &s ); }

		StrRef( const StrPtr &s )
		{ Set( &s ); }

		StrRef( const char *buf )
		{ Set( (char *)buf ); }

		StrRef( const char *buf, p4size_t len )
		{ Set( (char *)buf, len ); }

	static const StrPtr &Null()
		{ return null; }

	const StrRef & operator =(const StrRef &s)
		{ Set( &s ); return *this; }

	const StrRef & operator =(const StrPtr &s)
		{ Set( &s ); return *this; }

	const StrRef & operator =(const char *buf)
		{ Set( (char *)buf ); return *this; }

	void	operator +=( int l )
		{ buffer += l; length -= l; }

	void 	Set( char *buf )
		{ Set( buf, strlen( buf ) ); }
		 
	void	Set( char *buf, p4size_t len )
		{ buffer = buf; length = len; }

	void	Set( const StrPtr *s )
		{ Set( s->buffer, s->length ); }

	void	Set( const StrPtr &s )
		{ Set( s.buffer, s.length ); }

    private:
    	static	StrRef null;

} ;

class StrBuf : public StrPtr {

    public:
		StrBuf() 
		{ StringInit(); }

	void	StringInit()
		{ length = size = 0; buffer = nullStrBuf; }

		~StrBuf()
		{ if( buffer != nullStrBuf ) delete []buffer; }

	// copy constructor, assignment

		StrBuf( const StrBuf &s )
		{ StringInit(); Set( &s ); }

		StrBuf( const StrRef &s )
		{ StringInit(); Set( &s ); }

		StrBuf( const StrPtr &s )
		{ StringInit(); Set( &s ); }

		StrBuf( const char *buf )
		{ StringInit(); Set( buf ); }

	const StrBuf & operator =(const StrBuf &s)
		{ if( this != &s ) Set( &s ); return *this; }

	const StrBuf & operator =(const StrRef &s)
		{ if( (const StrRef *)this != &s ) Set( &s ); return *this; }

	const StrBuf & operator =(const StrPtr &s)
		{ if( this != &s ) Set( &s ); return *this; }

	const StrBuf & operator =(const char *buf)
		{
		    if( (const char*)this != buf && buffer != buf )
			Set( buf );

		    return *this;
		}

	// Setting, getting

	void 	Clear( void )
		{ length = 0; }

	void 	Reset( void )
		{ 
		    if( buffer != nullStrBuf ) 
		    {
	                delete []buffer; 
		
		        length = size = 0; 
		        buffer = nullStrBuf; 
		    }
		}

	void	Reset( const char *buf )
		{ Reset(); UAppend( buf ); }

	void	Reset( const StrPtr *s )
		{ Reset(); UAppend( s ); }

	void 	Reset( const StrPtr &s )
		{ Reset(); UAppend( &s ); }

	void	Set( const char *buf )
	    { if( buf == Text() ) SetLength(); else { Clear(); Append( buf ); } }

	void	Set( const StrPtr *s )
	    { if( s != this ) { Clear(); UAppend( s ); } }

	void	Set( const StrPtr &s )
	    { if( &s != this ) { Clear(); UAppend( &s ); } }

	void	Set( const char *buf, p4size_t len )
	    { if( buf == Text() ) SetLength( len ); else { Clear(); Append( buf, len ); } }

	void	Extend( const char *buf, p4size_t len )
		{ memcpy( Alloc( len ), buf, len ); }

	void	Extend( char c )
		{ *Alloc(1) = c; }

	void 	Terminate() 
		{ Extend(0); --length; }

	void	TruncateBlanks();     // Removes blanks just from the end
	void	TrimBlanks();         // Removes blanks from start and end

	void	Append( const char *buf );     

	void	Append( const StrPtr *s );

	void	Append( const char *buf, p4size_t len );

	void	UAppend( const char *buf );     

	void	UAppend( const StrPtr *s );

	void	UAppend( const char *buf, p4size_t len );

	// large-block append
	void	BlockAppend( const char *buf );

	void	BlockAppend( const StrPtr *s );

	void	BlockAppend( const char *buf, p4size_t len );

	void	UBlockAppend( const char *buf );

	void	UBlockAppend( const StrPtr *s );

	void	UBlockAppend( const char *buf, p4size_t len );

	char *	Alloc( p4size_t len )
		{
		    p4size_t oldlen = length;

		    if( ( length += len ) > size )
			Grow( oldlen );

		    return buffer + oldlen;
		}

	// large block (>= 128KB) allocation; no extra space is reserved
	char *	BlockAlloc( p4size_t len )
		{
		    p4size_t oldlen = length;

		    if( ( length += len ) > size )
			Reserve( oldlen );

		    return buffer + oldlen;
		}

        void    Fill( const char *buf, p4size_t len );

        void    Fill( const char *buf )
                {
		    Fill( buf, Length() );
		}

	p4size_t 	BufSize() const
		{ return size; }

	// leading-string compression

	void	Compress( StrPtr *s );
	void	UnCompress( StrPtr *s );

	// trailing-string compression
	int	EncodeTail( StrPtr &s, const char *replaceBytes );
	int	DecodeTail( StrPtr &s, const char *replaceBytes );

	// string << -- append string/number

	StrBuf& operator <<( const char *s )
		{ Append( s ); return *this; }

	StrBuf& operator <<( const StrPtr *s )
		{ Append( s ); return *this; }

	StrBuf& operator <<( const StrPtr &s )
		{ Append( &s ); return *this; }

	StrBuf& operator <<( int v );

    private:
	p4size_t	size;

	void	Grow( p4size_t len );

	// reserve a large block of memory (>= 128 KB); don't over-allocate
	void	Reserve( p4size_t oldlen );

	// Some DbCompare funcs memcpy from this, so it has be be big
	// enough that we aren't reaching past valid memory.  The
	// largest one seems to be DbInt64 (8 bytes.)
	static char nullStrBuf[ 8 ];
} ;

class StrFixed : public StrPtr {

    public:

		StrFixed( p4size_t l )
		{ this->length = l; this->buffer = new char[ l ]; }

		~StrFixed()
		{ delete []buffer; }

	void	SetBufferSize( p4size_t l );
} ;


class StrNum : public StrPtr {

    public:
		StrNum() {} 

		StrNum( int v ) 
		{ Set( v ); }

		StrNum( int ok, int v )
		{ if( ok ) Set( v ); else buffer = buf, length = 0; }

	void	Set( int v )
		{
		    buffer = Itoa( v, buf + sizeof( buf ) );
		    length = buf + sizeof( buf ) - buffer - 1;
		}

	void	SetHex( int v )
		{
		    buffer = Itox( v, buf + sizeof( buf ) );
		    length = buf + sizeof( buf ) - buffer - 1;
		}

	void	Set( int v, int digits )
		{
		    Set( v );

		    while( (int)length < digits )
			*--buffer = '0', ++length;
		}

# ifdef HAVE_INT64

		StrNum( long v ) { Set( (P4INT64)v ); }

		StrNum( P4INT64 v )
		{ Set( v ); }

	void	Set( P4INT64 v )
		{
		    buffer = Itoa64( v, buf + sizeof( buf ) );
		    length = buf + sizeof( buf ) - buffer - 1;
		}

# endif

    private:
		char buf[24];
} ;

class StrHuman : public StrPtr
{
	public:
	        StrHuman() {}
 
	        StrHuman( long v, int f = 1024 )
	        { Convert( (P4INT64)v, f ); }
 
	        StrHuman( P4INT64 v, int f = 1024 )
	        { Convert( v, f ); }
 
	        static char *Itoa64( P4INT64 v, char *endbuf, int f );
 
	private:
	        void	Convert( P4INT64 v, int f )
	        {
	            buffer = Itoa64( v, buf + sizeof( buf ), f );
	            length = buf + sizeof( buf ) - buffer - 1;
	        }

	    char buf[24];
} ;

# Change User Description Committed
#1 15071 alan_petersen Populate -o //guest/perforce_software/piper/...
//guest/alan_petersen/piper/....
//guest/perforce_software/piper/mac/R2.0/Perforce/p4api/Headers/strbuf.h
#2 13626 alan_petersen Copying using piper_mac_main2r2.0
#1 12962 alan_petersen Populate -o //guest/perforce_software/piper/mac/main/...
//guest/perforce_software/piper/mac/R2.0/....
//guest/perforce_software/piper/mac/main/Perforce/p4api/Headers/strbuf.h
#2 12961 alan_petersen Piper 2.0 Mega Update

New Features/Functionality
- Added help menu redirecting to URL.
- Added readonly property for creating new workspaces.
- Added html hyperlinks for Copy link functionality.
- Added functionality for managing Finder Favorite items in sidebar.
- Redesigned the way mapping is stored in Piper.
- First version of syncing finder sidebar items with workspace mapping.
- Small sorting improvements.
- Creating Projects directory inside users home folder.
- Adding Projects folder to finder sidebar item.
- Creating and removing symbolic links accordingly to mapped folders.
- Preventing duplicate names in symbolic links.
- Refreshing symbolic links on mapping change inside application.
- Storing workspace and server details in p4 configuration for other applications to use.
- Added contextual menu items for Finder integration.
- Added services menu for Adobe Illustrator integration.
- Keyboard shortcuts for Illustrator integration.
- Code refactoring and fixes for mapping issues.
- Added Finder functionality to edit all files in folder.
- Added user friendly message when editing a file using Finder outside the workspace.
- Implemented hidden automatic login when opening application using Finder integration.
- Logging to file in ~/Library/Logs
- Unified workspace and all files views to show both local and depot files and folders.
- Removed my workspace view references and logic.
- Editing unmapped files on server.
- First version of adding file to unmapped folders.
- Showing opened by and edit actions in column details for all depot files.
- Improved mappings functionality.
- Enabled same feature options for mapped and unmapped folders and files.
- Redesigned from scratch mapping and unmapping procedures for adding and removing files.
- Implemented cleaning workspace using new mapping functionality. Removed debug overlay coloring.
- Automated workspace creation
- Improvements in editing files already mapped to workspace.
- Implemented deleting remote files.
- Implemented first version of move operation for remote files.
- Removing last workspace information when disconnecting from workspace using app menu.
- Implemented editing and submitting using symbolic links in project folder. New finder menu service for symbolic links Show in Piper which acts like share link functionality.
- New icons for files and folders not tracked in the filesystem.
- Improvements in showing file using share link.
- Switched to new way of retrieving files in order to show user changes.
- Redesigned and implemented new functionality for chaining operations with mapping.
- Improvements and redesign of Edit/add actions to use new chaining logic . Fixed issue with file edit.
- Improvements in window showing when using services.
- Simplified file loading so the local files appears only when remote are also loaded.
- Improved deleting of untracked files to avoid mapping and marking for delete.
- Enabling simple copy paste and moving of remote and local files.
- Added abort for exception handling in order to force crashing application on critical failures
- Added custom exception handling for catching runtime errors to log and crash instead of continuing in unstable state.
- Changed file copying to use mark for add .
- Simplified and fixed responding file representations to mapping changes.

Bug Fixes
- Fixed crash when synchronizing.
- Fixed sync issue when downloading directory without file size information.
- Fixed issue with unread list crashing when file is not existing on disk.
- Fixed incorrect sync progress calculation.
- Removed relative path issues.
- Fixed many of case-sensitivity problems.
- Fixed deprecated methods and related issues in OS X 10.10.
- Fixed folder rename not updating in column view. Revised and fixed many potential problems from implicit casting.
- Fixed missing sync button on fast sync completion.
- Refreshing mapping on synchronization. Fixed symbolic links not appearing until app is restarted.
- Fixed latest crashing of autosync.
- Fixed loading indicator issues.
- Fixed and redesigned submit dialog to work correctly with Submit All Files option in Finder.
- Fixed multiple error messages on network outage. Redesigned showing errors in main window.
- Fixed opening random locations when using Finder integration.
- Fixed issue when panel was detached from parent window.
- Fixed bug when creating new workspace wouldn't store default settings.
- Fixed memory issues with network operations.
- Fixes in relogging mappings and file listing.
- Improvements in editing unmapped files.
- Fixed crash when adding file outside workspace.
- Fixed breadcrumbs control issue.
- Fixed issue with double parent folders when opening unmapped files.
- Fixed crashes on sync after mapping new files.
- Fixed issue with editing file using Finder
-- Merging code and additional fixes in add button functionality.
- Fixed unsync not working
- Fixed submit panel issue not selecting files with different name case.
- Fixed missing revert and sync to workspace actions in some cases.
- Fixed issue with Submit and Edit finder actions. Improvements in stability of finder integration.
- Fixed issue with unsubmitted folders breaking status of files inside.
- Fixed issue with added files not showing correct icon and status.
- Fixed bug with file edit resulting in a new directory named exactly like a file.
- Fixed issue with reloading of subpath resulting in untracked folders.
- Fixed mapping issue when result was always view mapping not relative.
- Fixed submit panel showing more than once.
- Fixed illustrator services not working.
- Fixed userdefaults preferences problem with workspace name being null.
- Fixed userdefaults keypath problem of dot-containing workspace names.
- Forcing recreating of browser to possibly prevent pre-10.10 errors with automatic workspace selection.
- Fixed adding file to depot not presenting correct icon.
- Fixed issues with reverting a file that was marked for add.
- Presenting error when trying to submit untracked files.
- Fixed issue when submit files service crashed when using unmapped files.
- Fixed file representation disappearing when removing file.
- Fixed issue with symlinks resolving working on 10.10 only. Issue related to workspace selection not showing.
- Fixed error panel method calls unavailable in Mac OS versions before 10.10. Issue related to hanging error panels.
- Fixed removing a local file resulting in action progress freezing.
- Fixed open file not working after edit.
- Fixing crash when mapping changed. Issue related to moving local file to unmapped folder and other similar cases.
#1 11252 alan_petersen Rename/move file(s)
//guest/perforce_software/piper/mac/Perforce/p4api/Headers/strbuf.h
#1 10744 alan_petersen Rename/move file(s)
//guest/perforce_software/piper/Perforce/p4api/Headers/strbuf.h
#1 8919 Matt Attaway Initial add of Piper, a lightweight Perforce client for artists and designers.