| /** \file filename.hpp . |
| ----------------------------------------------------------------------------- |
| |
| |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| |
| ----------------------------------------------------------------------------- |
| |
| \brief A filename class |
| |
| -------------------------------------------------------------------------- */ |
| |
| #ifndef __UIMA_FILENAME_HPP |
| #define __UIMA_FILENAME_HPP |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Interface dependencies */ |
| /* ----------------------------------------------------------------------- */ |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Implementation dependencies */ |
| /* ----------------------------------------------------------------------- */ |
| |
| #include "apr_file_info.h" |
| #include "apr_strings.h" |
| #include "apr_lib.h" |
| #include "uima/exceptions.hpp" |
| #include "uima/msg.h" |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Constants */ |
| /* ----------------------------------------------------------------------- */ |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Types / Classes */ |
| /* ----------------------------------------------------------------------- */ |
| |
| namespace uima { |
| namespace util { |
| |
| /** |
| * The class <tt> FilenameCl</tt> is used to maintain filenames with all of its |
| * (operating system specific) constituents: drive, path, base name and extension. |
| * \code |
| ??? |
| \endcode |
| */ |
| |
| class Filename { |
| public: |
| /** @name Constructors */ |
| /*@{*/ |
| /** create an empty filename */ |
| Filename(void); |
| /** create a filename based on a filename given as a C string */ |
| Filename(const char * filename); |
| |
| /** create a filename based on a path, a filename and an optional extension, |
| all given as C strings */ |
| Filename(const char * cpszPath, |
| const char * cpszFilename, |
| const char * cpszExtension = 0); |
| /** copy constructor */ |
| Filename(const Filename & filename); |
| /** destructor */ |
| ~Filename(void); |
| /*@}*/ |
| /** @name Assignment operations */ |
| /*@{*/ |
| /** assign new complete filename */ |
| Filename & operator = (const Filename & filename); |
| |
| |
| /** @name Properties */ |
| /*@{*/ |
| /** determine whether a file exists for filename on file system */ |
| bool isExistent(void) const; |
| |
| /** determine whether path has an absolute path specification */ |
| bool isAbsolute(void) const; |
| |
| /** return the size of this file in bytes. |
| \note If the file does not exist a size of 0 bytes is returned. */ |
| unsigned long getFileSize(void) const; |
| |
| /** @name Parts */ |
| /*@{*/ |
| /** return full filename as a C string pointer */ |
| const char * getAsCString(void) const { |
| return fname; |
| } |
| |
| operator const char* (void) const { |
| return fname; |
| } |
| |
| /** return the name part of this filename without the path but with the extension. |
| \note If the filename part is empty, the function returns a pointer |
| to an empty string, <em> not</em> a NULL pointer. */ |
| const char * getName(void) const; |
| |
| /** return the extension only, starting with the dot (e.g. ".so") |
| \note If there is no extension, the function returns a pointer |
| to an empty string, <em> not</em> a NULL pointer. */ |
| const char * getExtension(void) const; |
| |
| /** return the length of the complete filename */ |
| size_t getLength(void) const; |
| |
| /** assign a new entry from a path, optional filename and optional extension. */ |
| void setNew(const char * cpszPath, |
| const char * cpszName = 0, |
| const char * cpszExtension = 0); |
| |
| /** assign a new filename - keep current path. |
| filename may include extension or not */ |
| void setNewName(const char * cpszName); |
| |
| /** assign a new extension - keep current path and filename. |
| Specified extension must include the extension dot (".") */ |
| void setNewExtension(const char * cpszExtension); |
| |
| /** convert to an absolute name in native format with appropriate directory separators. */ |
| void normalizeAbsolute(void); |
| |
| /** convert to a name in native format with appropriate directory separators. */ |
| void normalize(void); |
| |
| /** copy path value to buffer pointed to by <tt> pszPath</tt>. |
| If a path does not exist for this object, <tt> pszPath</tt> is set to the empty string. |
| The path is returned with a terminating path separator character. */ |
| void extractPath(char * pszPath) const; |
| |
| /** copy base name (without path or extension) to buffer pointed to by <tt> pszBaseName</tt>. */ |
| void extractBaseName(char * pszBaseName) const; |
| |
| /** return TRUE if base names match (basic name part witout extension) */ |
| bool matchesBase(const Filename & crclFilename) const; |
| |
| /** search for file in a list of search paths and return TRUE if found */ |
| bool determinePath(const char* searchPaths); |
| |
| /*@}*/ |
| protected: |
| /* --- functions --- */ |
| private: |
| void createPool(void); |
| |
| apr_pool_t * fnPool; |
| char * fname; |
| } |
| ; /* Filename */ |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Implementation */ |
| /* ----------------------------------------------------------------------- */ |
| |
| /* ----------------------------------------------------------------------- */ |
| inline Filename::Filename(void) { |
| createPool(); |
| fname = NULL; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline Filename::Filename(const char* filename) { |
| createPool(); |
| fname = apr_pstrdup(fnPool, filename); |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline Filename::Filename(const char * cpszPath, const char * cpszName, |
| const char * cpszExtension) { |
| const char * fn; |
| apr_status_t rv; |
| |
| createPool(); |
| if ( cpszExtension != NULL ) |
| fn = apr_pstrcat( fnPool,cpszName,cpszExtension,NULL ); |
| else |
| fn = cpszName; |
| // Add directory separator if necessary & normalize etc. |
| rv = apr_filepath_merge(&fname, cpszPath, fn, APR_FILEPATH_NATIVE, fnPool); |
| if (rv != APR_SUCCESS) |
| fname = NULL; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline Filename::Filename(const Filename & filename) { |
| createPool(); |
| fname = apr_pstrdup(fnPool, filename.getAsCString()); |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline Filename::~Filename(void) { |
| if (fnPool != NULL) |
| apr_pool_destroy(fnPool); |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::createPool(void) { |
| if (apr_pool_create(&fnPool, NULL) != APR_SUCCESS) { |
| fnPool = NULL; |
| UIMA_EXC_THROW_NEW(ExcOutOfMemory, |
| UIMA_ERR_ENGINE_OUT_OF_MEMORY, |
| UIMA_MSG_ID_EXC_OUT_OF_MEMORY, |
| ErrorMessage(UIMA_MSG_ID_EXCON_CREATING_POOL_FOR_CLASS,"uima::util::Filename"), |
| ErrorInfo::unrecoverable); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline Filename & Filename::operator = (const Filename & filename) { |
| // Must make a copy since RHS & its pool may disappear |
| fname = apr_pstrdup(fnPool, filename.getAsCString()); |
| return *this; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline const char * Filename::getName(void) const { |
| if (fname == NULL) |
| return NULL; |
| else |
| return apr_filepath_name_get(fname); |
| // Probably returns a ptr to the end portion of fname so no memory allocated |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline const char * Filename::getExtension(void) const { |
| if (fname == NULL) |
| return NULL; |
| else { |
| const char* cpszExtn = strrchr(apr_filepath_name_get(fname), '.'); |
| return (cpszExtn!=NULL ? cpszExtn : ""); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline size_t Filename::getLength(void) const { |
| if (fname == NULL) |
| return 0; |
| else |
| return strlen(fname); |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::extractPath(char * pszPath) const { |
| if (fname == NULL) |
| *pszPath = '\0'; |
| else { |
| // Get length of path up to the filename, copy with trailing separator and append a 0 |
| unsigned long len = apr_filepath_name_get(fname) - fname; |
| strncpy(pszPath, fname, len); |
| pszPath[len] = '\0'; |
| } |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::extractBaseName(char * pszBaseName) const { |
| if (fname == NULL) |
| *pszBaseName = '\0'; |
| else { |
| // Get name after part and strip off extension (if any) |
| const char* cpszName = apr_filepath_name_get(fname); |
| const char* cpszExtn = strrchr(cpszName, '.'); |
| unsigned long len = cpszExtn==NULL ? strlen(cpszName) : cpszExtn - cpszName; |
| strncpy(pszBaseName, cpszName, len); |
| pszBaseName[len] = '\0'; |
| } |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline bool Filename::isExistent(void) const { |
| apr_finfo_t finfo; |
| apr_status_t rv; |
| |
| // Check if can determine type (file, directory, pipe ...) |
| rv = apr_stat(&finfo, fname, APR_FINFO_TYPE, fnPool); |
| return !(APR_STATUS_IS_ENOENT(rv)); |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline bool Filename::isAbsolute(void) const { |
| apr_status_t rv; |
| const char * root; |
| const char * fn = fname; |
| |
| // Modifies arg fn ... returns success if finds the root (?:\ on Windows) |
| rv = apr_filepath_root(&root, &fn, 0, fnPool); |
| return rv == APR_SUCCESS; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline bool Filename::matchesBase(const Filename & crclFilename) const { |
| const char * cpszName1, * cpszName2, * cpszExtn1, * cpszExtn2; |
| unsigned long len1, len2; |
| |
| if (fname == NULL) |
| return FALSE; |
| cpszName1 = apr_filepath_name_get(fname); |
| cpszExtn1 = strrchr(cpszName1, '.'); |
| len1 = cpszExtn1==NULL ? strlen(cpszName1) : cpszExtn1 - cpszName1; |
| |
| cpszName2 = crclFilename.getName(); |
| if (cpszName2 == NULL) |
| return FALSE; |
| cpszExtn2 = strrchr(cpszName2, '.'); |
| len2 = cpszExtn2==NULL ? strlen(cpszName2) : cpszExtn2 - cpszName2; |
| return (len1 == len2 && strncmp(cpszName1, cpszName2, len1) == 0); |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::setNew(const char * cpszPath, const char * cpszName, |
| const char * cpszExtension) { |
| // create new string from the 3 parts |
| // The path must end in a separator & the extension must start with a '.' |
| fname = apr_pstrcat( fnPool,cpszPath,cpszName,cpszExtension,NULL ); |
| return; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::setNewName(const char * cpszName) { |
| if (fname == NULL) |
| return; |
| // If new name is longer than old (or old had none) remove old |
| // and create a new entry by concatenating new filename. |
| char * pszName = (char*) apr_filepath_name_get(fname); |
| if (strlen(pszName) >= strlen(cpszName)) |
| strcpy( pszName,cpszName ); |
| else { |
| *pszName = '\0'; |
| fname = apr_pstrcat( fnPool,fname,cpszName,NULL ); |
| } |
| return; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::setNewExtension(const char * cpszExtension) { |
| const char * cpszName; |
| char * pszExtn; |
| |
| if (fname == NULL || cpszExtension == NULL) |
| return; |
| // If new extension not longer than old replace in place, otherwise |
| // remove old and create a new entry by concatenating new extension. |
| cpszName = apr_filepath_name_get(fname); |
| pszExtn = CONST_CAST(char *, strrchr(cpszName, '.')); |
| if ( pszExtn == NULL ) |
| fname = apr_pstrcat( fnPool,fname,cpszExtension,NULL ); |
| else { |
| if (strlen(pszExtn) >= strlen(cpszExtension)) |
| strcpy(pszExtn, cpszExtension); |
| else { |
| *pszExtn = '\0'; |
| fname = apr_pstrcat( fnPool,fname,cpszExtension,NULL ); |
| } |
| } |
| return; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline unsigned long Filename::getFileSize(void) const { |
| apr_finfo_t finfo; |
| apr_status_t rv; |
| |
| rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, fnPool); |
| return rv == APR_SUCCESS ? finfo.size : 0; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::normalizeAbsolute(void) { |
| apr_status_t rv; |
| char* newname; |
| |
| if (fname == NULL) |
| return; |
| rv = apr_filepath_merge(&newname, NULL, fname, APR_FILEPATH_NATIVE, fnPool); |
| if (rv == APR_SUCCESS) |
| fname = newname; |
| return; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline void Filename::normalize(void) { |
| apr_status_t rv; |
| char* newname; |
| |
| if (fname == NULL) |
| return; |
| rv = apr_filepath_merge(&newname, ".", fname, APR_FILEPATH_NATIVE, fnPool); |
| if (rv == APR_SUCCESS) |
| fname = newname; |
| return; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| inline bool Filename::determinePath(const char* searchPaths) { |
| apr_array_header_t * pathElts; |
| char * name; |
| |
| if (fname == NULL) |
| return FALSE; |
| // Drop any existing path |
| name = (char*) apr_filepath_name_get(fname); |
| apr_filepath_list_split(&pathElts, searchPaths, fnPool); // Cannot fail! |
| for ( int i = 0; i < pathElts->nelts; ++i ) { |
| apr_filepath_merge(&fname, ((char**)pathElts->elts)[i], name, APR_FILEPATH_NATIVE, fnPool); |
| if (isExistent()) |
| return TRUE; |
| } |
| return FALSE; |
| } |
| |
| } // namespace util |
| } // namespace uima |
| |
| #endif /* __UIMA_FILENAME_HPP */ |
| |
| /* <EOF> */ |