casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
MUString.h
Go to the documentation of this file.
00001 //# MUString.h: Pointed String class to aid analysis of quantity strings
00002 //# Copyright (C) 1996,1997,1999,2000,2001
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: MUString.h 20739 2009-09-29 01:15:15Z Malte.Marquarding $
00027 
00028 #ifndef CASA_MUSTRING_H
00029 #define CASA_MUSTRING_H
00030 
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/BasicSL/String.h>
00035 #include <casa/Containers/Block.h>
00036 
00037 //# Forward Declarations
00038 #include <casa/iosfwd.h>
00039 namespace casa { //# NAMESPACE CASA - BEGIN
00040 
00041 class Regex;
00042 template <class T> class Vector; 
00043 
00044 // <summary>
00045 // Pointed String class to aid analysis of quantity strings
00046 // </summary>
00047 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tMeasure" demos="">
00048 // </reviewed>
00049 
00050 // <prerequisite>
00051 //   <li> <linkto classString>String</linkto>
00052 // </prerequisite>
00053 //
00054 // <etymology>
00055 // From Measure Utility String
00056 // </etymology>
00057 //
00058 // <synopsis>
00059 // The MUString is a class with a String and an embedded pointer. It can be used
00060 // to linearly analyse a string for its semantics. Imagine for instance a
00061 // string that represents an angle. It could be formatted as 
00062 // <src>[+-]hh:mm:ss.ttt</src>
00063 // or as <src>[+-]hh[hH]mm[mM]</src> or as 
00064 // <src>[+-]dd.mm.ss.ttt</src>  or with <src>.'s</src> replaced with
00065 // <src>dms</src> or as <src>[+-]ddd.fff deg</src> etc.<br>
00066 // The available methods aid in analysing this string (see example).<br>
00067 // The following analysis method classes are avaible:
00068 // <ul>
00069 //   <li> construct   -- all constructors create a string with the pointer
00070 //              starting at the beginning of the string
00071 //   <li> testX(arg)  -- all test methods test if the next available
00072 //              character(s) fulfill the specified argument test. E.g.
00073 //              <src>Bool testSign()</src> test if current character is + or -.
00074 //              If at end of string; False is returned, except for 
00075 //              <src>testBlank()</src>. No pointer update. Any method with
00076 //              <em>NC</em> at the end (for no-case) will test irrespective
00077 //              of the case.
00078 //   <li> skipX(arg)  -- all skip methods skip all available character(s)
00079 //              fulfilling the specified argument. E.g.
00080 //              <src>void skipSign()</src> will skip all + and - found at
00081 //              the current and subsequent positions. Pointer updated.
00082 //   <li> tSkipX(arg) -- will skip as skipX, and return Bool as in testX.
00083 //              Pointer updated
00084 //   <li> getX(arg)   -- will get the indicated X value from the string.
00085 //              Pointer updated. A get will always return a valid result.
00086 //              However, if the value did not exist (e.g. 
00087 //              <src>Double getDouble()</src> form a string like <src>"abc"</src>
00088 //              will return 0.0) a False status will be saved. It can be
00089 //              interrogated by the <src>Bool status()</src> function.
00090 //              The string part used in producing the value is also
00091 //              saved, and can be obtained with 
00092 //              <src>const String &lastGet()</src>.
00093 //              No saving in case of a simple getChar() is done.
00094 //   <li> stack -- if it is necessary to save the current position of the
00095 //              pointer (for maybe later restoration) a <src>void push()</src>
00096 //              and <src>void pop()</src> are available
00097 //   <li> pointer -- the pointer can be manipulated with <src>void setPtr()</src>
00098 //               and <src>Int getPtr()</src>. Pointers are always protected in
00099 //              their value.
00100 // </ul> 
00101 // The following types (<em>X</em> in the above list) are available
00102 // <ul>
00103 //   <li> Char -- a single character
00104 //   <li> CharNC -- a single character with no case
00105 //   <li> String -- a string
00106 //   <li> StringNC -- a string without case
00107 //   <li> Alpha -- a through z and A through Z and _ (underscore)
00108 //   <li> Num -- digits 0 through 9
00109 //   <li> AlphaNum -- a field staring with Alpha, and remainder (if any)
00110 //              Alpha or Num
00111 //   <li> Sign -- a plus or minus
00112 //   <li> Blank -- a space ar a tab
00113 //   <li> uInt -- unsigned integer
00114 //   <li> Int -- an optionally signed integer
00115 //   <li> Double -- a double value
00116 // </ul>
00117 // General string aids are available. The main one a minimax, caseless
00118 // check of an input String against a vector:
00119 // <src>static uInt minimaxNC(String in, Int N_name, String name[])</src>
00120 // and its vector equivalent: 
00121 // <src>static uInt minimaxNC(String in, Vector<String> name)</src>.
00122 // Success is indicated by a return value less than N_name or the
00123 // vector length.
00124 // </synopsis>
00125 //
00126 // <example>
00127 // See <linkto class=MVAngle>MVAngle</linkto> class for example background.
00128 // The following example is the conversion of different input angle formats
00129 // to a <linkto class=Quantum>Quantity</linkto>. A full blown example,
00130 // but gives some idea of intricacies involved.
00131 // <srcblock>
00132 //  res = Quantity(0.0, "rad"); // result
00133 //  MUString tmp(in);           // Pointed non-const String
00134 //  tmp.skipBlank();
00135 //  Double s = tmp.getSign();   // sign
00136 //  tmp.push();                 // Save position to rescan
00137 //  Double r = tmp.getuInt();   // first field
00138 //  Int tp = 0;                 // distributor
00139 //  if (tmp.tSkipChar('.')) {   // if more than one ., dms format
00140 //    Double r1 = tmp.getuInt();
00141 //    if (tmp.tSkipChar('.')) {
00142 //      r += r1/60.0 + tmp.getDouble()/3600.0;
00143 //      tp = 4;
00144 //    } else {                  // else value with units
00145 //      tmp.pop();              // Reset position
00146 //      r = tmp.getDouble();
00147 //    };
00148 //  } else if (tmp.tSkipCharNC('d')) {  // dms
00149 //    tp = 1;
00150 //  } else if (tmp.tSkipCharNC('h')) {  // hms
00151 //    tp = 2;
00152 //  } else if (tmp.tSkipChar(':')) {    // hms
00153 //    tp = 3;
00154 //  };
00155 //  switch (tp) {
00156 // case 0: {
00157 //    UnitVal u; String us;
00158 //    if (!MVAngle::unitString(u,us,tmp)) return False;
00159 //    r *= s;
00160 //    if (u == UnitVal::NODIM) {        // check correct dimension
00161 //      res = Quantity(r,"rad");
00162 //      return True;
00163 //    };
00164 //    if (u == UnitVal::ANGLE) {
00165 //      res = Quantity(r,us);
00166 //      return True;
00167 //    };
00168 //    if (u == UnitVal::TIME) {
00169 //      res = Quantity(Quantity(r/240.,us).getBaseValue(), "deg");
00170 //      return True;
00171 //    };
00172 //    return False;
00173 //  };
00174 //  break;
00175 //
00176 //  case 1:
00177 //  case 2:
00178 //  case 3: {                   // get remainder od ms and hms formats
00179 //    Char tc = 'm';
00180 //    if (tp == 3) tc = ':';
00181 //    tmp.push();
00182 //    Double r1 = tmp.getuInt();
00183 //    if (tmp.tSkipChar('.')) {
00184 //      tmp.pop();
00185 //      r += tmp.getDouble()/3600.;
00186 //    } else if (tmp.tSkipCharNC(tc)) {
00187 //      r += r1/60.0 + tmp.getDouble()/3600.;
00188 //    } else {
00189 //      r += r1/3600.0;
00190 //    };
00191 //    r *= s;
00192 //  };
00193 //  break;
00194 //
00195 //  default:
00196 //    break;
00197 //  };
00198 //
00199 //  switch (tp) {               // make correct units
00200 //
00201 //  case 1:
00202 //  case 4:
00203 //    res = Quantity(r,"deg");
00204 //    break;
00205 //
00206 //  case 2:
00207 //  case 3:
00208 //    res = Quantity(Quantity(r/240.,"h").getBaseValue(), "deg");
00209 //    break;
00210 //
00211 //  default:
00212 //    break;
00213 //
00214 //  };
00215 //  return True;
00216 // </srcblock>
00217 // </example>
00218 //
00219 // <motivation>
00220 // The class was written to be able to analyse an input string for its
00221 // <linkto class=Quantum>Quantum</linkto> representation as value with
00222 // units, or os a date/time or as an angle.
00223 // </motivation>
00224 //
00225 // <todo asof="1996/11/14">
00226 //   <li> nothing I know of
00227 // </todo>
00228 
00229 class MUString
00230 {
00231 public:
00232 
00233 //# Friends
00234   // Output String starting at pointer
00235   friend ostream &operator<<(ostream &os, const MUString &in);
00236 //# Enumerations
00237 
00238 //# Constructors
00239   // Default constructor creates an empty string
00240   MUString();
00241   // Create from String; setting pointer at start
00242   // <group>
00243   MUString(const String &in);
00244   MUString(const Char *in);
00245   MUString(char in);
00246   // </group>
00247   // Copy constructor; new pointer will be same as old
00248   MUString(const MUString &other);
00249   // Copy assignment; new pointer will be same as old
00250   MUString &operator=(const MUString &other);
00251 
00252   // Destructor
00253   ~MUString();
00254 
00255 //# Operators
00256   // Obtain remaining string (same as <src>get()</src>).
00257   String operator()();
00258 
00259 //# General Member Functions
00260   // Save current pointer on internal stack
00261   void push();
00262   // Restore pointer from stack (or set to start if stack empty)
00263   void pop();
00264   // Restore stack for one level
00265   void unpush();
00266 
00267   // Act on whitespace; adjusting pointer if skip
00268   // <group>
00269   void skipBlank();
00270   Bool testBlank() const;
00271   Bool tSkipBlank();
00272   // </group>
00273 
00274   // Act on sign; return +1 or -1 depending on signs found (-- == +)
00275   // <group>
00276   void skipSign();
00277   Bool testSign() const;
00278   Bool tSkipSign();
00279   Int getSign();
00280   // </group>
00281 
00282   // Act on integer field. If no integer found in 0 returned; and False
00283   // <group>
00284   void skipInt();
00285   Bool testInt() const;
00286   Bool tSkipInt();
00287   Int getInt();
00288   void skipuInt();
00289   Bool tSkipuInt();
00290   Bool testuInt() const;
00291   uInt getuInt();
00292   // </group>
00293 
00294   // Act on Double field. If no value 0 returned and False.
00295   // <group>
00296   void skipDouble();
00297   Bool testDouble() const;
00298   Bool tSkipDouble();
00299   Double getDouble();
00300   // </group>
00301 
00302   // Act on character(s)
00303   // <group>
00304   void skipChar(Int n=1);
00305   void skipChar(Char ch);
00306   Bool tSkipChar(Char nc);
00307   void skipCharNC(Char ch);
00308   Bool tSkipCharNC(Char ch);
00309   Bool tSkipOneChar(Char ch);
00310   Bool tSkipOneCharNC(Char ch);
00311   void skipChar(const Regex &ex);
00312   Bool tSkipChar(const Regex &ex);
00313   void skipAlpha();
00314   Bool tSkipAlpha();
00315   void skipNum();
00316   Bool tSkipNum();
00317   void skipAlphaNum();
00318   Bool tSkipAlphaNum();
00319   Bool testChar(Char ch) const;
00320   Bool testCharNC(Char ch) const;
00321   Bool testChar(const Regex &ex) const;
00322   Bool testAlpha() const;
00323   Bool testNum() const;
00324   Bool testAlphaNum() const;
00325   Char getChar();
00326   String getAlpha();
00327   String getAlphaNum();
00328   // </group>
00329 
00330   // Act on series of characters
00331   // <group>
00332   Bool testString(const Regex &ex) const;
00333   Bool testString(const String &ex) const;
00334   Bool testStringNC(const String &ex) const;
00335   Bool tSkipString(const Regex &ex);
00336   Bool tSkipString(const String &ex);
00337   Bool tSkipStringNC(const String &ex);
00338   void skipString(const Regex &ex);
00339   void skipString(const String &ex);
00340   void skipStringNC(const String &ex);
00341   String getString(const Regex &ex);
00342   String getString(const String &ex);
00343   String getStringNC(const String &ex);
00344   // </group>
00345 
00346   // Match a pair of opening(at pointer)/closing characters (e.g. ( and )).
00347   // Return False if wrong semantics. The string between the pair 
00348   // (excluding them)
00349   // will be put in Last. If false, the ptr will be as originally; if True
00350   // it will point beyond the matched closing character
00351   Bool matchPair(Char nd);
00352 
00353   // Get frequency of occurrence
00354   Int freqChar(Char ch) const;
00355 
00356   // Get part of string
00357   // <group>
00358   String get();
00359   String get(uInt st);
00360   String get(uInt st, uInt nd);
00361   // </group>
00362 
00363   // Get pointer
00364   Int getPtr() const;
00365 
00366   // (Re-)set pointer
00367   void setPtr(Int in=0);
00368 
00369   // test for end of string
00370   Bool eos() const;
00371 
00372   // Get status last get
00373   Bool status() const;
00374 
00375   // Get String found at last get
00376   const String &lastGet() const;
00377 
00378   // Do minimax check on list of Strings
00379   // <group>
00380   static uInt minimaxNC(const String &in, Int N_name, 
00381                         const String tname[]);
00382   static uInt minimaxNC(const String &in, const Vector<String> &tname);
00383   // </group>
00384 
00385 private:
00386  // Data
00387  // String value
00388   String str;
00389   // 0-based pointer into string
00390   uInt ptr;
00391   // Length of string
00392   uInt len;
00393   // Pointer stack
00394   Block<uInt> stack;
00395   // Pointer into stack
00396   uInt stpt;
00397   // Status of last get
00398   Bool stat;
00399   // String found at last get
00400   String lget;
00401 
00402   // Member functions
00403   // Make a new pointer between 0 and len inclusive
00404   void adjustPtr(Int in);
00405 
00406   // Initialise last settings; return pointer
00407   Int initLast();
00408   // Set last settings
00409   void setLast(Int st);
00410 
00411 };
00412 
00413 // Global functions
00414 // <summary> Output global functions </summary>
00415 // Output
00416 // <group name=output>  
00417 ostream &operator<<(ostream &os, const MUString &in);
00418 // </group>
00419 
00420 
00421 } //# NAMESPACE CASA - END
00422 
00423 #endif