StarToken.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2013 Statoil ASA.
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef STAR_TOKEN_HPP
21 #define STAR_TOKEN_HPP
22 
23 #include <string>
24 #include <iostream>
25 #include <algorithm>
26 
27 #include <boost/lexical_cast.hpp>
28 
29 namespace Opm {
30  bool isStarToken(const std::string& token,
31  std::string& countString,
32  std::string& valueString);
33 
34  template <class T>
35  T readValueToken(const std::string& valueString) {
36  try {
37  return boost::lexical_cast<T>(valueString);
38  }
39  catch (boost::bad_lexical_cast&) {
40  throw std::invalid_argument("Unable to convert string '" + valueString + "' to typeid: " + typeid(T).name());
41  }
42  }
43 
44  template <>
45  inline double readValueToken<double>(const std::string& valueString) {
46  try {
47  return boost::lexical_cast<double>(valueString);
48  }
49  catch (boost::bad_lexical_cast&) {
50  // Eclipse supports Fortran syntax for specifying exponents of floating point
51  // numbers ('D' and 'E', e.g., 1.234d5) while C++ only supports the 'e' (e.g.,
52  // 1.234e5). the quick fix is to replace 'D' by 'E' and 'd' by 'e' before trying
53  // to convert the string into a floating point value. This may not be the most
54  // performant thing to do, but it is probably fast enough.
55  std::string vs(valueString);
56  std::replace(vs.begin(), vs.end(), 'D', 'E');
57  std::replace(vs.begin(), vs.end(), 'd', 'e');
58 
59  try { return boost::lexical_cast<double>(vs); }
60  catch (boost::bad_lexical_cast&) {
61  throw std::invalid_argument("Unable to convert string '" + valueString + "' to double");
62  }
63  }
64  }
65 
66  template <>
67  inline float readValueToken<float>(const std::string& valueString) {
68  return readValueToken<double>(valueString);
69  }
70 
71  template <>
72  inline std::string readValueToken<std::string>(const std::string& valueString) {
73  if (valueString.size() > 0 && valueString[0] == '\'') {
74  if (valueString.size() < 2 || valueString[valueString.size() - 1] != '\'')
75  throw std::invalid_argument("Unable to parse string '" + valueString + "' as a string token");
76  return valueString.substr(1, valueString.size() - 2);
77  }
78  else
79  return valueString;
80  }
81 
82 
83 class StarToken {
84 public:
85  StarToken(const std::string& token)
86  {
87  if (!isStarToken(token, m_countString, m_valueString))
88  throw std::invalid_argument("Token \""+token+"\" is not a repetition specifier");
89  init_(token);
90  }
91 
92  StarToken(const std::string& token, const std::string& countStr, const std::string& valueStr)
93  : m_countString(countStr)
94  , m_valueString(valueStr)
95  {
96  init_(token);
97  }
98 
99  size_t count() const {
100  return m_count;
101  }
102 
103  bool hasValue() const {
104  return !m_valueString.empty();
105  }
106 
107  // returns the coubt as rendered in the deck. note that this might be different
108  // than just converting the return value of count() to a string because an empty
109  // count is interpreted as 1...
110  const std::string& countString() const {
111  return m_countString;
112  }
113 
114  // returns the value as rendered in the deck. note that this might be different
115  // than just converting the return value of value() to a string because values
116  // might have different representations in the deck (e.g. strings can be
117  // specified with and without quotes and but spaces are only allowed using the
118  // first representation.)
119  const std::string& valueString() const {
120  return m_valueString;
121  }
122 
123 private:
124  // internal initialization method. the m_countString and m_valueString attributes
125  // must be set before calling this method.
126  void init_(const std::string& token) {
127  // special-case the interpretation of a lone star as "1*" but do not
128  // allow constructs like "*123"...
129  if (m_countString == "") {
130  if (m_valueString != "")
131  // TODO: decorate the deck with a warning instead?
132  throw std::invalid_argument("Not specifying a count also implies not specifying a value. Token: \'" + token + "\'.");
133 
134  // TODO: since this is explicitly forbidden by the documentation it might
135  // be a good idea to decorate the deck with a warning?
136  m_count = 1;
137  }
138  else {
139  m_count = boost::lexical_cast<int>(m_countString);
140 
141  if (m_count == 0)
142  // TODO: decorate the deck with a warning instead?
143  throw std::invalid_argument("Specifing zero repetitions is not allowed. Token: \'" + token + "\'.");
144  }
145  }
146 
147  ssize_t m_count;
148  std::string m_countString;
149  std::string m_valueString;
150 };
151 }
152 
153 
154 #endif
const std::string & valueString() const
Definition: StarToken.hpp:119
StarToken(const std::string &token, const std::string &countStr, const std::string &valueStr)
Definition: StarToken.hpp:92
Definition: Deck.hpp:29
Definition: StarToken.hpp:83
size_t count() const
Definition: StarToken.hpp:99
T readValueToken(const std::string &valueString)
Definition: StarToken.hpp:35
bool isStarToken(const std::string &token, std::string &countString, std::string &valueString)
bool hasValue() const
Definition: StarToken.hpp:103
StarToken(const std::string &token)
Definition: StarToken.hpp:85
const std::string & countString() const
Definition: StarToken.hpp:110
float readValueToken< float >(const std::string &valueString)
Definition: StarToken.hpp:67
double readValueToken< double >(const std::string &valueString)
Definition: StarToken.hpp:45