bug-commoncpp
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: new Path class


From: David Durham
Subject: Re: new Path class
Date: Thu, 21 Feb 2002 15:01:48 -0600
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.8) Gecko/20020204

I understand... Let me know of any changes I should make... Also, do you have a guess at when this might be able to go in? 1 month 3 months 1 yr?

Thanks,
  -- Davy

David Sugar wrote:

Right now we are in the process of validating Common C++ "2" for release very soon, so it may not be a good time to take this set of classes in at the moment. I will look at these though....

David Durham wrote:

Hi, I've created the Path class that I mentioned a few weeks back... This is actually my first code to ever release as open source... I have lots of other code that I plan to release (like my application which uses this class), but am just not ready yet. So I thought I'd start with this little thing. I just copied the license notices from another source file in the library and changed the copyright year... I didn't change the name... you can have it ;)

As far as the code goes: It has plenty of room for more functionality... I can imagine that there would be many other operations one might want to do on a path name than the operations I provided. I didn't put any doxygen formatted comments, but I did put a few simple comments that explains a little what each method does. Also, I was a little confused on how the rest of the CommonC++ library uses exceptions. (I, myself, am well versed in exceptions though) I saw that there was a define, "COMMON_STD_EXCEPTION" which is used.. If that define is not defined, it looks as if errors will go unreported at all... I also see throwing the object itself which seems a little strange... Anyway, what I did was just used exceptions throughout regardless of the define.. Change it if you want... One more thing about the exceptions... I found that if I derived from CommonC++'s Exception class that when I threw an exception constructed from an std::string it wouldn't retain the whole message or something... So I commented out the code for PathException and just typedefed it to std::runtime_error which is very similar to ost::Exception Finally, I only wrote this for linux, I could (if you want) make sure it works under Solaris if that's one of the 'supported' platforms, but I just need to know what defines would indicate the platform (I suppose I could look in config.h)

So... change whatever you want... I hope it's useful.. it has been to me in my sound editor application where I often need to manipulate the dirname basename or extention, check for existance, etc... of path names.

-- Davy


------------------------------------------------------------------------

// Copyright (C) 2002 Open Source Telecom Corporation.
//
// This program is free software; you can redistribute it and/or modify
// it under 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name Common C++.  If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for Common C++, it is your
// choice whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.

#ifndef CCXX_path_H_
#define CCXX_path_H_

#include <string>

#ifndef CCXX_CONFIG_H_
    #include <cc++/config.h>
#endif

//see BBB note below  #include <cc++/exception.h>

#ifndef WIN32
    #include <sys/types.h>
    #include <sys/stat.h>
#else
    #error unimplemented for win32 platform
#endif


// see BBB note below (this is what I did instead)
#include <stdexcept>
typedef runtime_error PathException;



#ifdef  CCXX_NAMESPACES
namespace ost {
#endif

/* BBB: I tried using this, but it wouldn't retain the whole exception message at the throw... it did if I used runtime_error from stdexcept
  so, did what's above instead instead ...
class PathException : public Exception
{
public:
    PathException(std::string str) : Exception(str) {};
};
*/



class Path
{
public:
static const char dirDelim; // either '\' or '/' depending on the platform

    Path(const std::string &path="");
    virtual ~Path();

    /*
        changes the path from what it was constructed with
    */
    void setPath(const std::string &path);

    /*
returns the path constructed with or the last one passed to setPath
    */
    const char *getPath() const;

    /*
        returns true iff the pathname exists and we could access it
    */
    bool Exists() const;

    /*
        possbily creates the path and/or updates its time(s) to current
    */
    bool Touch(bool canCreate=true,bool throwIfError=true) const;

    /*
        returns the absolute path resolved from a possibly relative path
    */
    const std::string RealPath() const;

    /*
returns the extension of the path name (i.e. returns "ext" for "/dir1/dir2/file.ext")
    */
    const std::string Extension() const;

    /*
returns just the directory name(s) part of the path (i.e. returns "/dir1/dir2" for "/dir1/dir2/file.ext")
    */
    const std::string DirName() const;
/* returns just the filename part of the path (i.e. returns "file.ext" for "/dir1/dir2/file.ext")
    */
    const std::string BaseName() const;

    /*
        returns the number of bytes allocated for the file
either returns 0 or throws an exception if it doesn't exist or wasn't accessible
    */
    long getSize(bool throwIfError=true) const;
    // many other things could be returned from the stat
    //time_t get ... Time() const;


private:
    char *path;
    bool exists;
    struct stat statBuf;

};

#ifdef  CCXX_NAMESPACES
}
#endif


#endif


------------------------------------------------------------------------

// Copyright (C) 2002 Open Source Telecom Corporation.
//
// This program is free software; you can redistribute it and/or modify
// it under 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name Common C++.  If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for Common C++, it is your
// choice whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.

#include "path.h"

/*
This was first written and tested under linux, however a few provisions have been made for a win32 port. Also, several functions used are probably only available under linux, i.e.
        realpath, dirname, basename
But there should be some equivalent under other unices, and implementation changes should be made when this file is compiled under these other platforms.
*/

#include <errno.h>

#ifndef WIN32
    #include <unistd.h>

    #include <fcntl.h>

    #include <limits.h>
    #include <stdlib.h>

    #include <string.h>

    #include <libgen.h>  // for basename and dirname
#else
    #error unimplemented for win32 platform
#endif


#ifdef  CCXX_NAMESPACES
namespace ost {
using namespace std;
#endif

#ifdef WIN32
    const char Path::dirDelim='\\';
#else
    const char Path::dirDelim='/';
#endif

Path::Path(const string &_path) :
    path(NULL),
    exists(false)
{
    setPath(_path);
}

Path::~Path()
{
    free(path);
}

void Path::setPath(const string &_path)
{
    if(_path.size()>=PATH_MAX)
throw PathException(string(__func__)+" -- path is >= than PATH_MAX -- '"+path+"'");

    if(path!=NULL)
        free(path);
    path=strdup(_path.c_str());

    if(stat(path,&statBuf)!=0)
    {
        exists=false;
        if(errno!=ENOENT)
throw PathException(string(__func__)+" -- error stat-ing path name -- '"+path+"' -- "+string(strerror(errno)));
    }
    else
        exists=true;
}

const char *Path::getPath() const
{
    return(path);
}

bool Path::Exists() const
{
    return(exists);
}

bool Path::Touch(bool canCreate,bool throwIfError) const
{
    if(canCreate)
    {
int fd = open (path, O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if (fd == -1)
{ if(throwIfError) throw PathException(string(__func__)+" -- error touching path name '"+path+"'-- "+string(strerror(errno)));
            else
                return(false);
        }
        close(fd);
    }
    else
    {
int fd = open (path, O_WRONLY | O_NONBLOCK | O_NOCTTY,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if (fd == -1 && errno!=ENOENT)
{ if(throwIfError) throw PathException(string(__func__)+" -- error touching path name '"+path+"'-- "+string(strerror(errno)));
            else
                return(false);
        }

        if(fd!=-1)
            close(fd);
    }

    return(true);
}

const string Path::RealPath() const
{
    if(!exists)
        return("");

    char resolvedPath[PATH_MAX];
    char *result=realpath(path,resolvedPath);
    if(result!=NULL)
        return(result);
    else
        return("");
}

const string Path::Extension() const
{
// find the right-most '.' which is also after the right-most dirDelim
    char *lastDot=strrchr(path,'.');
if(lastDot==NULL) // go ahead and bail if there wasn't even a '.' in the path
        return("");

    char *lastDirDelim=strrchr(path,dirDelim);

    if(lastDot>lastDirDelim)
        return(lastDot+1);
    else
        return("");
}

const string Path::DirName() const
{
    // make a copy because the function modifies the contents
    char tmp[PATH_MAX];
    strcpy(tmp,path);

    return(dirname(tmp));
}

const string Path::BaseName() const
{
    // make a copy because the function modifies the contents
    char tmp[PATH_MAX];
    strcpy(tmp,path);

    return(basename(tmp));
}


// many other things could possibly be returned from the stat
long Path::getSize(bool throwIfError) const
{
    if(!exists)
    {
        if(throwIfError)
throw(PathException(string(__func__)+" -- path did not exist or was inaccessible -- '"+path+"'"));
        else
            return(0);
    }

    return(statBuf.st_size);
}

//time_t get ... Path::Time() const;

#ifdef  CCXX_NAMESPACES
}
#endif


------------------------------------------------------------------------

#include <iostream>
#include <stdexcept>

#include "path.h"

using ost::Path;

int main()
{
    cout << "testing class Path\n";

    try
    {
        Path p;

        p.setPath("/etc/../etc/resolv.conf");

        cout << "path: " << p.getPath() << endl;

         cout << "exists: " << p.Exists() << endl;
         cout << "touch: " << p.Touch(false,false) << endl;
         cout << "RealPath: " << p.RealPath() << endl;
         cout << "Extension: " << p.Extension() << endl;
        cout << "DirName: " << p.DirName() << endl;
        cout << "BaseName: " << p.BaseName() << endl;
        cout << "getSize: " << p.getSize() << endl;
    }
    catch(exception &e)
    {
        cerr << "UNEXPECTED exception -- " << e.what() << endl;
    }
try
    {
        Path p;

        p.setPath("/etc/../etc/resolv.conf_pleasedontexist");

        cout << "path: " << p.getPath() << endl;

         cout << "exists: " << p.Exists() << endl;
         //cout << "touch: " << p.Touch(false,false) << endl;
         cout << "RealPath: " << p.RealPath() << endl;
         cout << "Extension: " << p.Extension() << endl;
        cout << "DirName: " << p.DirName() << endl;
        cout << "BaseName: " << p.BaseName() << endl;
        cout << "getSize: " << p.getSize(false) << endl;
    }
    catch(exception &e)
    {
        cerr << "UNEXPECTED exception -- " << e.what() << endl;
    }
    try
    {
        Path p;

        p.setPath("/etc/../etc/resolv.conf_pleasedontexist");

        cout << "path: " << p.getPath() << endl;

        cout << "getSize: " << p.getSize() << endl;
    }
    catch(exception &e)
    {
        cerr << "EXPECTED exception -- " << e.what() << endl;
    }
    return(0);
}





_______________________________________________
Bug-commoncpp mailing list
address@hidden
http://mail.gnu.org/mailman/listinfo/bug-commoncpp







reply via email to

[Prev in Thread] Current Thread [Next in Thread]