casa
$Rev:20696$
|
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