Skip to content
Snippets Groups Projects
Strings.cpp 40.6 KiB
Newer Older
#include "MantidKernel/Strings.h"
#include "MantidKernel/Exception.h"

#include <Poco/StringTokenizer.h>
#include <Poco/Path.h>

#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

#include <fstream>
#include <iomanip>
#include <iosfwd>
#include <iostream>
Alex Buts's avatar
Alex Buts committed
#include <list>
      //------------------------------------------------------------------------------------------------
      /** Loads the entire contents of a text file into a string
       *
       * @param filename :: full path to file
       * @return string contents of text file
       */
      std::string loadFile(const std::string & filename)
      {
        std::string retVal;
        std::string str;
        std::ifstream in;
        in.open(filename.c_str());
        getline(in,str);
        while ( in ) {
          retVal += str + "\n";
          getline(in,str);
        }
        in.close();
        return retVal;
      }
      //------------------------------------------------------------------------------------------------
      /** Return a string with all matching occurence-strings
       *
       * @param input :: input string
       * @param find_what :: will search for all occurences of this string
       * @param replace_with :: ... and replace them with this.
       * @return the modified string.
       */
      std::string replace(const std::string &input, const std::string &find_what, const std::string &replace_with)
      {
        std::string output = input;
        std::string::size_type pos=0;
        while((pos=output.find(find_what, pos))!=std::string::npos)
          output.erase(pos, find_what.length());
          output.insert(pos, replace_with);
          pos+=replace_with.length();
        }
        return output;
      }

      /**
       * Return a string with all occurrences of the characters in the input replaced by the replace string
       * @param input :: The input string to perform the replacement on
       * @param charStr :: Each occurrence of ANY character in this string within the input string will be replaced by substitute
       * @param substitute :: A substitute string
       * @return A new string with the characters replaced
       */
      MANTID_KERNEL_DLL std::string replaceAll(const std::string & input, const std::string & charStr, const std::string & substitute)
      {
        std::string replaced;
        replaced.reserve(input.size());
        std::string::const_iterator iend = input.end();
        for( std::string::const_iterator itr = input.begin(); itr != iend; ++itr )
          char inputChar = (*itr);
          if( charStr.find_first_of(inputChar) == std::string::npos ) // Input string char is not one of those to be replaced
          {
            replaced.push_back(inputChar);
          }
          else
          {
            replaced.append(substitute);
          }
        }
        return replaced;
      }



      //------------------------------------------------------------------------------------------------
      /**
       * Function to convert a number into hex
       * output (and leave the stream un-changed)
       * @param OFS :: Output stream
       * @param n :: Integer to convert
       * \todo Change this to a stream operator
       */
      void printHex(std::ostream& OFS,const int n)
      {
        std::ios_base::fmtflags PrevFlags=OFS.flags();
        OFS<<"Ox";
        OFS.width(8);
        OFS.fill('0');
        hex(OFS);
        OFS << n;
        OFS.flags(PrevFlags);
        return;
      }

      //------------------------------------------------------------------------------------------------
      /**
       * Removes the multiple spaces in the line
       * @param Line :: Line to process
       * @return String with single space components
       */
      std::string stripMultSpc(const std::string& Line)
      {
        std::string Out;
        int spc(1);
        int lastReal(-1);
        for(unsigned int i=0;i<Line.length();i++)
          if (Line[i]!=' ' && Line[i]!='\t' &&
              Line[i]!='\r' &&  Line[i]!='\n')
          {
            lastReal=i;
            spc=0;
            Out+=Line[i];
          }
          else if (!spc)
          {
            spc=1;
            Out+=' ';
          }
        }
        lastReal++;
        if (lastReal<static_cast<int>(Out.length()))
          Out.erase(lastReal);
        return Out;
      }

      //------------------------------------------------------------------------------------------------
      //------------------------------------------------------------------------------------------------
      /**
       *  Checks that as least cnt letters of
       *  works is part of the string. It is currently
       *  case sensitive. It removes the Word if found
       *  @param Line :: Line to process
       *  @param Word :: Word to use
       * @param cnt :: Length of Word for significants [default =4]
       *  @retval 1 on success (and changed Line)
       *  @retval 0 on failure
       */
      int extractWord(std::string& Line,const std::string& Word,const int cnt)
      {
        if (Word.empty())
          return 0;

        size_t minSize(cnt>static_cast<int>(Word.size()) ?  Word.size() : cnt);
        std::string::size_type pos=Line.find(Word.substr(0,minSize));
        if (pos==std::string::npos)
          return 0;
        // Pos == Start of find
        size_t LinePt=minSize+pos;
        for(;minSize<Word.size() && LinePt<Line.size()
        && Word[minSize]==Line[LinePt];LinePt++,minSize++)
        }

        Line.erase(pos,LinePt-(pos-1));
        return 1;
      }

      //------------------------------------------------------------------------------------------------
      /** If a word ends with a number representing a positive integer, return
       * the value of that int.
       *
       * @param word :: string possibly ending in a number
       * @return the number, or -1 if it does not end in a number
       */
      int endsWithInt(const std::string & word)
      {
        if (word.empty())
          return -1;
        int out = -1;
        // Find the index of the first number in the string (if any)
        int firstNumber = int(word.size());
        for (int i=int(word.size())-1; i>=0; i--)
          char c = word[i];
          if ((c > '9') || (c < '0'))
            break;
          firstNumber = i;
        // Convert the string of decimals to an int
        if (firstNumber < int(word.size()))
          std::string part = word.substr(firstNumber, word.size()-firstNumber);
          if (!convert(part, out))
            return -1;
        }
        return out;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Check to see if S is the same as the
       *  first part of a phrase. (case insensitive)
       *  @param S :: string to check
       *  @param fullPhrase :: complete phrase
       *  @return 1 on success
       */
      int confirmStr(const std::string& S,const std::string& fullPhrase)
      {
        const size_t nS(S.length());
        const size_t nC(fullPhrase.length());
        if (nS>nC || nS==0)
          return 0;
        for(size_t i=0;i<nS;i++)
          if (S[i]!=fullPhrase[i])
            return 0;
        return 1;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Gets a line and determine if there is addition component to add
       *  in the case of a very long line.
       *  @param fh :: input stream to get line
       *  @param Out :: string up to last 'tab' or ' '
       *  @param Excess :: string after 'tab or ' '
       *  @param spc :: number of char to try to read
       *  @retval 1 :: more line to be found
       *  @retval -1 :: Error with file
       *  @retval 0  :: line finished.
       */
      int getPartLine(std::istream& fh,std::string& Out,std::string& Excess,const int spc)
      {
        //std::string Line;
        if (fh.good())
          char* ss=new char[spc+1];
          const int clen = static_cast<int>(spc-Out.length());
          fh.getline(ss,clen,'\n');
          ss[clen+1]=0;           // incase line failed to read completely
          Out+=static_cast<std::string>(ss);
          delete [] ss;
          // remove trailing comments
          std::string::size_type pos = Out.find_first_of("#!");
          if (pos!=std::string::npos)
          {
            Out.erase(pos);
            return 0;
          }
          if (fh.gcount()==clen-1)         // cont line
          {
            pos=Out.find_last_of("\t ");
            if (pos!=std::string::npos)
            {
              Excess=Out.substr(pos,std::string::npos);
              Out.erase(pos);
            }
            else
              Excess.erase(0,std::string::npos);
            fh.clear();
            return 1;
          }
          return 0;
        }
        return -1;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Removes all spaces from a string
       * except those with in the form '\ '
       *  @param CLine :: Line to strip
       *  @return String without space
       */
      std::string removeSpace(const std::string& CLine)
      {
        std::string Out;
        char prev='x';
        for(unsigned int i=0;i<CLine.length();i++)
        {
          if (!isspace(CLine[i]) || prev=='\\')
          {
            Out+=CLine[i];
            prev=CLine[i];
          }
        }
        return Out;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Reads a line from the stream of max length spc.
       *  Trailing comments are removed. (with # or ! character)
       *  @param fh :: already open file handle
       *  @param spc :: max number of characters to read
       *  @return String read.
       */
      std::string getLine(std::istream& fh,const int spc)
      {
        char* ss=new char[spc+1];
        std::string Line;
        if (fh.good())
        {
          fh.getline(ss,spc,'\n');
          ss[spc]=0;           // incase line failed to read completely
          Line=ss;
          // remove trailing comments
          std::string::size_type pos = Line.find_first_of("#!");
          if (pos!=std::string::npos)
            Line.erase(pos);
        }
        delete [] ss;
        return Line;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Determines if a string is only spaces
       *  @param A :: string to check
       *  @return 1 on an empty string , 0 on failure
       */
      int isEmpty(const std::string& A)
      {
        std::string::size_type pos=
            A.find_first_not_of(" \t");
        return (pos!=std::string::npos) ? 0 : 1;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  removes the string after the comment type of
       *  '$ ' or '!' or '#  '
       *  @param A :: String to process
       */
      void stripComment(std::string& A)
      {
        std::string::size_type posA=A.find("$ ");
        std::string::size_type posB=A.find("# ");
        std::string::size_type posC=A.find("!");
        if (posA>posB)
          posA=posB;
        if (posA>posC)
          posA=posC;
        if (posA!=std::string::npos)
          A.erase(posA,std::string::npos);
        return;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Returns the string from the first non-space to the
       *  last non-space
       * @param A :: string to process
       * @return shortened string
       */
      std::string fullBlock(const std::string& A)
      {
        return strip(A);
      }

      //------------------------------------------------------------------------------------------------
      /** Returns the string from the first non-space to the
       *  last non-space
       *  @param A :: string to process
       *  @return shortened string
       */
      std::string strip(const std::string& A)
      {
        std::string::size_type posA=A.find_first_not_of(" ");
        std::string::size_type posB=A.find_last_not_of(" ");
        if (posA==std::string::npos)
          return "";
        return A.substr(posA,1+posB-posA);
      }


      //------------------------------------------------------------------------------------------------
      /**
       *  Write out the line in the limited form for MCNPX
       *  ie initial line from 0->72 after that 8 to 72
       *  (split on a space or comma)
       *  @param Line :: full MCNPX line
       *  @param OX :: ostream to write to
       */
      void writeMCNPX(const std::string& Line,std::ostream& OX)
      {
        const int MaxLine(72);
        std::string::size_type pos(0);
        std::string X=Line.substr(0,MaxLine);
        std::string::size_type posB=X.find_last_of(" ,");
        int spc(0);
        while (posB!=std::string::npos &&
            static_cast<int>(X.length())>=MaxLine-spc)
        {
          pos+=posB+1;
          if (!isspace(X[posB]))
            posB++;
          const std::string Out=X.substr(0,posB);
          if (!isEmpty(Out))
          {
            if (spc)
              OX<<std::string(spc,' ');
            OX<<X.substr(0,posB)<<std::endl;
          }
          spc=8;
          X=Line.substr(pos,MaxLine-spc);
          posB=X.find_last_of(" ,");
        }
        if (!isEmpty(X))
        {
          if (spc)
            OX<<std::string(spc,' ');
          OX<<X<<std::endl;
        }
        return;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Splits the sting into parts that are space delminated.
       *  @param Ln :: line component to strip
       *  @return vector of components
       */
      std::vector<std::string> StrParts(std::string Ln)
        std::vector<std::string> Out;
        std::string Part;
        while(section(Ln,Part))
          Out.push_back(Part);
        return Out;
      }

      /**
       * Splits a string into key value pairs and returns them as a map. Whitespace between separators is ignored
       * @param input :: The string containing the key/values
       * @param keyValSep :: The separator that splits a key and value [default: "="]
       * @param listSep :: The separator that splits elements of the list [default: ","]
       * @returns A map of keys->values
       */
      std::map<std::string,std::string>
      splitToKeyValues(const std::string & input, const std::string & keyValSep, const std::string & listSep)
      {
        std::map<std::string,std::string> keyValues;
        const int splitOptions = Poco::StringTokenizer::TOK_IGNORE_EMPTY + Poco::StringTokenizer::TOK_TRIM;
        Poco::StringTokenizer listSplitter(input, listSep);
        for(auto iter = listSplitter.begin(); iter != listSplitter.end(); ++iter)
        {
          Poco::StringTokenizer keyValSplitter(*iter, keyValSep, splitOptions);
          if(keyValSplitter.count() == 2)
          {
            keyValues[keyValSplitter[0]] = keyValSplitter[1];
          }
        }

        return keyValues;
      }


      //------------------------------------------------------------------------------------------------
      /**
       *  Converts a vax number into a standard unix number
       *  @param A :: float number as read from a VAX file
       *  @return float A in IEEE little eindian format
       */
      float getVAXnum(const float A)
        union
        {
          //char a[4];
          float f;
          int ival;
        } Bd;

        int sign,expt,fmask;
        float frac;
        double onum;

        Bd.f=A;
        sign  = (Bd.ival & 0x8000) ? -1 : 1;
        expt = ((Bd.ival & 0x7f80) >> 7);   //reveresed ?
        if (!expt)
          return 0.0;

        fmask = ((Bd.ival & 0x7f) << 16) | ((Bd.ival & 0xffff0000) >> 16);
        expt-=128;
        fmask |=  0x800000;
        frac = (float) fmask  / 0x1000000;
        onum = frac * static_cast<float>(sign) * pow(2.0,expt);
        return (float) onum;
      }


      //------------------------------------------------------------------------------------------------
      /**
       *  Takes a character string and evaluates
       *  the first [typename T] object. The string is then
       *  erase upt to the end of number.
       *  The diffierence between this and section is that
       *  it allows trailing characters after the number.
       *  @param out :: place for output
       *  @param A :: string to process
       *  @return 1 on success 0 on failure
       */
      template<typename T>
      int sectPartNum(std::string& A,T& out)
      {
        if (A.empty())
          return 0;

        std::istringstream cx;
        T retval;
        cx.str(A);
        cx.clear();
        cx>>retval;
        const std::streamoff xpt = cx.tellg();
        if (xpt < 0)
          return 0;
        A.erase(0,static_cast<unsigned int>(xpt));
        out=retval;
        return 1;
      }

      //------------------------------------------------------------------------------------------------
      /**
       *  Takes a character string and evaluates
       *  the first [typename T] object. The string is then filled with
       *  spaces upto the end of the [typename T] object
       *  @param out :: place for output
       *  @param cA :: char array for input and output.
       *  @return 1 on success 0 on failure
       */
      template<typename T>
      int section(char* cA,T& out)
      {
        if (!cA) return 0;
        std::string sA(cA);
        const int item(section(sA,out));
        if (item)
        {
          strcpy(cA,sA.c_str());
          return 1;
        }

      /**
       *  takes a character string and evaluates
       *  the first \<T\> object. The string is then filled with
       *  spaces upto the end of the \<T\> object
       *  @param out :: place for output
       *  @param A :: string for input and output.
       *  @return 1 on success 0 on failure
       */
      template<typename T>
      int section(std::string& A,T& out)
        if (A.empty()) return 0;
        std::istringstream cx;
        T retval;
        cx.str(A);
        cx.clear();
        cx>>retval;
        if (cx.fail())
          return 0;
        const std::streamoff xpt = cx.tellg();
        const char xc = static_cast<char>(cx.get());
        if (!cx.fail() && !isspace(xc))
          return 0;
        A.erase(0, static_cast<unsigned int>(xpt));
        out=retval;
        return 1;
      }

      /**
       *  Takes a character string and evaluates
       *  the first [T] object. The string is then filled with
       *  spaces upto the end of the [T] object.
       *  This version deals with MCNPX numbers. Those
       *  are numbers that are crushed together like
       *  - 5.4938e+04-3.32923e-6
       *  @param out :: place for output
       *  @param A :: string for input and output.
       *  @return 1 on success 0 on failure
       */
      template<typename T>
      int sectionMCNPX(std::string& A,T& out)
      {
        if (A.empty()) return 0;
        std::istringstream cx;
        T retval;
        cx.str(A);
        cx.clear();
        cx>>retval;
        if (!cx.fail())
        {
          const std::streamoff xpt = cx.tellg();
          if( xpt < 0 )
          {
            return 0;
          }
          const char xc=static_cast<char>(cx.get());
          if (!cx.fail() && !isspace(xc) && (xc!='-' || xpt<5))
          {
            return 0;
          }
          A.erase(0, static_cast<unsigned int>(xpt));
          out=retval;
          return 1;
        }
      //------------------------------------------------------------------------------------------------
      /**
       *  Takes a character string and evaluates
       *  the first [typename T] object. The string is then
       *  erase upto the end of number.
       *  The diffierence between this and convert is that
       *  it allows trailing characters after the number.
       *  @param out :: place for output
       *  @param A :: string to process
       *  @retval number of char read on success
       *  @retval 0 on failure
       */
      template<typename T>
      int convPartNum(const std::string& A,T& out)
      {
        if (A.empty()) return 0;
        std::istringstream cx;
        T retval;
        cx.str(A);
        cx.clear();
        cx>>retval;
        // If we have reached the end of the stream, then we need to clear the error as
        // it will cause the tellg() call to return -1.  Not pretty but works for now.
        cx.clear();
        const std::streamoff xpt = cx.tellg();
        if (xpt<0)
          return 0;
        out=retval;
        return static_cast<int>(xpt);
      }
      //------------------------------------------------------------------------------------------------
      /**
       *  Convert a string into a value
       *  @param A :: string to pass
       *  @param out :: value if found
       *  @return 0 on failure 1 on success
       */
      template<typename T>
      int convert(const std::string& A,T& out)
      {
        if (A.empty()) return 0;
        std::istringstream cx;
        T retval;
        cx.str(A);
        cx.clear();
        cx>>retval;
        if (cx.fail())
          return 0;
        const char clast = static_cast<char>(cx.get());
        if (!cx.fail() && !isspace(clast))
          return 0;
        out=retval;
        return 1;
      }
      //------------------------------------------------------------------------------------------------
      /**
       *  Convert a string into a value
       *  @param A :: string to pass
       *  @param out :: value if found
       *  @return 0 on failure 1 on success
       */
      template<typename T>
      int convert(const char* A,T& out)
      {
        // No string, no conversion
        if (!A) return 0;
        std::string Cx=A;
        return convert(Cx,out);
      }
      //------------------------------------------------------------------------------------------------
      /** Convert a number or other value to a string
       *
       * @param value :: templated value (e.g. a double) to convert
       * @return a string
       */
      template<typename T>
Nick Draper's avatar
Nick Draper committed
      std::string toString(const T &value)
      {
        std::ostringstream mess;
        mess << value;
        return mess.str();
      }

      /**
       * This assumes that the vector is sorted.
       *
       * @param value :: templated value (only works for integer types) to convert.
       * @return A reduced string representation.
       */
      template<typename T>
      std::string toString(const std::vector<T> &value)
        std::ostringstream mess;
        auto it = value.begin();
        auto last = value.end();
        T start;
        T stop;
        for (; it != last; ++it)
          start = *(it);
          stop = start;
          for ( ; it != last; ++it)
          {
            if( it+1 == last )
              break;
            else if ( (stop + static_cast<T>(1)) == *(it+1) )
              stop = *(it+1);
            else
              break;
          }
          mess << start;
          if (start != stop)
            mess << "-" << stop;
          if (it+1 != last)
            mess << ",";
        }
        return mess.str();
      }
      template<typename T>
      std::string toString(const std::set<T> &value)
      {
        return toString(std::vector<T>(value.begin(), value.end()));
      }
      //------------------------------------------------------------------------------------------------
      /**
       *  Write out the three vectors into a file of type dc 9
       *  @param step :: parameter to control x-step (starts from zero)
       * @param Y :: Y column
       *  @param Fname :: Name of the file
       *  @return 0 on success and -ve on failure
       */
      template<template<typename T,typename A> class V,typename T,typename A>
      int writeFile(const std::string& Fname,const T &step, const V<T,A>& Y)
      {
        V<T,A> Ex;   // Empty vector
        V<T,A> X;    // Empty vector
        for(unsigned int i=0;i<Y.size();i++)
          X.push_back(i*step);
        return writeFile(Fname,X,Y,Ex);
      }
      //------------------------------------------------------------------------------------------------
      /**
       *  Write out the three vectors into a file of type dc 9
       *  @param X :: X column
       *  @param Y :: Y column
       *  @param Fname :: Name of the file
       *  @return 0 on success and -ve on failure
       */
      template<template<typename T,typename A> class V,typename T,typename A>
      int writeFile(const std::string& Fname,const V<T,A>& X,const V<T,A>& Y)
      {
        V<T,A> Ex;   // Empty vector/list
        return writeFile(Fname,X,Y,Ex);  // don't need to specific ??
      }
      //------------------------------------------------------------------------------------------------
      /**
       *  Write out the three container into a file with
       *  column free-formated data in the form :
       *   - X  Y Err
       *   If Err does not exist (or is short) 0.0 is substituted.
       *  @param X :: X column
       *  @param Y :: Y column
       *  @param Err :: Err column
       *  @param Fname :: Name of the file
       *  @return 0 on success and -ve on failure
       */
      template<template<typename T,typename A> class V,typename T,typename A>
      int writeFile(const std::string& Fname,const V<T,A>& X,const V<T,A>& Y,const V<T,A>& Err)
      {
        const size_t Npts(X.size()>Y.size() ? Y.size() : X.size());
        const size_t Epts(Npts > Err.size() ? Err.size() : Npts);
        FX.open(Fname.c_str());
        if (!FX.good())
          return -1;
        FX<<"# "<<Npts<<" "<<Epts<<std::endl;
        FX.precision(10);
        FX.setf(std::ios::scientific,std::ios::floatfield);
        typename V<T,A>::const_iterator xPt=X.begin();
        typename V<T,A>::const_iterator yPt=Y.begin();
        typename V<T,A>::const_iterator ePt=(Epts ? Err.begin() : Y.begin());
        // Double loop to include/exclude a short error stack
        size_t eCount=0;
        for(;eCount<Epts;eCount++)
        {
          FX<<(*xPt)<<" "<<(*yPt)<<" "<<(*ePt)<<std::endl;
          ++xPt;
          ++yPt;
          ++ePt;
        }
        for(;eCount<Npts;eCount++)
        {
          FX<<(*xPt)<<" "<<(*yPt)<<" 0.0"<<std::endl;
          ++xPt;
          ++yPt;
        }
        FX.close();
        return 0;
      }
      //------------------------------------------------------------------------------------------------
      /**
       *  Call to read in various values in position x1,x2,x3 from the
       *  line. Note to avoid the dependency on crossSort this needs
       *  to be call IN ORDER
       *  @param Line :: string to read
       *  @param Index :: Indexes to read
       *  @param Out :: OutValues [unchanged if not read]
       *  @retval 0 :: success
       *  @retval -ve on failure.
       */
      template<typename T>
      int setValues(const std::string& Line,const std::vector<int>& Index,std::vector<T>& Out)
      {
        if (Index.empty())
          return 0;

        if(Out.size()!=Index.size())
          return -1;
        //    throw ColErr::MisMatch<int>(Index.size(),Out.size(),
        //        "Mantid::Kernel::Strings::setValues");

        std::string modLine=Line;
        std::vector<int> sIndex(Index);     // Copy for sorting
        std::vector<int> OPt(Index.size());
        for(unsigned int i=0;i<Index.size();i++)
          OPt[i]=i;


        //  mathFunc::crossSort(sIndex,OPt);

        typedef std::vector<int>::const_iterator iVecIter;
        std::vector<int>::const_iterator sc=sIndex.begin();
        std::vector<int>::const_iterator oc=OPt.begin();
        int cnt(0);
        T value;
        std::string dump;
        while(sc!=sIndex.end() && *sc<0)
        {
        while(sc!=sIndex.end())
        {
          if (*sc==cnt)
          {
            if (!section(modLine,value))
              return static_cast<int>(-1-distance(static_cast<iVecIter>(sIndex.begin()),sc));
            // this loop handles repeat units
            do
            {
              Out[*oc]=value;
            } while (sc!=sIndex.end() && *sc==cnt);
          }
          else
          {
            if (!section(modLine,dump))
              return static_cast<int>(-1-distance(static_cast<iVecIter>(sIndex.begin()),sc));
          }
          cnt++;         // Add only to cnt [sc/oc in while loop]
        }
        // Success since loop only gets here if sc is exhaused.
Alex Buts's avatar
Alex Buts committed
        return 0;
      }





      //-----------------------------------------------------------------------------------------------
      /** Get a word from a line and strips spaces
       *
       * @param in :: stream input
       * @param consumeEOL :: set to true to remove the new lines at the end of the line
       * @return a string with the word read in
       */
      std::string getWord( std::istream &in ,  bool consumeEOL )
      {
        std::string s;
        char c = 0;
        if( in.good() )
          for(  c = static_cast<char>(in.get()) ; c == ' ' && in.good() ; c = static_cast<char>(in.get()) )
          {}
        else
          return std::string();

        if( c == '\n' )
        {
          if( !consumeEOL )
            in.putback( c );

          return std::string();
        }

        s.push_back( c );

        if( in.good() )
          for(  c = static_cast<char>(in.get()) ; in.good()&&c != ' ' && c != '\n' && c != '\r' ; c = static_cast<char>(in.get()) )
            s.push_back( c );

        if( ((c == '\n') || (c == '\r')) && !consumeEOL )
          in.putback( c );

        return s;
      }

      //-----------------------------------------------------------------------------------------------
      /** Read up to the eol
       *
       * @param in :: stream input
       * @param ConsumeEOL :: set to true to remove the new lines at the end of the line
       */
      void readToEndOfLine( std::istream& in ,  bool ConsumeEOL )
      {
        while( in.good() && getWord( in ,  false ).length() > 0  )
          getWord( in ,  false );
        if( !ConsumeEOL )
          return ;
        getWord( in ,  true );
      }

      /**
       * Function parses a path, placed into input string "path" and returns vector of the folders contributed into the path
       *  @param path :: the string containing input path, found in path string, if they are separated by \ or / symbols.
       *  Treats special symbols, if defined in the input string as path-es
       *  returns 0 for empty input string
       *  @param path_components :: holder for the individual folders in the path
       *  used to generate path in hdf file, so the resulting path has to obey hdf constrains;
       */
      size_t split_path(const std::string &path, std::vector<std::string> &path_components)
      {
        if(path.empty()){
          path_components.resize(0);
          return 0;
        }
        // convert Windows path into the unix one
        std::string working_path(path);
        for(size_t i=0;i<path.size();i++){
          if(working_path[i]<0x20||working_path[i]>0x7E)working_path[i]='_';
          if(working_path[i]=='\\')working_path[i]='/';
          if(working_path[i]==' ')working_path[i]='_';
        }


        // path start with relative character, and we need to convert it into full path
        if(path[0]=='.'){
          // get absolute path using working directory as base;
          Poco::Path absol;
          absol = absol.absolute();
          working_path = absol.toString(Poco::Path::PATH_UNIX)+working_path;
        }
        // as poco splt using regular expressions is doing some rubbish, we need to do split manually
        // code below implements perl split(/\\//,string) commamd. (\\ has been converted to / above)
        std::list<int64_t> split_pos;
        split_pos.push_back(-1);