Nektar++
ParseUtils.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ParseUtils.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: This file contains various parsing utilities, primarily used
32 // by SpatialDomains to process input files.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <sstream>
37 #include <boost/core/ignore_unused.hpp>
38 #include <boost/spirit/include/qi_core.hpp>
39 #include <boost/spirit/include/qi_auto.hpp>
41 
42 namespace qi = boost::spirit::qi;
43 namespace fusion = boost::fusion;
44 
45 namespace Nektar
46 {
47 
48 /**
49  * @brief Helper functors for holding a vector of numbers to be parsed by
50  * boost::spirit.
51  *
52  * @see ParseUtils::GenerateSeqVector
53  */
54 template<typename T>
56 {
57  PushBackFunctor(std::vector<T> &in) : m_vec(in) {}
58 
59  /**
60  * @brief Pushes back values onto #m_vec as given by @p num.
61  */
62  void operator()(T num) const
63  {
64  m_vec.push_back(num);
65  }
66 
67  /**
68  * @brief Pushes back values onto #m_vec between the range supplied by @p
69  * num. Valid for only integer types.
70  */
71  void operator()(fusion::vector<T, T> num) const
72  {
73  static_assert(std::is_integral<T>::value, "Integer type required.");
74  for (T i = fusion::at_c<0>(num); i <= fusion::at_c<1>(num); ++i)
75  {
76  m_vec.push_back(i);
77  }
78  }
79 private:
80  // Do not allow assignment
82  {
83  boost::ignore_unused(src);
84  return *this;
85  }
86 
87  /// Storage vector that will hold parsed variables from boost::spirit.
88  std::vector<T> &m_vec;
89 };
90 
91 /**
92  * @brief Takes a comma-separated compressed string and converts it to entries
93  * in a vector.
94  *
95  * This routine is the inverse of ParseUtils::GenerateSeqString. For example,
96  *
97  * std::string input = "1-4,6-8,5,2,3";
98  * std::vector<unsigned int> output;
99  * ParseUtils::GenerateSeqString(input, output);
100  *
101  * produces an `output` vector with the entries `{1,2,3,4,6,7,8,5,2,3}`.
102  *
103  * @param str Input CSV string of unsigned integers.
104  * @param out Output vector.
105  *
106  * @see ParseUtils::GenerateSeqString
107  */
109  const std::string &str, std::vector<unsigned int> &out)
110 {
111  PushBackFunctor<unsigned int> f1(out), f2(out);
112 
113  auto it = str.begin();
114  bool success = qi::phrase_parse(
115  it,
116  str.end(),
117  ((qi::uint_ >> '-' >> qi::uint_)[f2] | qi::uint_[f1]) % ',',
118  qi::ascii::space);
119 
120  return success && it == str.end();
121 }
122 
123 /**
124  * @brief Takes a comma-separated string and converts it to entries in a vector.
125  *
126  * This routine splits up a comma-separated string and returns a vector with the
127  * entries. Template specialisations should be defined in this file (and not in
128  * the header file) as the use of boost::spirit::qi makes compilation times
129  * quite slow.
130  *
131  * @param str Input CSV string.
132  * @param out Output vector.
133  */
134 template <typename T>
135 bool ParseUtils::GenerateVector(const std::string &str, std::vector<T> &out)
136 {
137  auto it = str.begin();
138  bool success = qi::phrase_parse(
139  it, str.end(), qi::auto_ % ',', qi::ascii::space, out);
140  return success && it == str.end();
141 }
142 
143 template LIB_UTILITIES_EXPORT bool ParseUtils::GenerateVector<int>(
144  const std::string &str, std::vector<int> &out);
145 template LIB_UTILITIES_EXPORT bool ParseUtils::GenerateVector<long>(
146  const std::string &str, std::vector<long> &out);
147 template LIB_UTILITIES_EXPORT bool ParseUtils::GenerateVector<unsigned int>(
148  const std::string &str, std::vector<unsigned int> &out);
149 template LIB_UTILITIES_EXPORT bool ParseUtils::GenerateVector<double>(
150  const std::string &str, std::vector<double> &out);
151 template LIB_UTILITIES_EXPORT bool ParseUtils::GenerateVector<float>(
152  const std::string &str, std::vector<float> &out);
153 
154 /**
155  * @brief Specialised version of ParseUtils::GenerateVector for std::string.
156  *
157  * This routine specialises for the std::string data type as this type is not
158  * supported by boost::spirit::qi::auto_.
159  */
160 template <> LIB_UTILITIES_EXPORT
161 bool ParseUtils::GenerateVector(const std::string &str,
162  std::vector<std::string> &out)
163 {
164  auto it = str.begin();
165  bool success = qi::phrase_parse(
166  it, str.end(), +~qi::char_(",") % ',', qi::ascii::space, out);
167  return success && it == str.end();
168 }
169 
170 }
Helper functors for holding a vector of numbers to be parsed by boost::spirit.
Definition: ParseUtils.cpp:55
void operator()(fusion::vector< T, T > num) const
Pushes back values onto m_vec between the range supplied by num. Valid for only integer types...
Definition: ParseUtils.cpp:71
void operator()(T num) const
Pushes back values onto m_vec as given by num.
Definition: ParseUtils.cpp:62
std::vector< T > & m_vec
Storage vector that will hold parsed variables from boost::spirit.
Definition: ParseUtils.cpp:88
PushBackFunctor & operator=(const PushBackFunctor &src)
Definition: ParseUtils.cpp:81
#define LIB_UTILITIES_EXPORT
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
Definition: ParseUtils.cpp:135
PushBackFunctor(std::vector< T > &in)
Definition: ParseUtils.cpp:57
static bool GenerateSeqVector(const std::string &str, std::vector< unsigned int > &out)
Takes a comma-separated compressed string and converts it to entries in a vector. ...
Definition: ParseUtils.cpp:108