home *** CD-ROM | disk | FTP | other *** search
- /*
- ADSSTRNG.CPP -
-
- This file:
-
- Defines class ADS_STRING.
-
- (C) Copyright 1988-1994 by Autodesk, Inc.
-
- This program is copyrighted by Autodesk, Inc. and is licensed
- to you under the following conditions. You may not distribute
- or publish the source code of this program in any form. You
- may incorporate this code in object form in derivative works
- provided such derivative works are (i.) are designed and
- intended to work solely with Autodesk, Inc. products, and
- (ii.) contain Autodesk's copyright notice "(C) Copyright
- 1988-1994 by Autodesk, Inc."
-
- AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
- AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MER-
- CHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
- DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
- UNINTERRUPTED OR ERROR FREE.
-
- */
- #include "adsinc.h"
-
- /******************************************************************************
- * *
- * ADS_STRING class *
- * *
- ******************************************************************************/
- //-----------------------------------------------------------------------------
- size_t ADS_STRING::initial_capac = 63;
- size_t ADS_STRING::resize_inc = 64;
- size_t ADS_STRING::max_waste = 63;
-
- //-----------------------------------------------------------------------------
- ADS_STRING& ADS_STRING::Assign( const ADS_STRING &src
- , size_t origin
- , size_t how_long )
- {
- if( origin != 0 || how_long < src.Length() )
- {
- size_t loc = min( origin,src.Length() );
- size_t len = min( src.Length() - loc, how_long );
- STRING_REF *temp = new STRING_REF( src.CString() + loc, len, 0, 0, 0);
- if( p->RemoveReference() == 0 )
- {
- delete p;
- }
- p = temp;
- }
- else
- {
- src.p->AddReference();
- if( p->RemoveReference() == 0 )
- {
- delete p;
- }
- p = src.p;
- }
- return *this;
- }
-
- //-----------------------------------------------------------------------------
- ADS_STRING& ADS_STRING::Append( const ADS_STRING &src
- , size_t orig
- , size_t n )
- {
- CopyOnWrite();
- size_t loc = min( orig, src.Length() );
- size_t len = min( src.Length() - loc, n );
- p->Splice( p->nchars, 0, src.CString(), len );
- return *this;
- }
-
- /******************************************************************************
- * *
- * STRING_REF *
- * *
- ******************************************************************************/
- //-----------------------------------------------------------------------------
- void STRING_REF::GrowTo( size_t n )
- {
- capacity = n;
- array = ( char * )realloc( array, capacity +1 );
- ASSERT( array != 0 );
- }
-
- //-----------------------------------------------------------------------------
- STRING_REF::STRING_REF( const char *str1, size_t count1
- , const char *str2, size_t count2
- , size_t extra ) : ADS_REFERENCE( 1 )
- {
- nchars = count1 + count2;
- capacity = RoundCapacity( nchars + extra );
- array = new char[ capacity + 1 ];
- ASSERT( array != NULL );
- memcpy( array, str1, count1 );
- memcpy( array + count1, str2, count2 );
- array[ count1 + count2 ] = '\0';
- }
-
- //-----------------------------------------------------------------------------
- void STRING_REF::Splice( size_t start
- , size_t extent
- , const char *cp
- , size_t num_char )
- {
- char *destarray; // Will point to final destination array
-
- // Final length:
- size_t tot = nchars + num_char - extent;
- // Final capacity:
- size_t newCapac = RoundCapacity( tot );
-
- // Resize if necessary:
- if( newCapac > capacity )
- {
- GrowTo( newCapac ); // Grew
- destarray = array; // Record what will be the final
- // destination array
- }
- else if( capacity - newCapac > ADS_STRING::GetMaxWaste() )
- {
- // Shrunk. destarray will point to brand new memory
- destarray = new char[ newCapac + 1 ];
- if( array == 0 )
- {
- ASSERT( "Outta of it" != NULL );
- }
- if( start )
- {
- memcpy( destarray, array, start ); // Copy beginning of string.
- }
- capacity = newCapac;
- }
- else
- {
- destarray = array; // string capacity stayed the same. Reuse old array.
- }
-
- //
- // Copy the end of the string. This will be necessary if new memory is
- // involved, or if the size of the replacing substring does not match
- // the original extent.
- //
- if( destarray != array || num_char != extent )
- {
- memmove( destarray + start + num_char
- , array + start + extent
- , nchars - start - extent );
- }
-
- // Copy middle of string:
- if( num_char )
- {
- if( cp )
- {
- memmove( destarray + start, cp, num_char ); /* NB: memmove() necessary */
- }
- else
- {
- memset( destarray + start, ' ', num_char );
- }
- }
-
- nchars = tot;
- destarray[nchars] = '\0';
-
- if( destarray != array )
- {
- free(array);
- array = destarray;
- }
- }
-
- //-----------------------------------------------------------------------------
- size_t STRING_REF::RoundCapacity( size_t nc )
- {
- size_t init_cap = ADS_STRING::GetInitialCapacity();
- size_t resize_size = ADS_STRING::GetResizeIncrement();
- return ( ( nc - init_cap + resize_size - 1 ) / resize_size ) * resize_size
- + init_cap ;
- }
-
- #ifdef TEST_ADSSTRNG
-
- #include <iostream.h>
-
- void Test( ADS_STRING& src, ADS_STRING* dst )
- {
- *dst = src;
- }
-
- #ifdef main
- #undef main
- #endif
-
- void main()
- {
- ADS_STRING mystring( "Hello, my dear" );
- ADS_STRING *foo = new ADS_STRING;
- *foo = mystring;
- cout << mystring << endl;
- cout << *foo << endl;
- mystring += mystring + *foo;
- delete foo;
- cout << mystring << endl;
-
- ADS_STRING bar("Hello, ");
- bar += "my dear";
- cout << bar << endl;
- if ( bar == mystring )
- {
- cout << "Passed!" << endl;
- }
- else
- {
- cout << "Failed!" << endl;
- }
- }
-
- #endif
-