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_