Commit 4c8b87dc authored by Dick Hollenbeck's avatar Dick Hollenbeck
Browse files

sch_dir_lib_source.* continued work

parent 2def9b3f
Loading
Loading
Loading
Loading
+88 −44
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ using namespace SCH;
#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <fcntl.h>
#include <errno.h>
#include <errno.h>
#include <assert.h>


#include <vector>
#include <vector>
using namespace std;
using namespace std;
@@ -159,13 +160,19 @@ static const char* endsWithRev( const char* start, const char* tail, char separa
    return 0;
    return 0;
}
}


static inline const char* endsWithRev( const STRING& aPartName, char separator )
{
    return endsWithRev( aPartName.c_str(),  aPartName.c_str()+aPartName.size(), separator );
}


// see struct BY_REV
// see struct BY_REV
bool BY_REV::operator() ( const STRING& s1, const STRING& s2 ) const
bool BY_REV::operator() ( const STRING& s1, const STRING& s2 ) const
{
{
    // avoid instantiating new STRINGs, and thank goodness that c_str() is const.
    // avoid instantiating new STRINGs, and thank goodness that c_str() is const.


    const char* rev1 = endsWithRev( s1.c_str(), s1.c_str()+s1.size(), '/' );
    const char* rev1 = endsWithRev( s1, '/' );
    const char* rev2 = endsWithRev( s2.c_str(), s2.c_str()+s2.size(), '/' );
    const char* rev2 = endsWithRev( s2, '/' );


    int rootLen1 =  rev1 ? rev1 - s1.c_str() : s1.size();
    int rootLen1 =  rev1 ? rev1 - s1.c_str() : s1.size();
    int rootLen2 =  rev2 ? rev2 - s2.c_str() : s2.size();
    int rootLen2 =  rev2 ? rev2 - s2.c_str() : s2.size();
@@ -259,7 +266,7 @@ STRING DIR_LIB_SOURCE::makeFileName( const STRING& aPartName )


    STRING  fileName = sourceURI + "/";
    STRING  fileName = sourceURI + "/";


    const char* rev = endsWithRev( aPartName.c_str(), aPartName.c_str()+aPartName.size(), '/' );
    const char* rev = endsWithRev( aPartName, '/' );


    if( rev )
    if( rev )
    {
    {
@@ -278,14 +285,14 @@ STRING DIR_LIB_SOURCE::makeFileName( const STRING& aPartName )
}
}




void DIR_LIB_SOURCE::readSExpression( STRING* aResult, const STRING& aFilename ) throw( IO_ERROR )
void DIR_LIB_SOURCE::readString( STRING* aResult, const STRING& aFileName ) throw( IO_ERROR )
{
{
    FILE_WRAP   fw = open( aFilename.c_str(), O_RDONLY );
    FILE_WRAP   fw = open( aFileName.c_str(), O_RDONLY );


    if( fw == -1 )
    if( fw == -1 )
    {
    {
        STRING  msg = strerror( errno );
        STRING  msg = strerror( errno );
        msg += "; cannot open(O_RDONLY) file " + aFilename;
        msg += "; cannot open(O_RDONLY) file " + aFileName;
        throw( IO_ERROR( msg.c_str() ) );
        throw( IO_ERROR( msg.c_str() ) );
    }
    }


@@ -296,7 +303,7 @@ void DIR_LIB_SOURCE::readSExpression( STRING* aResult, const STRING& aFilename )
    // sanity check on file size
    // sanity check on file size
    if( fs.st_size > (1*1024*1024) )
    if( fs.st_size > (1*1024*1024) )
    {
    {
        STRING msg = aFilename;
        STRING msg = aFileName;
        msg += " seems too big.  ( > 1 mbyte )";
        msg += " seems too big.  ( > 1 mbyte )";
        throw IO_ERROR( msg.c_str() );
        throw IO_ERROR( msg.c_str() );
    }
    }
@@ -310,7 +317,7 @@ void DIR_LIB_SOURCE::readSExpression( STRING* aResult, const STRING& aFilename )
    if( count != (int) fs.st_size )
    if( count != (int) fs.st_size )
    {
    {
        STRING  msg = strerror( errno );
        STRING  msg = strerror( errno );
        msg += "; cannot read file " + aFilename;
        msg += "; cannot read file " + aFileName;
        throw( IO_ERROR( msg.c_str() ) );
        throw( IO_ERROR( msg.c_str() ) );
    }
    }


@@ -358,42 +365,42 @@ DIR_LIB_SOURCE::~DIR_LIB_SOURCE()
void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory )
void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory )
    throw( IO_ERROR )
    throw( IO_ERROR )
{
{
    PN_ITER limit = aCategory.size() ?
                        partnames.lower_bound( aCategory + char( '/' + 1 ) ) :
                        partnames.end();

    PN_ITER it    = aCategory.size() ?
                        partnames.lower_bound( aCategory + "/" ) :
                        partnames.begin();

    aResults->clear();
    aResults->clear();


    if( aCategory.size() )
    if( useVersioning )
    {
    {
        STRING  lower = aCategory + "/";
        STRING  partName;
        STRING  upper = aCategory + char( '/' + 1 );

        PART_CACHE::const_iterator limit = partnames.upper_bound( upper );


        for( PART_CACHE::const_iterator it = partnames.lower_bound( lower );  it!=limit;  ++it )
        while( it != limit )
        {
        {
            /*
            const char* rev   = endsWithRev( *it, '/' );
            const char* start = it->c_str();
            size_t      len   = it->size();


            if( endsWithRev( start, start+len, '/' ) )
            // all cached partnames have a rev string in useVersioning mode
                continue;
            assert( rev );
            */


            aResults->push_back( *it );
            // partName is substring which omits the rev AND the rev separator
            partName.assign( *it, 0, rev - it->c_str() - 1 );

            aResults->push_back( partName );

            // skip over all other versions of the same partName.
            it = partnames.lower_bound( partName + char( '/' + 1 ) );
        }
        }

    }
    }

    else
    else
    {
    {
        for( PART_CACHE::const_iterator it = partnames.begin();  it!=partnames.end();  ++it )
        while( it != limit )
        {
            aResults->push_back( *it++ );
            /*
            const char* start = it->c_str();
            size_t      len   = it->size();

            if( !endsWithRev( start, start+len, '/' ) )
                continue;
            */

            aResults->push_back( *it );
        }
    }
    }
}
}


@@ -401,25 +408,53 @@ void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& a
void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev )
void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev )
    throw( IO_ERROR )
    throw( IO_ERROR )
{
{
    STRING  partname = aPartName;
    STRING  fileName;
    STRING  partName = aPartName;   // appended with aRev too if not empty
    const char* rev  = endsWithRev( partName, '/' );


    if( aRev.size() )
    if( aRev.size() )
        partname += "/" + aRev;
    {
        if( rev )   // a supplied rev replaces any in aPartName
            partName.resize( rev - partName.c_str() - 1 );

        partName += "/" + aRev;


    PART_CACHE::const_iterator it = partnames.find( partname );
        rev = endsWithRev( partName, '/' );
    }

    // partName is the exact part name we need here, or if rev is NULL,
    // then look for the highest numbered revision.

    if( rev )
    {
        PN_ITER it = partnames.find( partName );


        if( it == partnames.end() )    // part not found
        if( it == partnames.end() )    // part not found
        {
        {
        partname += " not found.";
            partName += " not found.";
        throw IO_ERROR( partname.c_str() );
            throw IO_ERROR( partName.c_str() );
        }

        readString( aResult, makeFileName( partName ) );
    }
    }
    else
    {
        STRING search = partName + '/';


    // create a fileName for the sweet string
        // no rev on partName string.  First the first, which should be
    STRING  fileName = makeFileName( aPartName );
        // the highnest numbered rev because of BY_REV compare method.
        PN_ITER it = partnames.upper_bound( search );


    // @todo what about aRev?, and define the public API wrt to aRev better.
        // verify that this one that is greater than partName is a match and not
        // some unrelated name that is larger.
        if( it == partnames.end() || it->compare( 0, search.size(), search ) != 0 )
        {
            partName += " rev not found.";
            throw IO_ERROR( partName.c_str() );
        }


    readSExpression( aResult, fileName );
        readString( aResult, makeFileName( *it ) );
    }
}
}




@@ -539,6 +574,8 @@ int main( int argc, char** argv )


    try
    try
    {
    {
        STRINGS::const_iterator  pn;

//        DIR_LIB_SOURCE  uut( argv[1] ? argv[1] : "", "" );
//        DIR_LIB_SOURCE  uut( argv[1] ? argv[1] : "", "" );
        DIR_LIB_SOURCE  uut( argv[1] ? argv[1] : "", "useVersioning" );
        DIR_LIB_SOURCE  uut( argv[1] ? argv[1] : "", "useVersioning" );


@@ -555,6 +592,13 @@ int main( int argc, char** argv )


        uut.ReadParts( &sweets, partnames );
        uut.ReadParts( &sweets, partnames );


        printf( "\nSweets for Category = 'Category' parts:\n" );
        pn = partnames.begin();
        for( STRINGS::const_iterator it = sweets.begin();  it!=sweets.end();  ++it, ++pn )
        {
            printf( " %s: %s", pn->c_str(), it->c_str() );
        }

        // fetch the part names for ALL categories.
        // fetch the part names for ALL categories.
        uut.GetCategoricalPartNames( &partnames );
        uut.GetCategoricalPartNames( &partnames );


@@ -567,7 +611,7 @@ int main( int argc, char** argv )
        uut.ReadParts( &sweets, partnames );
        uut.ReadParts( &sweets, partnames );


        printf( "\nSweets for ALL parts:\n" );
        printf( "\nSweets for ALL parts:\n" );
        STRINGS::const_iterator pn = partnames.begin();
        pn = partnames.begin();
        for( STRINGS::const_iterator it = sweets.begin();  it!=sweets.end();  ++it, ++pn )
        for( STRINGS::const_iterator it = sweets.begin();  it!=sweets.end();  ++it, ++pn )
        {
        {
            printf( " %s: %s", pn->c_str(), it->c_str() );
            printf( " %s: %s", pn->c_str(), it->c_str() );
+6 −4
Original line number Original line Diff line number Diff line
@@ -77,10 +77,12 @@ class DIR_LIB_SOURCE : public LIB_SOURCE
    /// and some of which may have legal "revN[N..]" type strings.
    /// and some of which may have legal "revN[N..]" type strings.
    PART_CACHE          partnames;
    PART_CACHE          partnames;


    typedef PART_CACHE::const_iterator PN_ITER;

    /// categories which we expect to find in the set of @a partnames
    /// categories which we expect to find in the set of @a partnames
    NAME_CACHE          categories;
    NAME_CACHE          categories;


    std::vector<char>   readBuffer;     ///< used by readSExpression()
    std::vector<char>   readBuffer;     ///< used by readString()


    /**
    /**
     * Function cache
     * Function cache
@@ -109,10 +111,10 @@ class DIR_LIB_SOURCE : public LIB_SOURCE
    bool makePartName( STRING* aPartName, const char* aEntry, const STRING& aCategory );
    bool makePartName( STRING* aPartName, const char* aEntry, const STRING& aCategory );


    /**
    /**
     * Function readSExpression
     * Function readString
     * reads an s-expression into aResult.  Candidate for virtual function later.
     * reads a Sweet string into aResult.  Candidate for virtual function later.
     */
     */
    void readSExpression( STRING* aResult, const STRING& aNameSpec ) throw( IO_ERROR );
    void readString( STRING* aResult, const STRING& aFileName ) throw( IO_ERROR );


    /**
    /**
     * Function cacheOneDir
     * Function cacheOneDir
+2 −1
Original line number Original line Diff line number Diff line
@@ -90,7 +90,8 @@ protected: ///< derived classes must implement
     * Function ReadParts
     * Function ReadParts
     * fetches the s-expressions for each part given in @a aPartNames, into @a aResults,
     * fetches the s-expressions for each part given in @a aPartNames, into @a aResults,
     * honoring the array indices respectfully.
     * honoring the array indices respectfully.
     * @param aPartNames is a list of part names, one name per list element.
     * @param aPartNames is a list of part names, one name per list element.  If a part name
     *        does not have a version string, then the most recent version is fetched.
     * @param aResults receives the s-expressions
     * @param aResults receives the s-expressions
     */
     */
    virtual void ReadParts( STRINGS* aResults, const STRINGS& aPartNames )
    virtual void ReadParts( STRINGS* aResults, const STRINGS& aPartNames )