file.h

Go to the documentation of this file.
00001 #ifndef FILE_HEADER_INCLUDED
00002 #define FILE_HEADER_INCLUDED
00003 
00004 //
00005 // Copyright 2002, Lowell Boggs Jr.
00006 //
00007 // This file or directory, containing source code for a computer program,
00008 // is Copyrighted by Lowell Boggs, Jr.  987 Regency Drive, Lewisville
00009 // TX (USA), 75067.  You may use, copy, modify, and distribute this
00010 // source file without charge or obligation so long as you agree to
00011 // the following:
00012 //
00013 //  1.  You must indemnify Lowell Boggs against any and all financial
00014 //      obligations caused by its use, misuse, function, or malfunction.
00015 //      Further, you acknowledge that there is no warranty of any kind,
00016 //      whatsoever.
00017 //
00018 //  2.  You agree not to attempt to patent any portion of this original
00019 //      work -- though you may attempt to patent your own extensions to
00020 //      it if you so choose.
00021 //
00022 //  3.  You keep this copyright notice with the file and all copies
00023 //      of the file and do not change it anyway except language translation.
00024 //
00025 // You are responsible for enforcing your own compliance with these
00026 // conditions and may not use this source file if you cannot agree to the
00027 // above terms and conditions.
00028 
00029 #include <string>
00030 #include <string.h>
00031 #include <memory>
00032 #include <sys/types.h>
00033 #include <time.h>
00034 #include <sys/stat.h>
00035 #include <iostream>
00036 #include <list>
00037 #include <set>
00038 #include <memory>
00039 #include <cxxtls/strtool.h>
00040 
00041 namespace cxxtls
00042 {
00043 
00049 
00050 //========================================================================================
00051 //========================================================================================
00052 //========================================================================================
00053 
00054 struct FileTime
00062 {
00063   int year;     
00064   int month;    
00065   int day;      
00066   int hour;     
00067   int minute;   
00068   int second;   
00069 
00070   friend bool operator<(FileTime const &l, FileTime const &r)
00071   {
00072       if(l.year < r.year)
00073          return true;
00074       else
00075       if(l.year > r.year)
00076         return false;
00077 
00078 
00079       if(l.month < r.month)
00080          return true;
00081       else
00082       if(l.month > r.month)
00083         return false;
00084 
00085 
00086       if(l.day < r.day)
00087          return true;
00088       else
00089       if(l.day > r.day)
00090         return false;
00091 
00092 
00093       if(l.hour < r.hour)
00094          return true;
00095       else
00096       if(l.hour > r.hour)
00097         return false;
00098 
00099 
00100       if(l.minute < r.minute)
00101          return true;
00102       else
00103       if(l.minute > r.minute)
00104         return false;
00105 
00106 
00107       if(l.second < r.second)
00108          return true;
00109       else
00110       if(l.second > r.year)
00111         return false;
00112 
00113 
00114       return false;
00115   }
00116 
00117 
00118   operator std::string() const;
00120 
00121   friend std::ostream& operator<< (std::ostream& o, FileTime const &r)
00123   {
00124     return o << std::string(r);
00125   }
00126 
00127   FileTime()       
00128   : year(0),
00129     month(0),
00130     day(0),
00131     hour(0),
00132     minute(0),
00133     second(0)
00134   {
00135   }
00136 
00137   FileTime(struct tm const *);     
00138 
00139   FileTime(std::string s)          
00140   : year(0),
00141     month(0),
00142     day(0),
00143     hour(0),
00144     minute(0),
00145     second(0)
00146   {
00147     construct_from_string(s);
00148   }
00149 
00150   bool construct_from_string(std::string s);
00176 
00177   std::string short_string() const;
00181 };
00182 
00183 //========================================================================================
00184 //========================================================================================
00185 //========================================================================================
00186 
00187 struct FileMode
00213 {
00214   int mode;  
00215 
00216 
00217 
00218   int os_mode() const;  
00219 
00220 
00221 
00222 
00223   operator std::string() const;   
00224 
00225   friend std::ostream& operator<< (std::ostream& o, FileMode const &r)
00229   {
00230     return o << std::string(r);
00231   }
00232 
00233   FileMode(): mode(0) {}   
00234 
00235   FileMode(int m);
00241 
00242   FileMode(char const*s)
00250   {
00251     construct_from_string(s);
00252   }
00253 
00254   FileMode(std::string s)
00258   {
00259     construct_from_string(s.c_str());
00260   }
00261 
00262   void construct_from_string(char const *string);
00267 
00268   void construct_from_string(std::string const& s)
00273   {
00274     construct_from_string(s.c_str());
00275   }
00276 
00277 
00278   enum bit_name
00280   {
00281        link     = 010000,  
00282        directory= 004000,  
00283        set_uid  = 002000,
00284        set_gid  = 001000,
00285 
00286        user_readable   = 000400,  
00287        user_writeable  = 000200,  
00288        user_executable = 000100,
00289 
00290        group_readable  = 000040,
00291        group_writeable = 000020,
00292        group_executable= 000010,
00293 
00294        world_readable   = 000004,
00295        world_writeable  = 000002,
00296        world_executable = 0000001
00297   };
00298 
00299   bool is_dir() const { return mode & directory; }
00307 
00308   bool is_link() const { return mode & link; }
00322 
00323 
00324   void unpackPermissions(std::string &userMode, std::string &groupMode, std::string &worldMode);
00327 
00328   void packPermissions(std::string const &userMode, std::string const &groupMode, std::string const &worldMode);
00333 
00334    bool permStringValid(std::string const &string);
00340 };
00341 
00342 //========================================================================================
00343 //========================================================================================
00344 //========================================================================================
00345 
00346 struct FileStatus
00350 {
00351    typedef off_t file_size_t;   
00352 
00353    FileMode     mode;           
00354    file_size_t  size;           
00355    FileTime     time;           
00356    int          owner_id;       
00357    int          group_id;       
00358 
00359    FileStatus()
00360    : mode(),
00361      size(0),
00362      time(),
00363      owner_id(0),
00364      group_id(0)
00365    {
00366        // this constructor is needed to prevent a gcc warning that some members of the
00367        // class are uninitialized
00368    }
00369 
00370    std::string convert_to_string(bool resolve_id_names=false) const;
00377 
00378    operator std::string() const
00381    {
00382      return convert_to_string();
00383    }
00384 
00385    friend std::ostream& operator<< (std::ostream& o, FileStatus const &r)
00389    {
00390      return o << std::string(r);
00391    }
00392 
00393    static std::string id2string(int id);
00399 
00400    static std::string group2string(int id);  // use this to convert group_id to strings
00406 
00407 };
00408 
00409 //========================================================================================
00410 //========================================================================================
00411 //========================================================================================
00412 
00413 class FileContents
00419 {
00420 private:
00421 
00422    char *begin_;         
00423    char *end_;           
00424    char const *error_;   
00425 
00426 public:
00427 
00428    FileContents()        
00429    : begin_(0),
00430      end_(0),
00431      error_("not read yet")
00432    {
00433    }
00434 
00435    ~FileContents()       
00436    {
00437      delete [] begin_;
00438    }
00439 
00440    typedef char *iterator;               
00441    typedef char const *const_iterator;   
00442 
00443    const_iterator begin() const { return begin_; }
00447 
00448    const_iterator end()   const { return end_;   }
00452 
00453    iterator begin() { return begin_; } 
00454    iterator end()   { return end_;   } 
00455 
00456    void reserve(long bytes) { delete [] begin_; begin_ = new char[bytes]; end_ = begin_ + bytes; }
00460 
00461    long size() const { return end_ - begin_; }  
00462 
00463    char const *error() const { return error_; }
00467 
00468    void set_error(char const *msg) { error_ = msg ; }
00472 
00473    void clear_error() { error_ = 0; }
00476 
00477    bool ok() const { return error_ == 0; }
00480 
00481 
00482 };
00483 
00484 //========================================================================================
00485 //========================================================================================
00486 //========================================================================================
00487 
00488 
00489 
00490 class FileName
00515 {
00516 public:
00517 
00518   struct FileNameSorter
00519   {
00520      bool operator()(FileName const &a, FileName const &b) const 
00521           { return  0 > StrTool:: compareInsensitive(a,b); }
00522   };
00523 
00524   typedef std::set<FileName, FileNameSorter> sorted_names_t; 
00525 
00526   typedef std::string              rep_t;          
00527   typedef FileStatus::file_size_t  off_t;          
00528   typedef rep_t::const_iterator    const_iterator; 
00529   typedef rep_t::iterator          iterator;       
00530 
00531 private:
00532   rep_t             impl_;   
00533 
00534 public:
00535 
00536   operator std::string       &()            { return impl_; }         
00537   operator std::string const &() const      { return impl_; }         
00538   const_iterator              begin() const { return impl_.begin(); } 
00539   const_iterator              end()   const { return impl_.end();   } 
00540   size_t                      size()  const { return impl_.size(); }  
00541   iterator                    begin()       { return impl_.begin(); } 
00542   iterator                    end()         { return impl_.end();   } 
00543   char const *                c_str() const { return impl_.c_str(); } 
00544   char const *                data()  const { return impl_.data();  } 
00545 
00546   char operator[](size_t i) const { return impl_[i]; }   
00547 
00548 
00549   char &operator[](size_t i) { return impl_[i]; }   
00550 
00551 
00552   void erase(iterator a)                { impl_.erase(a);    } 
00553   void erase(iterator a, iterator b)    { impl_.erase(a,b);  } 
00554   void erase(size_t o, size_t l)        { impl_.erase(o,l);  } 
00555   void erase(size_t o)                  { impl_.erase(o);    } 
00556   void insert(iterator a, char c)       { impl_.insert(a,c); } 
00557   void insert(size_t o, char const *s)  { impl_.insert(o,s); } 
00558   void insert(size_t o, rep_t const &s) { impl_.insert(o,s); } 
00559   bool empty() const                    { return impl_.empty(); } 
00560 
00561   bool operator<( std::string const &rhs ) const
00563   {
00564     return impl_ < rhs; 
00565   }
00566 
00567   rep_t substr(size_t s, size_t l) const 
00569   { 
00570       return impl_.substr(s,l); 
00571   } 
00572 
00573   FileName &operator+= (char const *p)  
00574   {
00575      std::string *me = &impl_;
00576 
00577      *me += p;
00578 
00579      return *this;
00580  
00581   }
00582 
00583   FileName &operator+= (char c) 
00584   {
00585      std::string *me = &impl_;
00586 
00587      *me += c;
00588 
00589      return *this;
00590 
00591   }
00592 
00593 
00594   FileName &operator+= (std::string const &r) 
00595   {
00596      std::string *me = &impl_;
00597 
00598      *me += r;
00599 
00600      return *this;
00601 
00602   }
00603 
00604 
00605   FileName()  
00606   {
00607   }
00608 
00609   FileName(char const *r)  
00610   : impl_(r)
00611   {
00612   }
00613 
00614   FileName(std::string const &r) 
00615   : impl_(r)
00616   {
00617   }
00618 
00619   FileName(FileName const &r) 
00620   : impl_(r)
00621   {
00622   }
00623 
00624 
00625   FileName expand_tildes() const;
00642 
00643   rep_t basename(bool remove_extension=false) const;
00646 
00647   rep_t extension() const;
00650 
00651   rep_t dirname()  const;
00654 
00655   void  convert_to_absolute_path();
00658 
00659   bool  is_syntactically_valid() const;
00661 
00662   bool  exists() const;
00664 
00665   bool  is_dir() const;                     
00666   bool  is_executable() const;              
00667   bool  is_writeable() const;               
00668   bool  is_readable() const;                
00669   bool  is_createable() const;              
00670   bool  is_absolute_path() const;           
00671   bool  is_root_dir() const;                
00672 
00673   FileMode file_mode() const;               
00674   off_t    file_size() const;               
00675 
00676   bool  file_time(FileTime *t) const;       
00682 
00683   bool  file_stat(FileStatus* s, bool l=false) const;
00684 
00700 
00701   bool  matches(char const *pattern) const; 
00707 
00708   bool  matches(rep_t pattern) const        
00710   { 
00711     return matches(pattern.c_str()); 
00712   }
00713 
00714 
00715   FileName readlink(int *returnedMode=0) const; 
00733 
00734 
00735   bool remove() const;                      
00737 
00738   bool chmod(FileMode) const;
00742 
00743 
00744   bool copy(FileName const &destination) const;
00754 
00755   bool rename(FileName const &destination) const;
00762 
00763   bool mkdir(FileMode m=FileMode(" drwxrwxrwx") ) const;
00769 
00770   bool rmdir() const;
00773 
00774   void convertToDirectorySearchPattern(std::string const &pattern)
00785   {
00786       convertToDirectorySearchPattern(pattern.c_str());
00787   }
00788   
00789   void convertToDirectorySearchPattern(char const *pattern="*");
00791 
00792 
00793   static int find_matching(char const     *pattern, 
00794                            sorted_names_t *matches, 
00795                            int             options=0
00796                           );
00828 
00829 
00830   static int find_matching(rep_t           pattern, 
00831                            sorted_names_t* l, 
00832                            int             options=0
00833                           )
00835   { 
00836     return find_matching(pattern.c_str(), l, options); 
00837   }
00838 
00839   void slurp(FileContents *f) const ;
00843 
00844   bool write(std::string const &file_contents, bool binary_mode=true);
00860 
00861   bool write(char const *begin, char const *end, bool binary_mode=true);
00872     //   @return true if a failure occurs.  See errno.
00874 
00875   size_t slurp(std::list<std::string> *lines) const;
00882 
00883   struct accumulate_lines
00895   {
00896     virtual ~accumulate_lines(){}
00900 
00901     virtual void push_back(std::string const &new_line) = 0;
00905 
00906     virtual std::string &back() = 0;
00911 
00912     virtual void setBackHasCR(bool flag){ }
00919            
00920   };
00921 
00922   std::string read_lines(accumulate_lines &accum, size_t *line_count_ptr=0, bool removeCR=false);
00962 
00963   template<class Container>
00964   struct Accum
00965   : public accumulate_lines
00976     {
00977       Container& container_;
00978 
00979       Accum(Container& container)
00980       : container_(container)
00981       {
00982       }
00983 
00984       void push_back(std::string const &s) { container_.push_back(s); }
00985       std::string & back()                 { return container_.back();}
00986 
00987     };
00988 
00989   template<class Container>
00990   std::string read_file(Container &container, size_t* line_count_ptr=0)
01015   {
01016 
01017     Accum<Container> accum(container);
01018 
01019     return read_lines( accum, line_count_ptr );
01020 
01021   }
01022 
01023 
01024   static FileName mktemp(FileName dir="./");
01048 
01049 
01050   static char PATH_separator;  
01051 
01052 
01053 
01054                         
01055   struct is_separator
01062   {
01063     bool operator() (char c) const
01064     {
01065       return c == FileName::PATH_separator;
01066     }
01067   };
01068 
01069   static FileName find_executable(std::string progname, std::string path="");
01089 
01090   static FileName find_file_in_path(std::string filename, std::string path="");
01100 
01101   std::string shorten(int max_chars) const;
01107 
01108   FileName operator+(FileName const &r ) const 
01109   {
01110     std::string const &me = *this;
01111     std::string const &other = r;
01112 
01113 
01114     return FileName(me + other);
01115   }
01116 
01117   FileName operator+(char const* r) const
01119   {
01120     std::string const &me = *this;
01121 
01122 
01123     return FileName(me + r);
01124   }
01125 
01126   FileName operator+(std::string const &r) const
01128   {
01129     std::string const &me = *this;
01130 
01131 
01132     return FileName(me + r);
01133   }
01134 
01135   template<class T>
01136   FileName &operator=(T const &rhs)
01138   {
01139      impl_ = rhs;
01140 
01141      return *this;
01142   }
01143 
01144 
01145 
01146   friend std::string operator+(std::string const &lhs, FileName const&rhs)
01149   {
01150     return lhs + (std::string const &)(rhs);
01151   }
01152 
01153   friend std::string operator+(char const *lhs, FileName const&rhs)
01156   {
01157     return lhs + (std::string const &)(rhs);
01158   }
01159 
01160   static int compareIgnoringPathSeparatorDifferences(char const *l,
01161                                                      char const *r,
01162                                                      size_t      lsize,
01163                                                      size_t      rsize
01164                                                     )
01169   {
01170 
01171 
01172      size_t smaller = lsize < rsize ? lsize : rsize;
01173 
01174      for(size_t i = 0; i < smaller; ++i)
01175      {
01176          char lc = l[i];
01177          char rc = r[i];
01178 
01179          if(lc == '\\')
01180             lc = '/';
01181 
01182          if(rc == '\\')
01183            rc = '/';
01184 
01185          if(lc < rc)
01186             return -1;
01187 
01188          if(lc > rc)
01189             return 1;
01190 
01191          // the characters are equal, so keep comparing.
01192 
01193 
01194      }
01195 
01196      // if we get here, the two strings are euqal up in the range [0..smaller-1].
01197      // which represents the common sub-range of the the two strings.
01198 
01199      if(lsize < rsize)
01200         return -1;
01201      else
01202      if(lsize > rsize)
01203        return 1;
01204 
01205      return 0; // strings are equal
01206 
01207       
01208   }
01209 
01210   static int compareIgnoringPathSeparatorDifferences(std::string const &l,
01211                                                      std::string const &r
01212                                                     )
01217   {
01218       return compareIgnoringPathSeparatorDifferences(l.data(), r.data(), l.size(), r.size());
01219       
01220   }
01221 
01222 
01223 
01224   bool operator==(FileName const rhs) const
01226   {
01227     int cmp = compareIgnoringPathSeparatorDifferences(*this, rhs);
01228 
01229     if(cmp != 0)
01230        return false;
01231 
01232     return true;
01233 
01234 
01235     // return ((std::string const &)(*this)) == (std::string const&)(rhs);
01236   }
01237 
01238   bool operator==(std::string const rhs) const
01240   {
01241 
01242     int cmp = compareIgnoringPathSeparatorDifferences(this->data(), rhs.data(), this->size(), rhs.size());
01243 
01244     if(cmp != 0)
01245        return false;
01246 
01247     return true;
01248 
01249     // return ((std::string const &)(*this)) == rhs;
01250   }
01251 
01252   bool operator==(char const *rhs) const
01254   {
01255     int cmp = compareIgnoringPathSeparatorDifferences(this->data(), rhs, this->size(), strlen(rhs));
01256 
01257     if(cmp != 0)
01258        return false;
01259 
01260     return true;
01261 
01262     
01263     return ((std::string const &)(*this)) == rhs;
01264   }
01265 
01266 
01267   friend bool operator==(std::string const &lhs, FileName const& rhs)
01269   {
01270 
01271     int cmp = compareIgnoringPathSeparatorDifferences(lhs, rhs);
01272 
01273     if(cmp != 0)
01274        return false;
01275 
01276     return true;
01277 
01278     // return lhs == (std::string const &)(rhs);
01279   }
01280 
01281   friend bool operator==(char const*lhs, FileName const& rhs)
01283   {
01284 
01285     int cmp = compareIgnoringPathSeparatorDifferences(lhs, rhs.data(), strlen(lhs), rhs.size());
01286 
01287     if(cmp != 0)
01288        return false;
01289 
01290     return true;
01291     
01292     // return lhs == (std::string const &)(rhs);
01293   }
01294 
01295   static FileName getcwd(); 
01296 
01297   class Tree
01304   {
01305   public:
01306      typedef std::list<Tree*> children_t; 
01307 
01308      friend class FileName;  
01309 
01310   private:
01311 
01312      FileStatus      status_;   
01313      std::string     name_;     
01314      children_t      children_; 
01315 
01316      Tree*           parent_;   
01317 
01318      int             depth_;    
01319 
01320   public:
01321 
01322       Tree(Tree* parent=0) 
01323       : parent_(parent),
01324         depth_(0)
01325       {
01327       } 
01328 
01329      ~Tree();               
01330       Tree(Tree const &r);  
01331 
01332       Tree(std::string const &name, FileStatus const &status, Tree* parent=0, int depth=0)
01333       : status_(status),
01334         name_(name),
01335         parent_(parent),
01336         depth_(0)
01337       {
01340       }
01341 
01342       Tree &operator=(Tree const &r)
01343       {
01344         this->~Tree();       // delete self
01345         new (this) Tree(r);  // copy construct from r
01346         return *this;
01347       }
01348 
01349 
01350       FileStatus const&  status() const   { return status_; }
01352 
01353       FileName           name() const     { return name_;   }
01355 
01356       FileName           path() const;
01361 
01362       int                depth() const  { return depth_; }
01366 
01367       children_t  const&  children() const { return children_; }
01369 
01370       void add_child(FileName const &name, FileStatus const &status)
01372       {
01373           children_.push_back(new Tree(name,status,this,this->depth_+1));
01374       }
01375 
01376       void add_child(Tree *tree)
01378       {
01379         tree->parent_ = this;
01380         tree->depth_  = depth_+1;
01381         children_.push_back(tree);
01382       }
01383 
01384       void remove_child(FileName const &name);
01386 
01387   };
01388 
01389   std::auto_ptr<Tree> tree(bool only_dirs=false) const;
01400 
01401 private:
01402     std::auto_ptr<Tree> 
01403     tree_helper(std::string const &path, bool only_dirs=false, int depth=0) const;
01405 };
01406 
01407 //========================================================================================
01408 //========================================================================================
01409 //========================================================================================
01410 
01411 inline std::ostream &operator<< (std::ostream &s, FileName const &rhs)
01412 {
01413     std::string const &data = rhs;
01414 
01415     return s << data;
01416 }
01417 
01418 //========================================================================================
01419 //========================================================================================
01420 //========================================================================================
01421 template<class T>
01422 inline bool operator!= (FileName const &lhs, T const &rhs)
01423 {
01424     std::string const &data = lhs;
01425 
01426     return data != rhs;
01427 
01428 }
01429 
01430 //========================================================================================
01431 //========================================================================================
01432 //========================================================================================
01433 template<class T>
01434 inline bool operator!= (T const &lhs, FileName const &rhs)
01435 {
01436     std::string const &data = rhs;
01437 
01438     return data != rhs;
01439 
01440 }
01441 
01442 
01443 
01444 } // namespace cxxtls
01445 
01446 #endif
Generated on Wed Feb 29 22:50:04 2012 for CXXUtilities by  doxygen 1.6.3