StringUtils.hpp

Go to the documentation of this file.
00001 #pragma ident "$Id: StringUtils.hpp 3323 2012-10-03 10:44:12Z yanweignss $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00025 //============================================================================
00026 //
00027 //This software developed by Applied Research Laboratories at the University of
00028 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00029 //Department of Defense. The U.S. Government retains all rights to use,
00030 //duplicate, distribute, disclose, or release this software. 
00031 //
00032 //Pursuant to DoD Directive 523024 
00033 //
00034 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00035 //                           release, distribution is unlimited.
00036 //
00037 //=============================================================================
00038 
00044 #ifndef GPSTK_STRINGUTILS_HPP
00045 #define GPSTK_STRINGUTILS_HPP
00046 
00047 #include <string>
00048 #include <sstream>
00049 #include <iomanip>
00050 #include <iostream>
00051 #include <list>
00052 #include <vector>
00053 #include <cstdio>   
00054 #include <cctype>
00055 #include <limits>
00056 
00057 #ifdef _WIN32
00058         #if _MSC_VER < 1700 
00059         // For lower version of visual studio 2012 use gnu regex 
00060                 #include <regex.h>
00061                 #pragma comment(lib, "regex.lib") 
00062         #else
00063         // visual studio 2012 support c++ 0x, and we use std::regex
00064                 #include <regex>
00065         #endif
00066 #else
00067     // TODO: we should use std::regex for upper than g++ 4.6
00068         #include <regex.h>                      
00069 #endif
00070 
00071 #include "Exception.hpp"
00072 
00073 namespace gpstk
00074 {
00093    namespace StringUtils
00094    {
00097 
00101       NEW_EXCEPTION_CLASS(StringException, Exception);
00102 
00104       class HexDumpDataConfig
00105       {
00106       public:
00107          HexDumpDataConfig()
00108                : showIndex(true), hexIndex(true), upperHex(false),
00109                  idxDigits(4), indexWS(1), groupBy(1), groupWS(1),
00110                  group2By(8), group2WS(2), bytesPerLine(16), showText(true),
00111                  separator(0), textWS(4)
00112          {}
00113          HexDumpDataConfig(bool ashowIndex, bool ahexIndex, bool aupperHex,
00114                            unsigned aidxDigits, unsigned aindexWS,
00115                            unsigned agroupBy, unsigned agroupWS,
00116                            unsigned agroup2By, unsigned agroup2WS,
00117                            unsigned abytesPerLine, bool ashowText,
00118                            char aseparator, unsigned atextWS)
00119                : showIndex(ashowIndex), hexIndex(ahexIndex),
00120                  upperHex(aupperHex), idxDigits(aidxDigits),
00121                  indexWS(aindexWS), groupBy(agroupBy), groupWS(agroupWS),
00122                  group2By(agroup2By), group2WS(agroup2WS),
00123                  bytesPerLine(abytesPerLine), showText(ashowText),
00124                  separator(aseparator), textWS(atextWS)
00125          {}
00126          bool showIndex; 
00127          bool hexIndex; 
00128          bool upperHex; 
00129          unsigned idxDigits; 
00130          unsigned indexWS; 
00131          unsigned groupBy; 
00132          unsigned groupWS; 
00133          unsigned group2By; 
00134          unsigned group2WS; 
00135          unsigned bytesPerLine; 
00136          bool showText; 
00137          char separator; 
00138          unsigned textWS; 
00139       };
00140 
00149       inline void hexDumpData(std::ostream& s,
00150                               const std::string& data,
00151                               unsigned indent = 0,
00152                               HexDumpDataConfig cfg = HexDumpDataConfig());
00153       
00162       inline void hexDumpData(std::ostream& s,
00163                               const std::string& data,
00164                               const std::string& tag,
00165                               HexDumpDataConfig cfg = HexDumpDataConfig());
00166 
00177       inline 
00178       std::string& stripLeading(std::string& s,
00179                                 const std::string& aString,
00180                                 std::string::size_type num = std::string::npos)
00181          throw(StringException);
00182 
00193       inline std::string stripLeading(const std::string& s,
00194                                       const std::string& aString,
00195                                       std::string::size_type num = std::string::npos)
00196          throw(StringException)
00197       { std::string t(s); stripLeading(t, aString, num); return t; }
00198 
00209       inline std::string& stripLeading(std::string& s, 
00210                                        const char* pString,
00211                                        std::string::size_type num = std::string::npos)
00212          throw(StringException)
00213       { return stripLeading(s, std::string(pString), num); }
00214 
00225       inline std::string stripLeading(const std::string& s, 
00226                                       const char* pString,
00227                                       std::string::size_type num = std::string::npos)
00228          throw(StringException)
00229       { std::string t(s); stripLeading(t, std::string(pString), num); return t; }
00230 
00241       inline std::string& stripLeading(std::string& s, 
00242                                        const char aCharacter,
00243                                        std::string::size_type num = std::string::npos)
00244          throw(StringException)
00245       { return stripLeading(s, std::string(1,aCharacter), num); }
00246      
00257       inline std::string stripLeading(const std::string& s, 
00258                                       const char aCharacter,
00259                                       std::string::size_type num = std::string::npos)
00260          throw(StringException)
00261       { std::string t(s); stripLeading(t, std::string(1,aCharacter), num); return t; }
00262      
00272       inline std::string& stripLeading(std::string& s, 
00273                                        std::string::size_type num = std::string::npos)
00274          throw(StringException)
00275       { return stripLeading(s,std::string(1,' '),num); }
00276 
00286       inline std::string stripLeading(const std::string& s, 
00287                                       std::string::size_type num = std::string::npos)
00288          throw(StringException)
00289       { std::string t(s); stripLeading(t,std::string(1,' '),num); return t; }
00290      
00301       inline std::string& stripTrailing(std::string& s,
00302                                         const std::string& aString,
00303                                         std::string::size_type num = std::string::npos)
00304          throw(StringException);
00305 
00316       inline std::string stripTrailing(const std::string& s,
00317                                        const std::string& aString,
00318                                        std::string::size_type num = std::string::npos)
00319          throw(StringException)
00320       { std::string t(s); stripTrailing(t, aString, num); return t;}
00321 
00332       inline std::string& stripTrailing(std::string& s, 
00333                                         const char* pString, 
00334                                         std::string::size_type num = std::string::npos)
00335          throw(StringException)
00336       { return stripTrailing(s, std::string(pString), num); }
00337 
00348       inline std::string stripTrailing(const std::string& s, 
00349                                        const char* pString, 
00350                                        std::string::size_type num = std::string::npos)
00351          throw(StringException)
00352       { std::string t(s); stripTrailing(t, std::string(pString), num); return t; }
00353 
00364       inline std::string& stripTrailing(std::string& s, 
00365                                         const char aCharacter,
00366                                         std::string::size_type num = std::string::npos)
00367          throw(StringException)
00368       { return stripTrailing(s, std::string(1,aCharacter), num); }
00369 
00380       inline std::string stripTrailing(const std::string& s, 
00381                                        const char aCharacter,
00382                                        std::string::size_type num = std::string::npos)
00383          throw(StringException)
00384       { std::string t(s); stripTrailing(t, std::string(1,aCharacter), num); return t; }
00385 
00395       inline std::string& stripTrailing(std::string& s, 
00396                                         std::string::size_type num = std::string::npos)
00397          throw(StringException)
00398       { return stripTrailing(s, std::string(1,' '), num); }
00399 
00409       inline std::string stripTrailing(const std::string& s, 
00410                                        std::string::size_type num = std::string::npos)
00411          throw(StringException)
00412       { std::string t(s); stripTrailing(t, std::string(1,' '), num); return t;}
00413 
00424       inline std::string& strip(std::string& s, 
00425                                 const std::string& aString, 
00426                                 std::string::size_type num = std::string::npos)
00427          throw(StringException);
00428 
00429 
00440       inline std::string strip(const std::string& s, 
00441                                const std::string& aString, 
00442                                std::string::size_type num = std::string::npos)
00443          throw(StringException)
00444       { std::string t(s);  strip(t, aString, num); return t; }
00445 
00446 
00457       inline std::string& strip(std::string& s, 
00458                                 const char* pString,
00459                                 std::string::size_type num = std::string::npos)
00460          throw(StringException)
00461       { return strip(s, std::string(pString), num); }
00462 
00473       inline std::string strip(const std::string& s, 
00474                                const char* pString,
00475                                std::string::size_type num = std::string::npos)
00476          throw(StringException)
00477       { std::string t(s); strip(t, std::string(pString), num); return t; }
00478 
00489       inline std::string& strip(std::string& s, 
00490                                 const char aCharacter,
00491                                 std::string::size_type num = std::string::npos)
00492          throw(StringException)
00493       { return strip(s, std::string(1,aCharacter), num); }
00494 
00505       inline std::string strip(const std::string& s, 
00506                                const char aCharacter,
00507                                std::string::size_type num = std::string::npos)
00508          throw(StringException)
00509       { std::string t(s);  strip(t, std::string(1,aCharacter), num); return t;}
00510 
00520       inline std::string& strip(std::string& s, 
00521                                 std::string::size_type num = std::string::npos)
00522          throw(StringException)
00523       { return strip(s, std::string(1, ' '), num); }
00524 
00534       inline std::string strip(const std::string& s, 
00535                                std::string::size_type num = std::string::npos)
00536          throw(StringException)
00537       { std::string t(s);  strip(t, std::string(1, ' '), num); return t;}
00538 
00550       inline std::string translate(const std::string& aString,
00551                                    const std::string& inputChars,
00552                                    const std::string& outputChars,
00553                                    const char pad = ' ');
00554       
00574       inline std::string change(const std::string& aString,
00575                                 const std::string& inputString,
00576                                 const std::string& outputString,
00577                                 std::string::size_type startPos = 0,
00578                                 unsigned numChanges = (std::numeric_limits<unsigned>::max)());
00579 
00599       inline std::string& change(std::string& aString,
00600                                  const std::string& inputString,
00601                                  const std::string& outputString,
00602                                  std::string::size_type startPos = 0,
00603                                  unsigned numChanges = (std::numeric_limits<unsigned>::max)());
00604 
00616       inline std::string& rightJustify(std::string& s, 
00617                                        const std::string::size_type length, 
00618                                        const char pad = ' ')
00619          throw(StringException);
00620 
00632       inline std::string rightJustify(const std::string& s, 
00633                                       const std::string::size_type length, 
00634                                       const char pad = ' ')
00635          throw(StringException)
00636       { std::string t(s); return rightJustify(t, length, pad); }
00637 
00649       inline std::string& leftJustify(std::string& s,
00650                                       const std::string::size_type length,
00651                                       const char pad = ' ')
00652          throw(StringException);
00653 
00665       inline std::string leftJustify(const std::string& s,
00666                                      const std::string::size_type length,
00667                                      const char pad = ' ')
00668          throw(StringException)
00669       { std::string t(s); return leftJustify(t, length, pad); }
00670      
00688       inline std::string& center(std::string& s,
00689                                  const std::string::size_type length,
00690                                  const char pad = ' ')
00691          throw(StringException);
00692 
00711       inline std::string center(const std::string& s,
00712                                 const std::string::size_type length,
00713                                 const char pad = ' ')
00714          throw(StringException)
00715       { std::string t(s); return center(t, length, pad); }
00716 
00722       inline double asDouble(const std::string& s)
00723       { return strtod(s.c_str(), 0); }
00724      
00730       inline long asInt(const std::string& s)
00731       { return strtol(s.c_str(), 0, 10); }
00732      
00738       inline unsigned long asUnsigned(const std::string& s)
00739       { return strtoul(s.c_str(), 0, 10); }
00740      
00746       inline float asFloat(const std::string& s)
00747          throw(StringException);
00748 
00754       inline long double asLongDouble(const std::string& s)
00755          throw(StringException);
00756      
00764       template <class X>
00765       inline X asData(const std::string& s)
00766          throw(StringException);
00767 
00774       inline std::string asString(const long double x, 
00775                              const std::string::size_type precision = 21);
00776      
00783       inline std::string asString(const double x, 
00784                              const std::string::size_type precision = 17);
00785      
00792       template <class X>
00793       inline std::string asString(const X x);
00794      
00803       inline std::string& d2x(std::string& s)
00804          throw(StringException);
00805      
00815       inline std::string d2x(const std::string& s)
00816          throw(StringException)
00817       { std::string t(s);  return d2x(t); }
00818      
00827       inline std::string& x2d(std::string& s)
00828          throw(StringException);
00829      
00839       inline std::string x2d(const std::string& s)
00840          throw(StringException)
00841       { std::string t(s);  return x2d(t); }
00842      
00850       inline std::string& c2x(std::string& s)
00851          throw(StringException);
00852 
00858       inline std::string c2x(const std::string& s)
00859          throw(StringException)
00860       { std::string t(s);  return c2x(t); }
00861 
00868       inline unsigned int x2uint(const std::string& s)
00869          throw(StringException);
00870 
00876       inline std::string int2x(const unsigned int& i)
00877          throw(StringException);
00878 
00886       inline std::string& replaceAll(std::string& s, 
00887                                      const std::string& oldString, 
00888                                      const std::string& newString )
00889          throw(StringException);
00890 
00898       inline bool isDigitString(const std::string& s);
00899 
00906       inline bool isDecimalString(const std::string& s);
00907 
00915       inline bool isScientificString(const std::string& s);
00916 
00924       inline bool isAlphaString(const std::string& s);
00925 
00942       inline std::string matches(const std::string& s,
00943                                  const std::string& aPattern,
00944                                  const char zeroOrMore = '*',
00945                                  const char oneOrMore = '+',
00946                                  const char anyChar = '.' )
00947          throw(StringException);
00948 
00964       inline bool isLike(const std::string& s, 
00965                          const std::string& aPattern,
00966                          const char zeroOrMore = '*', 
00967                          const char oneOrMore = '+',
00968                          const char anyChar = '.' )
00969          throw(StringException)
00970       { return matches(s, aPattern, zeroOrMore, oneOrMore, anyChar) !=
00971            std::string(); }
00972 
00973 
00989       inline bool isLike(const std::string& s, 
00990                          const char* pPattern,
00991                          const char zeroOrMore = '*', 
00992                          const char oneOrMore = '+',
00993                          const char anyChar = '.' )
00994          throw(StringException)
00995       { return matches(s, std::string(pPattern), 
00996                        zeroOrMore, oneOrMore, anyChar) !=  std::string(); }
00997      
00998      
01014       template <class T>
01015       std::string formattedPrint(const std::string& fmt, 
01016                                  const std::string& pat,
01017                                  const std::string& rep, 
01018                                  T to)
01019          throw(StringException);
01020 
01026       inline std::string subString(const std::string& s, 
01027                                    const std::string::size_type startPos = 0,
01028                                    const std::string::size_type length = std::string::npos,
01029                                    const char pad = ' ' )
01030          throw(StringException);
01031      
01038       inline std::string& lowerCase(std::string& s);
01039 
01046       inline std::string lowerCase(const std::string& s)
01047       { std::string t(s);  return lowerCase(t); }
01048 
01055       inline std::string& upperCase(std::string& s);
01056 
01063       inline std::string upperCase(const std::string& s)
01064       { std::string t(s);  return upperCase(t); }
01065 
01075       inline std::string memToString(const void* p, 
01076                                      const std::string::size_type size);
01077       
01085       inline std::string firstWord(const std::string& s, 
01086                                    const char delimiter = ' ')
01087          throw(StringException);
01088      
01096       inline int numWords(const std::string& s, 
01097                           const char delimiter = ' ')
01098          throw(StringException);
01099      
01112       inline std::string words(const std::string& s, 
01113                                const std::string::size_type firstWord = 0,
01114                                const std::string::size_type numWords = std::string::npos,
01115                                const char delimiter = ' ')
01116          throw(StringException);
01117      
01128       inline std::string word(const std::string& s, 
01129                               const std::string::size_type wordNum = 0,
01130                               const char delimiter = ' ')
01131          throw(StringException)
01132       { return words(s, wordNum, 1, delimiter); }
01133      
01142       inline std::string stripFirstWord(std::string& s, 
01143                                         const char delimiter = ' ')
01144          throw(StringException);
01145      
01152        inline std::vector<std::string> split(const std::string& str,
01153                                              const char delimiter = ' ')
01154           throw(StringException);
01155 
01166       inline std::string& removeWords(std::string& s, 
01167                                       const std::string::size_type first = 0, 
01168                                       const std::string::size_type wordsToReplace = std::string::npos,
01169                                       const char delimiter = ' ')
01170          throw(StringException);
01171 
01182       inline std::string doub2sci(const double& d, 
01183                                   const std::string::size_type length, 
01184                                   const std::string::size_type expLen,
01185                                   const bool showSign = true,
01186                                   const bool checkSwitch = true);
01187       
01196       inline std::string doubleToScientific(const double& d,
01197                                             const std::string::size_type length,
01198                                             const std::string::size_type precision,
01199                                             const std::string::size_type explen,
01200                                             bool showPlus=false);
01201 
01217       inline std::string& sci2for(std::string& aStr, 
01218                                   const std::string::size_type startPos = 0,
01219                                   const std::string::size_type length = std::string::npos, 
01220                                   const std::string::size_type expLen = 3,
01221                                   const bool checkSwitch = true)
01222          throw(StringException);
01223 
01236       inline std::string doub2for(const double& d, 
01237                                   const std::string::size_type length, 
01238                                   const std::string::size_type expLen,
01239                                   const bool checkSwitch = true)
01240          throw(StringException);
01241 
01251       inline double for2doub(const std::string& aStr, 
01252                              const std::string::size_type startPos = 0,
01253                              const std::string::size_type length = std::string::npos);
01254       
01262       inline std::string printable(const std::string& aStr)
01263          throw(StringException);
01264 
01276       inline std::string& prettyPrint(std::string& aStr,
01277                                       const std::string& lineDelim = "\n",
01278                                       const std::string& indent = "",
01279                                       const std::string& firstIndent = "     ",
01280                                       const std::string::size_type len = 80,
01281                                       const char wordDelim = ' ')
01282          throw(StringException);
01283 
01295       inline std::string prettyPrint(const std::string& aStr,
01296                                      const std::string& lineDelim = "\n",
01297                                      const std::string& indent = "",
01298                                      const std::string& firstIndent = "     ",
01299                                      const std::string::size_type len = 80,
01300                                      const char wordDelim = ' ')
01301          throw(StringException)
01302       { 
01303          std::string temp(aStr); 
01304          prettyPrint(temp, lineDelim, indent, firstIndent, len, wordDelim); 
01305          return temp; 
01306       }
01307 
01314       inline std::vector<std::string> split(const std::string& aStr,
01315                                             const std::string& theDelimiters=" ",
01316                                             bool trimWhitespace = false, 
01317                                             bool ignoreEmpty = true)
01318       {
01319          std::vector<std::string> toReturn;
01320 
01321          std::string::size_type lastPos = aStr.find_first_not_of(theDelimiters, 0);         
01322          std::string::size_type pos     = aStr.find_first_of(theDelimiters, lastPos);      
01323 
01324          while (std::string::npos != pos || std::string::npos != lastPos)     
01325          {              
01326             std::string token = aStr.substr(lastPos, pos - lastPos);
01327 
01328             if(trimWhitespace) token = StringUtils::strip(token);
01329 
01330             if(!token.empty() || !ignoreEmpty) toReturn.push_back(token);  
01331 
01332             lastPos = aStr.find_first_not_of(theDelimiters, pos);              
01333             pos = aStr.find_first_of(theDelimiters, lastPos);     
01334          } 
01335 
01336          return toReturn;
01337       }
01338 
01339    } // namespace StringUtils
01340   
01341 } // namespace gpstk
01342 
01343 // ################################################
01344 //   Implementations of inline functions follow
01345 // ################################################
01346 
01347 namespace gpstk
01348 {
01349 
01350    namespace StringUtils
01351    {
01352       inline void hexDumpData(std::ostream& s, const std::string& data,
01353                               unsigned indent, HexDumpDataConfig cfg)
01354       {
01355          std::string instr(indent, ' ');
01356          hexDumpData(s, data, instr, cfg);
01357       }
01358 
01359       inline void hexDumpData(std::ostream& s, const std::string& data,
01360                               const std::string& tag, HexDumpDataConfig cfg)
01361       {
01362          std::string ascii="";
01363          unsigned indent = tag.length();
01364          int col = 0;
01365          int datasize=data.size();
01366          std::string groupws(cfg.groupWS, ' ');
01367          std::string group2ws(cfg.group2WS, ' ');
01368          std::string indexws(cfg.indexWS, ' ');
01369          std::string textws(cfg.textWS, ' ');
01370          unsigned linesize;
01371 
01372          if (cfg.groupBy && ((cfg.bytesPerLine % cfg.groupBy) != 0))
01373          {
01374             s << "hexDumpData: cfg.bytesPerLine % cfg.groupBy != 0"
01375               << std::endl;
01376             return;
01377          }
01378          if (cfg.group2By && ((cfg.bytesPerLine % cfg.group2By) != 0))
01379          {
01380             s << "hexDumpData: cfg.bytesPerLine % cfg.group2By != 0"
01381               << std::endl;
01382             return;
01383          }
01384          if (cfg.groupBy && ((cfg.group2By % cfg.groupBy) != 0))
01385          {
01386             s << "hexDumpData: cfg.group2By % cfg.groupBy != 0"
01387               << std::endl;
01388             return;
01389          }
01390 
01391             // line format:
01392             // <tag><index>:<indexws><group1byte1>...<group1byte[groupBy]><groupws>...<group[group2By]byte1>...<group[group2By]byte[groupBy]><group2ws>....<byte[bytesPerLine]><textws><separator><text><separator>\n
01393          linesize = indent;
01394          if (cfg.showIndex)
01395             linesize += cfg.idxDigits + 1 + cfg.indexWS;
01396          linesize += cfg.bytesPerLine * 2;
01397          unsigned w2 = 0;
01398          unsigned w1 = 0;
01399          if (cfg.group2By)
01400             w2 = (cfg.bytesPerLine / cfg.group2By) - 1;
01401          if (cfg.groupBy)
01402             w1 = (cfg.bytesPerLine / cfg.groupBy) - w2 - 1;
01403          if (cfg.groupBy > 0)
01404             linesize += cfg.groupWS * w1;
01405          if (cfg.group2By > 0)
01406             linesize += cfg.group2WS * w2;
01407             /*
01408               linesize doesn't include text stuff
01409          if (cfg.showText)
01410             linesize += cfg.textWS + cfg.bytesPerLine;
01411          if (cfg.separator)
01412             linesize += 2;
01413             */
01414 
01415          for (int i=0; i<datasize; i++)
01416          {
01417             if (i%cfg.bytesPerLine==0)
01418             {
01419                s << tag;
01420                col = indent;
01421                if (cfg.showIndex)
01422                {
01423                   if (cfg.hexIndex)
01424                   {
01425                      s << std::hex;
01426                      if (cfg.upperHex)
01427                         s << std::uppercase;
01428                      else
01429                         s << std::nouppercase;
01430                   }
01431                   else
01432                      s << std::dec;
01433                   s << std::setfill('0');
01434                   s << std::setw(cfg.idxDigits) << i << ":" << indexws;
01435                   s << std::dec << std::nouppercase;
01436                }
01437                col += cfg.idxDigits + 1 + cfg.indexWS;
01438             }
01439             unsigned char c=data[i];
01440             if (isprint(c))
01441                ascii += c;
01442             else
01443                ascii += '.';
01444             if (cfg.upperHex)
01445                s << std::uppercase;
01446             else
01447                s << std::nouppercase;
01448             s << std::hex << std::setw(2) << (int)c << std::dec
01449               << std::nouppercase;
01450             col += 2;
01451             if (((i % cfg.bytesPerLine) == (cfg.bytesPerLine-1)) ||
01452                 (i == (datasize-1)))
01453             {
01454                if (cfg.showText)
01455                {
01456                   int extra = linesize-col;
01457                   std::string space(extra, ' ');
01458                   s << space << textws;
01459                   if (cfg.separator)
01460                      s << cfg.separator;
01461                   s << ascii;
01462                   if (cfg.separator)
01463                      s << cfg.separator;
01464                   s << std::endl;
01465                }
01466                   // this *should* be updated at the beginning of the loop
01467                   //col=indent+6;
01468                ascii.erase();
01469             }
01470             else if (cfg.group2By && ((i % cfg.group2By) == (cfg.group2By-1)))
01471             {
01472                s << group2ws;
01473                col += cfg.group2WS;
01474             }
01475             else if (cfg.groupBy && ((i % cfg.groupBy) == (cfg.groupBy-1)))
01476             {
01477                s << groupws;
01478                col += cfg.groupWS;
01479             }
01480          }
01481       }
01482 
01483          // Keep searching for aString at the start of s
01484          // until num == 0 or aString is not found at the start of s
01485       inline std::string& stripLeading(std::string& s,
01486                                   const std::string& aString,
01487                                   std::string::size_type num)
01488          throw(StringException)
01489       {
01490          try
01491          {
01492             if (aString == "")
01493                return s;
01494 
01495             while((num > 0) &&
01496                   (s.find(aString,0) == 0) &&
01497                   (s.length() > 0))
01498             {      
01499                s.erase(0,aString.length());
01500                --num;
01501             }
01502             return s;
01503          }
01504          catch(std::exception &e)
01505          {
01506             StringException strexc("Exception thrown: " + std::string(e.what()));
01507             GPSTK_THROW(strexc);
01508          }
01509       }
01510 
01511          // keep searching for aString at the end of s
01512          // until aString isn't found there or num == 0
01513       inline std::string& stripTrailing(std::string& s,
01514                                    const std::string& aString,
01515                                    std::string::size_type num)
01516          throw(StringException)
01517       {
01518          try
01519          {
01520             std::string::size_type pos = s.length() - aString.length();
01521 
01522                // empty string, etc.
01523             if ((pos > s.length()) || (aString == ""))
01524                return s;
01525 
01526             while((num > 0) && 
01527                   (s.rfind(aString,pos) == pos) &&
01528                   (s.length() > 0))
01529             {
01530                s.erase(pos, std::string::npos);
01531                --num;
01532                pos = s.length() - aString.length();
01533             }
01534             return s;
01535          }
01536          catch(std::exception &e)
01537          {
01538             StringException strexc("Exception thrown: " + std::string(e.what()));
01539             GPSTK_THROW(strexc);
01540          }
01541       }
01542 
01543       inline std::string& strip(std::string& s, 
01544                            const std::string& aString, 
01545                            std::string::size_type num)
01546          throw(StringException)
01547       {
01548          stripLeading(s, aString, num);
01549          stripTrailing(s, aString, num);
01550          return s;
01551       }
01552 
01553       inline std::string translate(const std::string& aString,
01554                               const std::string& inputChars,
01555                               const std::string& outputChars,
01556                               const char pad)
01557       {
01558          std::string rv = aString;
01559          std::string::size_type aspos = 0;
01560          std::string::size_type inpos = std::string::npos;
01561          char toc = pad;
01562 
01563             // By starting at the last position, we avoid infinite
01564             // loops in case someone did something dumb, like, for
01565             // example, setting inputChars=outputChars.
01566          while ((aspos = rv.find_first_of(inputChars, aspos))
01567                 != std::string::npos)
01568          {
01569                // figure out which char we found;
01570             inpos = inputChars.find(rv[aspos]);
01571             if (outputChars.length()-1 < inpos)
01572                toc = pad;
01573             else
01574                toc = outputChars[inpos];
01575             rv[aspos] = toc;
01576 
01577             aspos++; // try to guarantee no infinite loops
01578          }
01579 
01580          return rv;
01581       }
01582 
01583       inline std::string change(const std::string& aString, const std::string& inputString,
01584                            const std::string& outputString,
01585                            std::string::size_type startPos, unsigned numChanges)
01586       {
01587          std::string rv(aString);
01588          change(rv, inputString, outputString, startPos, numChanges);
01589          return rv;
01590       }
01591 
01592       inline std::string& change(std::string& aString, const std::string& inputString,
01593                             const std::string& outputString,
01594                             std::string::size_type startPos, unsigned numChanges)
01595       { 
01596     unsigned count = 0;
01597          std::string::size_type opos = startPos;
01598 
01599          while (count < numChanges)
01600          {
01601             std::string::size_type pos = aString.find(inputString, opos);
01602             if (pos != std::string::npos)
01603             {
01604                count++;
01605                aString.replace(pos, inputString.length(), outputString);
01606                opos = pos + outputString.length();
01607             }
01608             else
01609                break;
01610          }
01611 
01612          return aString;
01613       }
01614 
01615          // if the string is bigger than length, truncate it from the left.
01616          // otherwise, add pad characters to it's left.
01617       inline std::string& rightJustify(std::string& s, 
01618                                   const std::string::size_type length, 
01619                                   const char pad)
01620          throw(StringException)
01621       {
01622          try
01623          {
01624             if(length < s.length())
01625             {
01626                s = s.substr(s.length()-length, std::string::npos);
01627             }
01628             else
01629             {
01630                s.insert((std::string::size_type)0, length-s.length(), pad);
01631             }
01632             return s;
01633          }
01634          catch(std::exception &e)
01635          {
01636             StringException strexc("Exception thrown: " + std::string(e.what()));
01637             GPSTK_THROW(strexc);
01638          }
01639       }
01640 
01641          // if the string is bigger than length, truncate it from the right.
01642          // otherwise, add pad characters to it's right.
01643       inline std::string& leftJustify(std::string& s,
01644                                  const std::string::size_type length,
01645                                  const char pad)
01646          throw(StringException)
01647       {
01648          try
01649          {
01650             if(length < s.length())
01651             {
01652                s = s.substr(0, length);
01653             }
01654             else
01655             {
01656                s.append(length-s.length(), pad);
01657             }
01658             return s;
01659          }
01660          catch(std::exception &e)
01661          {
01662             StringException strexc("Exception thrown: " + std::string(e.what()));
01663             GPSTK_THROW(strexc);
01664          }
01665       }
01666 
01667          // leftJustify if s is bigger than length.
01668          // otherwise, add pad to the left and right of s.
01669       inline std::string& center(std::string& s,
01670              const std::string::size_type length,
01671              const char pad)
01672          throw(StringException)
01673       { 
01674          try
01675          {
01676             if(length < s.length())
01677             {
01678                leftJustify(s, length, pad);
01679             }
01680             else {
01681                std::string::size_type leftOff = s.length() + (length - s.length()) / 2;
01682                leftJustify(s, leftOff, pad);
01683                rightJustify(s, length, pad);
01684             }
01685             return s;
01686          }
01687          catch(StringException &e)
01688          {
01689             GPSTK_RETHROW(e);
01690          }
01691          catch(std::exception &e)
01692          {
01693             StringException strexc("Exception thrown: " + std::string(e.what()));
01694             GPSTK_THROW(strexc);
01695          }
01696       } 
01697 
01698 
01699       inline float asFloat(const std::string& s)
01700          throw(StringException)
01701       {
01702          try
01703          {
01704             std::istringstream is(s);
01705             float f;
01706             is >> f;
01707             return f;
01708          }
01709          catch(std::exception &e)
01710          {
01711             StringException strexc("Exception thrown: " + std::string(e.what()));
01712             GPSTK_THROW(strexc);
01713          }
01714       }
01715 
01716       inline long double asLongDouble(const std::string& s)
01717          throw(StringException)
01718       {
01719          try
01720          {
01721             std::istringstream is(s);
01722             long double x;
01723             is >> x;
01724             return x;
01725          }
01726          catch(std::exception &e)
01727          {
01728             StringException strexc("Exception thrown: " + std::string(e.what()));
01729             GPSTK_THROW(strexc);
01730          }
01731       }
01732      
01733       template <class X>
01734       inline X asData(const std::string& s)
01735          throw(StringException)
01736       {
01737          try
01738          {
01739             std::istringstream is(s);
01740             X x;
01741             is >> x;
01742             return x;
01743          }
01744          catch(std::exception &e)
01745          {
01746             StringException strexc("Exception thrown: " + std::string(e.what()));
01747             GPSTK_THROW(strexc);
01748          }
01749       }
01750 
01751       inline std::string asString(const long double x, const std::string::size_type precision)
01752       {
01753          std::ostringstream ss;
01754          ss << std::fixed << std::setprecision(precision) << x ;
01755          return ss.str();
01756       }
01757      
01758       inline std::string asString(const double x, const std::string::size_type precision)
01759       {
01760          std::ostringstream ss;
01761          ss << std::fixed << std::setprecision(precision) << x;
01762          return ss.str();
01763       }
01764      
01765       template<class X>
01766       inline std::string asString(const X x) 
01767       {
01768          std::ostringstream ss;
01769          ss << x;
01770          return ss.str();
01771       }
01772      
01773          // decimal to hex...
01774       inline std::string& d2x(std::string& s)
01775          throw(StringException)
01776       {
01777          try
01778          {
01779                // remove the integer from s, including
01780                // leading spaces and 0's
01781             long l = asInt(s);
01782             stripLeading(s);
01783             stripLeading(s, "0");
01784             stripLeading(s, asString<long>(l));
01785             
01786                // put the int in a stringstream to convert it
01787             std::ostringstream st;
01788             st << std::hex << l << std::dec;
01789             
01790                // add the new hex to s
01791             s.insert(0, upperCase(st.str()) );
01792             
01793             return s;
01794          }
01795          catch(StringException &e)
01796          {
01797             GPSTK_RETHROW(e);
01798          }
01799          catch(std::exception &e)
01800          {
01801             StringException strexc("Exception thrown: " + std::string(e.what()));
01802             GPSTK_THROW(strexc);
01803          }
01804       }
01805 
01806          // character to hex...
01807       inline std::string& c2x(std::string& s)
01808          throw(StringException)
01809       {
01810          const char hexDigits[] = "0123456789ABCDEF";
01811          try
01812          {
01813             std::string old(s);
01814             const unsigned char *pSource = (unsigned char *)old.c_str();
01815             unsigned n = old.length();
01816 
01817             s.resize(n * 2, 0);
01818 
01819             for (int i = 0; i < (int)n * 2;)
01820             {
01821                unsigned char c = *pSource++;
01822                s[i++] = hexDigits[ c / 16 ];
01823                s[i++] = hexDigits[ c % 16 ];
01824             }
01825 
01826             return s;
01827          }
01828          catch(StringException &e)
01829          {
01830             GPSTK_RETHROW(e);
01831          }
01832          catch(std::exception &e)
01833          {
01834             StringException strexc("Exception thrown: " + std::string(e.what()));
01835             GPSTK_THROW(strexc);
01836          }
01837       }
01838 
01840           // hex to a long.
01841       inline unsigned int x2uint(const std::string& s)
01842          throw (StringException)
01843       {
01844          try
01845          {
01846                // make the stringstream, get the integer, and 
01847                // remove it from the string
01848             std::istringstream iss(s);
01849             unsigned int ui;
01850             iss >> std::hex >> ui;
01851             return ui;
01852          }
01853          catch(StringException &e)
01854          {
01855             GPSTK_RETHROW(e);
01856          }
01857          catch(std::exception &e)
01858          {
01859             StringException strexc("Exception thrown: " + std::string(e.what()));
01860             GPSTK_THROW(strexc);
01861          }
01862       }
01863 
01865          // hex to decimal
01866       inline std::string& x2d(std::string& s)
01867          throw(StringException)
01868       {
01869          try
01870          {
01871                // remove the "0x" part, leading zeros and spaces from the 
01872                // string
01873                // ex. ' 0x003' -> '3'
01874             stripLeading(s);
01875             stripLeading(s, "0x", 1);
01876             stripLeading(s, "0");
01877             
01878                // make the stringstream, get the integer, and 
01879                // remove it from the string
01880             std::istringstream strstr(s);
01881             int i = 0;
01882             strstr >> std::hex >> i;
01883             stripLeading(s, asString<int>(asInt(s)), 1);
01884             
01885                // append the decimal to the existing string
01886             s.insert(0,asString<int>(i));
01887             return s;
01888          }
01889          catch(StringException &e)
01890          {
01891             GPSTK_RETHROW(e);
01892          }
01893          catch(std::exception &e)
01894          {
01895             StringException strexc("Exception thrown: " + std::string(e.what()));
01896             GPSTK_THROW(strexc);
01897          }
01898       }
01899      
01900       inline std::string int2x(const unsigned int& i)
01901          throw(StringException)
01902       {
01903          try
01904          {
01905             std::ostringstream ss;
01906             ss << std::hex << i;
01907             return ss.str();
01908          }
01909          catch(StringException &e)
01910          {
01911             GPSTK_RETHROW(e);
01912          }
01913          catch(std::exception &e)
01914          {
01915             StringException strexc("Exception thrown: " + std::string(e.what()));
01916             GPSTK_THROW(strexc);
01917          }
01918       }
01919 
01920       inline std::string& replaceAll(std::string& s, 
01921                                 const std::string& oldString, 
01922                                 const std::string& newString)
01923          throw(StringException)
01924       {
01925          try
01926          {
01927             int spot = s.find(oldString, 0);
01928             while (spot != (int)std::string::npos)
01929             {
01930                s.replace(spot, oldString.length(), newString);
01931                spot += newString.length();
01932                spot = s.find(oldString, spot);
01933             }
01934             return s;
01935          }
01936          catch(std::exception &e)
01937          {
01938             StringException strexc("Exception thrown: " + std::string(e.what()));
01939             GPSTK_THROW(strexc);
01940          }
01941       }
01942 
01943       inline bool isDigitString(const std::string& s)
01944       {
01945          if (s.size() == 0) 
01946             return false;
01947 
01948          std::string::size_type index = 0;
01949          if((s[0] == '-') || (s[0] == '+'))
01950             index++;
01951          for( ; index < s.size(); index++)
01952             if (!isdigit(s[index]))
01953                return false;
01954          return true;
01955       }
01956 
01957       inline bool isDecimalString(const std::string& s)
01958       {
01959          if (s.size() == 0) 
01960             return false;
01961 
01962          std::string::size_type index = 0;
01963          bool sawdot = false;
01964          if((s[0] == '-') || (s[0] == '+'))
01965             index++;
01966          for( ; index < s.size(); index++)
01967          {
01968             if (s[index] == '.')
01969             {
01970                if (sawdot)
01971                   return false;
01972                else sawdot = true;
01973             }
01974             else if (!isdigit(s[index]))
01975                return false;
01976          }
01977          return true;
01978       }
01979 
01980       inline bool isScientificString(const std::string& s)
01981       {
01982          if(s.size() == 0)
01983             return false;
01984 
01985          std::string::size_type pos = s.find_first_of("EeDd");
01986          if(pos == std::string::npos)
01987             return isDecimalString(s);
01988 
01989          std::string mant=s.substr(0,pos);
01990          std::string exp=s.substr(pos+1);
01991          return (isDecimalString(mant) && (exp.size()==0 || isDigitString(exp)));
01992       }
01993 
01994       inline bool isAlphaString(const std::string& s)
01995       {
01996          if (s.size() == 0) 
01997             return false;
01998 
01999          std::string::size_type index;
02000          for(index = 0; index < s.size(); index++)
02001             if (!isalpha(s[index]))
02002                return false;
02003          return true;
02004       }
02005 
02006       inline std::string matches(const std::string& s,
02007                                  const std::string& aPattern,
02008                                  const char zeroOrMore,
02009                                  const char oneOrMore,
02010                                  const char anyChar)
02011          throw(StringException)
02012       {
02013                   std::string thisPattern(aPattern);
02014                   std::string thisStr(s);
02015 
02016                   // check if something other than the regex standard
02017                   // characters (*,+,.) is used for those variables
02018                   if (zeroOrMore != '*')
02019                   {
02020                           replaceAll(thisPattern, "*", "\\*");
02021                           replaceAll(thisPattern, std::string(1, zeroOrMore), "*");
02022                   }
02023                   if (oneOrMore != '+')
02024                   {
02025                           replaceAll(thisPattern, "+", "\\+");
02026                           replaceAll(thisPattern, std::string(1, oneOrMore), "+");
02027                   }
02028                   if (anyChar != '.')
02029                   {
02030                           replaceAll(thisPattern, ".", "\\.");
02031                           replaceAll(thisPattern, std::string(1, anyChar), ".");
02032                   }
02033 
02034 #if defined(_WIN32) && _MSC_VER >= 1700
02035                   try
02036                   {
02037                           std::regex reg (thisPattern);
02038 
02039                           std::smatch sm;
02040                           if(std::regex_search(thisStr,sm,reg,
02041                                   std::regex_constants::match_not_bol|
02042                                   std::regex_constants::match_not_eol))
02043                           {
02044                                   return sm.str();
02045                           }
02046                           else
02047                           {
02048                                   return std::string();
02049                           }
02050                   }
02051                   catch(std::regex_error& e)
02052                   {
02053                           Exception E(std::string("std::regex_error: ") + e.what() );
02054                           GPSTK_THROW(E);
02055                   }
02056                   
02057 #else
02058 
02059          const std::string::size_type regErrorBufSize = 512;
02060 
02061          
02062          regmatch_t matches;
02063          regex_t regExp;
02064          char errorMsg[regErrorBufSize];
02065          int rc = regcomp(&regExp, thisPattern.c_str(), REG_EXTENDED);
02066 
02067          if (rc != 0)
02068          {
02069             regerror(rc, NULL, errorMsg, regErrorBufSize - 1);
02070             regfree(&regExp);
02071             StringException strerr("Regexp error: " + std::string(errorMsg));
02072             GPSTK_THROW(strerr);
02073          }
02074          rc = regexec(&regExp, thisStr.c_str(), 1, &matches, 
02075                       REG_NOTBOL | REG_NOTEOL);
02076          if ( (rc != 0) && (rc != REG_NOMATCH) )
02077          {
02078             regerror(rc, &regExp, errorMsg, regErrorBufSize - 1);
02079             regfree(&regExp);
02080             StringException strerr("Regexp error: " + std::string(errorMsg));
02081             GPSTK_THROW(strerr);
02082          }
02083 
02084          regfree(&regExp);
02085          if (rc == REG_NOMATCH)
02086             return std::string();
02087          else
02088             return thisStr.substr(matches.rm_so, matches.rm_eo - matches.rm_so);
02089 #endif
02090       }
02091 
02092       template <class T>
02093       inline std::string formattedPrint(const std::string& fmt,
02094                                         const std::string& pat,
02095                                         const std::string& rep,
02096                                         T to)
02097          throw(StringException)
02098       {
02099 #if defined(_WIN32) && _MSC_VER >= 1700
02100         
02101           std::string rv(fmt);
02102 
02103         try
02104         {
02105                 std::regex reg(pat); 
02106 
02107                 std::smatch m;
02108                 while (std::regex_search (rv,m,reg)) 
02109                 {
02110                         std::string mac = m.str();
02111                         mac = StringUtils::replaceAll(mac, rep.substr(0,1), rep.substr(1));
02112 
02113                         char buffer[1024];
02114                         sprintf(buffer, mac.c_str(), to);
02115 
02116                         rv.replace(m.position(), m.length(), std::string(buffer));
02117                 }
02118         }
02119         catch(std::regex_error& e)
02120         {
02121                 Exception E(std::string("std::regex_error:")+e.what());
02122                 GPSTK_THROW(E);
02123         }
02124 
02125         return rv;
02126 #else
02127          regex_t re;
02128          const size_t bufferSize = 513;
02129          char buffer[bufferSize];
02130          int rc = regcomp(&re, pat.c_str(), REG_EXTENDED);
02131             // if the regex doesnt compile, toast =)
02132          if ( rc != 0)
02133          {
02134             regerror(rc, NULL, buffer, bufferSize - 1);
02135             regfree(&re);
02136             StringException se("Regexp error: " + std::string(buffer));
02137             GPSTK_THROW(se);
02138          }
02139          
02140          regmatch_t r;
02141          std::string rv = fmt;
02142 
02143          while ( regexec(&re, rv.c_str(), 1, &r, 0) == 0 )
02144          {
02145             size_t len = r.rm_eo - r.rm_so;
02146             std::string mac = rv.substr(r.rm_so, len);
02147             mac = replaceAll(mac, rep.substr(0,1), rep.substr(1));
02148             sprintf(buffer, mac.c_str(), to);
02149             rv.replace(r.rm_so, len, std::string(buffer));
02150          }
02151          
02152          regfree(&re);
02153          return rv;
02154 #endif
02155       }
02156       
02157       inline std::string subString(const std::string& s, 
02158                                    const std::string::size_type startPos,
02159                                    const std::string::size_type length,
02160                                    const char pad)
02161          throw(StringException)
02162       {
02163          try
02164          {
02165             if(startPos >= s.length())
02166             {
02167                return std::string(length, pad);
02168             }
02169             std::string temp = s.substr(startPos, length);
02170             return leftJustify(temp, length, pad);
02171          }
02172          catch(StringException &e)
02173          {
02174             GPSTK_RETHROW(e);
02175          }
02176          catch(std::exception &e)
02177          {
02178             StringException strexc("Exception thrown: " + std::string(e.what()));
02179             GPSTK_THROW(strexc);
02180          }
02181       }
02182 
02183       inline std::string& lowerCase(std::string& s)
02184       {
02185          for(std::string::size_type i = 0; i < s.length(); i++)
02186          {
02187             s[i] = tolower(s[i]);
02188          }
02189          return s;
02190       }
02191 
02192       inline std::string& upperCase(std::string& s)
02193       {
02194          for(std::string::size_type i = 0; i < s.length(); i++)
02195          {
02196             s[i] = toupper(s[i]);
02197          }
02198          return s;
02199       }
02200 
02201       inline std::string memToString(const void* p,
02202                                 const std::string::size_type size)
02203       {
02204          unsigned char* q = (unsigned char*)p;
02205          std::string s(size,'\0');
02206          for (int i=0; i<(int)size; i++)
02207          {
02208             s[i] = (unsigned char)(*q++);
02209          }
02210          return s;
02211       }
02212      
02213       inline std::string firstWord(const std::string& s, 
02214                               const char delimiter)
02215          throw(StringException)
02216       {
02217          try
02218          {
02219                // return s if there are no delimiters
02220             std::string::size_type pos = s.find_first_not_of(delimiter);
02221             if (pos == std::string::npos)
02222             {
02223                return s;
02224             }
02225                // find the end delimiter (if any) and return the string
02226             std::string::size_type endPos = s.find(delimiter, pos);
02227             if (endPos == std::string::npos)
02228             {
02229                return std::string(s, pos, endPos);
02230             }
02231             else
02232             {
02233                return std::string(s, pos, endPos - pos);
02234             }
02235          }
02236          catch(StringException &e)
02237          {
02238             GPSTK_RETHROW(e);
02239          }
02240          catch(std::exception &e)
02241          {
02242             StringException strexc("Exception thrown: " + std::string(e.what()));
02243             GPSTK_THROW(strexc);
02244          }
02245       }
02246      
02247       inline int numWords(const std::string& s, 
02248                           const char delimiter)
02249          throw(StringException)
02250       {
02251          try
02252          {
02253             std::string t(s);
02254             stripTrailing(t, delimiter);
02255             
02256             int words = 0;
02257             while(t.length())
02258             {
02259                stripLeading(t, delimiter);
02260                stripLeading(t, firstWord(t, delimiter));
02261                words++;
02262             }
02263             return words;
02264          }
02265          catch(StringException &e)
02266          {
02267             GPSTK_RETHROW(e);
02268          }
02269          catch(std::exception &e)
02270          {
02271             StringException strexc("Exception thrown: " + std::string(e.what()));
02272             GPSTK_THROW(strexc);
02273          }
02274       }
02275      
02276       inline std::string words(const std::string& s, 
02277                           const std::string::size_type firstWord,
02278                           const std::string::size_type numWords,
02279                           const char delimiter)
02280          throw(StringException)
02281       {
02282          try
02283          {
02284             if ((firstWord == 0) && (numWords == 1))
02285                return StringUtils::firstWord(s, delimiter);
02286             if (numWords == 0)
02287                return "";
02288             std::string::size_type wordNum = 0;
02289             std::string::size_type pos = 0, startPos = 0;
02290             
02291             std::string toReturn;
02292 
02293                // get position of word wordNum
02294             pos = s.find_first_not_of(delimiter, pos);
02295             while ((pos != std::string::npos) && (pos <= s.length()))
02296             {
02297                if (wordNum == firstWord)
02298                   startPos = pos;
02299                   // get first delimter after word wordNum
02300                pos = s.find(delimiter, pos);
02301                if (((int)numWords != -1) && ((int)wordNum == (int)(firstWord + (numWords-1))))
02302                   break;
02303                pos = s.find_first_not_of(delimiter, pos);
02304                wordNum++;
02305             }
02306 
02307             if (pos == std::string::npos)
02308                return s.substr(startPos);
02309             return s.substr(startPos, pos-startPos);
02310          }
02311          catch(StringException &e)
02312          {
02313             GPSTK_RETHROW(e);
02314          }
02315          catch(std::exception &e)
02316          {
02317             StringException strexc("Exception thrown: " + std::string(e.what()));
02318             GPSTK_THROW(strexc);
02319          }
02320       }
02321      
02322       inline std::string stripFirstWord(std::string& s, 
02323                                    const char delimiter)
02324          throw(StringException)
02325       {
02326          try
02327          {
02328             stripLeading(s, delimiter);
02329             std::string toReturn = firstWord(s, delimiter);
02330             stripLeading(s, toReturn);
02331             stripLeading(s, delimiter);
02332             return toReturn;
02333          }
02334          catch(StringException &e)
02335          {
02336             GPSTK_RETHROW(e);
02337          }
02338          catch(std::exception &e)
02339          {
02340             StringException strexc("Exception thrown: " + std::string(e.what()));
02341             GPSTK_THROW(strexc);
02342          }
02343       }
02344      
02345       inline std::vector<std::string> split(const std::string& str,
02346                                             const char delimiter)
02347          throw(StringException)
02348       {
02349          try {
02350             std::vector<std::string> rvec;   // vector to return
02351             std::string tempStr(str);        // copy the input string
02352             stripLeading(tempStr,delimiter); // remove leading delimiters
02353             while(tempStr.size() > 0)
02354                rvec.push_back(stripFirstWord(tempStr,delimiter));
02355             return rvec;
02356          }
02357          catch(StringException &e)
02358          {
02359             GPSTK_RETHROW(e);
02360          }
02361          catch(std::exception &e)
02362          {
02363             StringException strexc("Exception thrown: " + std::string(e.what()));
02364             GPSTK_THROW(strexc);
02365          }
02366       }
02367 
02368       inline std::string& removeWords(std::string& s, 
02369                                  const std::string::size_type first, 
02370                                  const std::string::size_type wordsToReplace,
02371                                  const char delimiter)
02372          throw(StringException)
02373       {
02374          try
02375          {
02376             std::string temp(s);
02377             std::string::size_type thisWord;
02378             
02379                // empty out s.  add the new parts of s as they are parsed
02380             s.erase(0, std::string::npos);
02381             
02382                // copy the part of the string through word 'first'
02383                // by appending any delimiters then appending
02384                // a word for however many words we're keeping.
02385             for(thisWord = 0; thisWord < first; thisWord++)
02386             {
02387                s.append(temp.find_first_not_of(delimiter),delimiter);
02388                stripLeading(temp, delimiter);
02389                s.append(firstWord(temp));
02390                stripLeading(temp, firstWord(temp));
02391             }
02392             
02393                // skip over the number of words to replace, making
02394                // sure to stop when there's no more string left
02395                // to skip
02396             for(thisWord = 0; 
02397                 (thisWord < wordsToReplace) && 
02398                    (temp.length() != 0);
02399                 thisWord++)
02400             {
02401                stripLeading(temp, delimiter);
02402                stripLeading(temp, firstWord(temp));
02403             }
02404             
02405                // add on any extra words at the end
02406             s.append(temp);
02407             
02408             return s;
02409          }
02410          catch(StringException &e)
02411          {
02412             GPSTK_RETHROW(e);
02413          }
02414          catch(std::exception &e)
02415          {
02416             StringException strexc("Exception thrown: " + std::string(e.what()));
02417             GPSTK_THROW(strexc);
02418          }
02419       }
02420 
02421       inline std::string doub2sci(const double& d, 
02422                              const std::string::size_type length, 
02423                              const std::string::size_type expLen,
02424                              const bool showSign,
02425               const bool checkSwitch)
02426       {
02427          std::string toReturn;
02428          short exponentLength = expLen;
02429             
02430             /* Validate the assumptions regarding the input arguments */
02431          if (exponentLength < 0) exponentLength = 1;
02432          if (exponentLength > 3 && checkSwitch) exponentLength = 3;
02433             
02434          std::stringstream c;
02435          c.setf(std::ios::scientific, std::ios::floatfield);
02436             
02437             // length - 3 for special characters ('.', 'e', '+' or '-')
02438             // - exponentlength (e04)
02439             // - 1 for the digit before the decimal (2.)
02440             // and if showSign == true,
02441             //    an extra -1 for '-' or ' ' if it's positive or negative
02442          int expSize = 0;
02443          if (showSign)
02444             expSize = 1;
02445          c.precision(length - 3 - exponentLength - 1 - expSize);
02446 
02447             
02448          c << d;
02449             
02450          c >> toReturn;
02451 
02452          return toReturn;
02453       }
02454 
02455       inline std::string doubleToScientific(const double& d,
02456                                             const std::string::size_type length,
02457                                             const std::string::size_type precision,
02458                                             const std::string::size_type explen,
02459                                             bool showPlus)
02460       {
02461          // get final exp length, precision and total length
02462          std::string::size_type elen = (explen > 0 ? (explen < 3 ? explen : 3) : 1);
02463          std::string::size_type prec = (precision > 0 ? precision : 1);
02464          std::string::size_type leng = (length > 0 ? length : 1);
02465 
02466          // i will be minimum length required with prec==1: force leng if necessary
02467          int i = (int(leng) - int(elen) - 4);
02468          if(showPlus) i--;
02469          if(i > 0 && leng < i) leng = std::string::size_type(i);
02470 
02471          // set up the stream for writing
02472          std::stringstream ss;
02473          ss << std::scientific << std::setprecision(prec);
02474          if(showPlus) ss << std::showpos;
02475 
02476          // write d to a string with precision, sign and in scientific notation
02477          ss << d;
02478 
02479          // now read that string
02480          std::string str1,str2;
02481          ss >> str1;
02482          std::string::size_type pos = str1.find_first_of("EDed");    // find exponent
02483          str2 = str1.substr(0,pos+2);        // str2 = +123.2345e+
02484          str1 = str1.substr(pos+2);          // str1 = exponent only
02485 
02486          // make the exponent length elen
02487          str2 += StringUtils::rightJustify(
02488                      StringUtils::asString(StringUtils::asInt(str1)),elen,'0');
02489 
02490          // pad if necessary
02491          if(str2.length() < leng) str2 = StringUtils::rightJustify(str2,leng);
02492 
02493          return str2;
02494       }
02495 
02496       inline std::string& sci2for(std::string& aStr, 
02497                              const std::string::size_type startPos,
02498                              const std::string::size_type length, 
02499                              const std::string::size_type expLen,
02500               const bool checkSwitch)
02501          throw(StringException)
02502       {
02503          try
02504          {
02505             std::string::size_type idx = aStr.find('.', startPos);
02506             int expAdd = 0;
02507             std::string exp;
02508             long iexp;
02509          //If checkSwitch is false, always redo the exponential. Otherwise,
02510          //set it to false. 
02511        bool redoexp=!checkSwitch;
02512             
02513                // Check for decimal place within specified boundaries
02514             if ((idx == 0) || (idx >= (startPos + length - expLen - 1)))
02515             {
02516                StringException e("sci2for: no decimal point in string");
02517                GPSTK_THROW(e);
02518             }
02519             
02520                // Here, account for the possibility that there are
02521                // no numbers to the left of the decimal, but do not
02522                // account for the possibility of non-scientific
02523                // notation (more than one digit to the left of the
02524                // decimal)
02525             if (idx > startPos)
02526             {
02527                redoexp = true;
02528                   // Swap digit and decimal.
02529                aStr[idx] = aStr[idx-1];
02530                aStr[idx-1] = '.';
02531                   // Only add one to the exponent if the number is non-zero
02532                if (asDouble(aStr.substr(startPos, length)) != 0.0)
02533                   expAdd = 1;
02534             }
02535             
02536             idx = aStr.find('e', startPos);
02537             if (idx == std::string::npos)
02538             {
02539                idx = aStr.find('E', startPos);
02540                if (idx == std::string::npos)
02541                {
02542                   StringException e("sci2for:no 'e' or 'E' in string");
02543                   GPSTK_THROW(e);
02544                }
02545             }
02546                // Change the exponent character to D normally, or E of checkSwitch is false.
02547        if (checkSwitch)
02548                aStr[idx] = 'D';
02549        else 
02550                aStr[idx] = 'E';
02551                
02552           // Change the exponent itself
02553             if (redoexp)
02554             {
02555                exp = aStr.substr(idx + 1, std::string::npos);
02556                iexp = asInt(exp);
02557                iexp += expAdd;
02558 
02559                aStr.erase(idx + 1);
02560                if (iexp < 0)
02561                {
02562                   aStr += "-";
02563                   iexp -= iexp*2;
02564                }
02565                else
02566                   aStr += "+";
02567                aStr += rightJustify(asString(iexp),expLen,'0');
02568 
02569             }
02570 
02571                // if the number is positive, append a space
02572                // (if it's negative, there's a leading '-'
02573             if (aStr[0] == '.')
02574             {
02575                aStr.insert((std::string::size_type)0, 1, ' ');
02576             }
02577        
02578           //If checkSwitch is false, add on one leading zero to the string
02579        if (!checkSwitch)
02580        {
02581           aStr.insert((std::string::size_type)1, 1, '0');
02582             }
02583        
02584        
02585             return aStr;
02586          }
02587          catch(StringException &e)
02588          {
02589             GPSTK_RETHROW(e);
02590          }
02591          catch(std::exception &e)
02592          {
02593             StringException strexc("Exception thrown: " + std::string(e.what()));
02594             GPSTK_THROW(strexc);
02595          }
02596       }  // end sci2for
02597 
02598 
02599       inline std::string doub2for(const double& d, 
02600                              const std::string::size_type length, 
02601                              const std::string::size_type expLen,
02602               const bool checkSwitch)
02603          throw(StringException)
02604       {
02605          try
02606          {
02607             short exponentLength = expLen;
02608             
02609                /* Validate the assumptions regarding the input arguments */
02610             if (exponentLength < 0) exponentLength = 1;
02611             if (exponentLength > 3 && checkSwitch) exponentLength = 3;
02612 
02613             std::string toReturn = doub2sci(d, length, exponentLength, true, checkSwitch);
02614             sci2for(toReturn, 0, length, exponentLength, checkSwitch);
02615          
02616             return toReturn;
02617          }
02618          catch(StringException &e)
02619          {
02620             GPSTK_RETHROW(e);
02621          }
02622          catch(std::exception &e)
02623          {
02624             StringException strexc("Exception thrown: " + std::string(e.what()));
02625             GPSTK_THROW(strexc);
02626          }
02627       }
02628       
02629       
02630       inline double for2doub(const std::string& aStr,
02631                              const std::string::size_type startPos,
02632                              const std::string::size_type length) 
02633       {
02634          std::string s(aStr, startPos, length);
02635          strip(s);
02636 
02637             // you can blame Rinex for these special checks
02638          if (s.empty())
02639          {
02640             return 0;
02641          }
02642 
02643          std::string::size_type pos = s.find_first_of("EDd");
02644          if (pos != std::string::npos)
02645          {
02646             s[pos] = 'e';
02647          }
02648          else
02649          {
02650                // just treat it like a double
02651             return asDouble(aStr.substr(startPos, length));
02652          }
02653          
02654          std::stringstream st;
02655          st << s;
02656          
02657          double d;
02658          st >> d;
02659          
02660          return d;
02661       }
02662 
02663       inline std::string printable(const std::string& aStr)
02664          throw(StringException)
02665       {
02666          try
02667          {
02668             std::string rv(aStr);
02669 
02670             for (int i = 0; i < (int)rv.length(); i++)
02671             {
02672                char c = rv[i];
02673                if (!isprint(c))
02674                {
02675                   if (iscntrl(c))
02676                   {
02677                      rv.replace(i,1,2,'^');
02678                      rv.replace(i+1,1,1, 64+(c));
02679                   }
02680                   else
02681                   {
02682                      std::string mess(c2x(rv.substr(i,1)));
02683                      rv.replace(i,1,"<"+mess+">");
02684                   }
02685                }
02686             }
02687 
02688             return rv;
02689          }
02690          catch(StringException &e)
02691          {
02692             GPSTK_RETHROW(e);
02693          }
02694          catch(std::exception &e)
02695          {
02696             StringException strexc("Exception thrown: " + std::string(e.what()));
02697             GPSTK_THROW(strexc);
02698          }
02699       }
02700 
02701       inline std::string& prettyPrint(std::string& aStr,
02702                                       const std::string& lineDelim,
02703                                       const std::string& indent,
02704                                       const std::string& firstIndent,
02705                                       const std::string::size_type len,
02706                                       const char wordDelim)
02707          throw(StringException)
02708       {
02709          try
02710          {
02711                // chop aStr up into words based on wordDelim
02712             std::list<std::string> wordList;
02713             std::string tempStr(aStr);
02714             stripLeading(tempStr, wordDelim);
02715             while (!tempStr.empty())
02716             {
02717                std::string theFirstWord = firstWord(tempStr,wordDelim);
02718                wordList.push_back(theFirstWord);
02719                stripLeading(tempStr, theFirstWord);
02720                stripLeading(tempStr, wordDelim);
02721             }
02722 
02723                // now reassemble the words into sentences
02724             std::string toReturn;
02725             std::string thisLine = firstIndent, lastLine;
02726             while (!wordList.empty())
02727             {
02728                lastLine = thisLine;
02729                if (!lastLine.empty())
02730                   thisLine += wordDelim;
02731                thisLine += wordList.front();
02732 
02733                if (thisLine.length() > len)
02734                {
02735                      // if the first word is longer than a line, just add it.
02736                      // if this is the first line, remember to add the indent.
02737                   if (lastLine.empty())
02738                   {
02739                      if (toReturn.empty())
02740                         lastLine += firstIndent;
02741                      lastLine = wordList.front();
02742                   }
02743 
02744                   toReturn += lastLine + lineDelim;
02745 
02746                   thisLine.erase();
02747                   lastLine.erase();
02748 
02749                   thisLine = indent;
02750                }
02751                else
02752                   wordList.erase(wordList.begin());
02753             }
02754             if (!thisLine.empty())
02755                toReturn += (thisLine + lineDelim);
02756 
02757             aStr = toReturn;
02758             return aStr;
02759          }
02760          catch(StringException &e)
02761          {
02762             GPSTK_RETHROW(e);
02763          }
02764          catch(std::exception &e)
02765          {
02766             StringException strexc("Exception thrown: " + std::string(e.what()));
02767             GPSTK_THROW(strexc);
02768          }
02769       }
02770 
02772 
02773    } // namespace StringUtils
02774 
02775 } // namespace gpstk
02776 #endif // GPSTK_STRINGUTILS_HPP
02777 
02778 
02779 

Generated on Mon May 20 03:31:13 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1