core/vul/vul_awk.h
Go to the documentation of this file.
00001 // This is core/vul/vul_awk.h
00002 #ifndef vul_awk_h_
00003 #define vul_awk_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \author Andrew W. Fitzgibbon, Oxford RRG
00010 // \date   17 May 97
00011 //
00012 // \verbatim
00013 // Modifications
00014 // 970517 AWF Initial version.
00015 // PDA (Manchester) 21/03/2001: Tidied up the documentation
00016 // Peter Vanroose   27/05/2001: Corrected the documentation
00017 // Eric Moyer       15/07/2009: Modified the documentation to reflect
00018 //                              working strip_comments and non-working
00019 //                              backslash_continuation
00020 // \endverbatim
00021 
00022 
00023 #include <vcl_string.h>
00024 #include <vcl_iosfwd.h>
00025 #include <vcl_vector.h>
00026 
00027 //: The core of awk
00028 // vul_awk reads lines from a vcl_istream and breaks them into whitespace-separated
00029 // fields.  Its primary advantage is that its name defines the semantics of
00030 // its methods---except that this C++ version uses zero-based fields.  The
00031 // usage is exemplified in this example, to print the second field in every
00032 // line:
00033 // \code
00034 //    for (vul_awk awk=cin; awk; ++awk)
00035 //      vcl_cout << awk[2] << vcl_endl;
00036 // \endcode
00037 //
00038 // The constructor takes an integer mode-flag variable.  Right now,
00039 // only the strip_comments flag has any effect, though the ModeFlags
00040 // enumeration contains other potential flags.
00041 //
00042 // When the strip_comments flag is set then everything from the first
00043 // '#' character to the end of the line is replaced with a single
00044 // space.  As a special feature, lines that contain an # as the first
00045 // character are skipped entirely by the next() routine, no attempt
00046 // will be made to extract fields from them.  They will be counted in
00047 // the line numbering so that error messages can easily refer to the
00048 // correct line in the file.  To extend the above example to handle
00049 // comments in the file, write:
00050 // \code
00051 //    for (vul_awk awk(cin, vul_awk::strip_comments); awk; ++awk)
00052 //      vcl_cout << awk[2] << vcl_endl;
00053 // \endcode
00054 //
00055 
00056 class vul_awk
00057 {
00058   VCL_SAFE_BOOL_DEFINE;
00059  public:
00060   // Constructors/Destructors--------------------------------------------------
00061   enum ModeFlags {
00062     none = 0x00,
00063     verbose = 0x01,
00064     strip_comments = 0x02,
00065     backslash_continuations = 0x04
00066   };
00067 
00068   vul_awk(vcl_istream& s, ModeFlags mode = none);
00069   ~vul_awk();
00070 
00071   // Operations----------------------------------------------------------------
00072 
00073 //: Return field i.  Counting starts at 0.
00074   char const* operator[] (unsigned i) const {
00075     if (i < fields_.size())
00076       return fields_[i];
00077     else
00078       return 0;
00079   }
00080 
00081 //: Return the current "record number", i.e. line number
00082   int NR() const { return line_number_; }
00083 
00084 //: Return the number of fields on this line.
00085   int NF() const { return int(fields_.size()); }
00086 
00087 //: Return the entire line
00088   char const* line() const { return (char const*)line_.c_str(); }
00089 
00090 //: Return the remainder of the line, starting from field_number.
00091 // (0 is from the first non-whitespace character)
00092   char const* line_from(int field_number) const;
00093 
00094 //: Return true if this line is not the last.
00095   operator safe_bool () const
00096     { return (!done_)? VCL_SAFE_BOOL_TRUE : 0; }
00097 
00098 //: Return false if this line is not the last.
00099   bool operator!() const
00100     { return done_; }
00101 
00102 //: Advance to the next line
00103   vul_awk& operator ++ () { next(); return *this; }
00104 
00105 //: Display error message, line number.
00106 // Also display optional field number and  char within field.
00107 
00108   void error(vcl_ostream&, char const* message, int field = -1,
00109              int char_within_field = 0);
00110 
00111  protected:
00112   // Data Members--------------------------------------------------------------
00113   vcl_istream& fd_;
00114 
00115   ModeFlags mode_;
00116 
00117   // The last input line.
00118   vcl_string line_;
00119 
00120   // Copy of last line with null characters at the start of every field
00121   char* split_line_;
00122   // Pointers to the fields within split_line_;
00123   vcl_vector<char *> fields_;
00124 
00125   // May as well keep track of it...
00126   int line_number_;
00127 
00128   // Set to true when the current line is the last one.
00129   bool done_;
00130 
00131   void next();
00132 
00133   vul_awk(const vul_awk& that);
00134   vul_awk& operator=(const vul_awk& that);
00135 };
00136 
00137 #endif // vul_awk_h_