irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

irods_kvp_string_parser.cpp
Go to the documentation of this file.
1 #include "irods_log.hpp"
2 
3 // =-=-=-=-=-=-=-
5 #include "irods_stacktrace.hpp"
6 
7 // =-=-=-=-=-=-=-
8 // rods includes
9 #include "rodsErrorTable.h"
10 #include <sstream>
11 #include <set>
12 #include <boost/algorithm/string/predicate.hpp>
13 
14 namespace irods {
17  std::string kvp_delimiter() {
18  return KVP_DEF_DELIMITER;
19  }
20 
23  std::string kvp_association() {
24  return KVP_DEF_ASSOCIATION;
25  }
26 
29  std::string kvp_escape() {
30  return KVP_DEF_ESCAPE;
31  }
32 
37  const std::string& _token,
38  kvp_map_t& _kvp,
39  const std::string& _assoc ) {
40  // =-=-=-=-=-=-=-
41  // split along the associative delimiter and place into the map
42  std::vector< std::string > token_vec;
43  try {
44  boost::split( token_vec, _token, boost::is_any_of( _assoc ), boost::token_compress_on );
45  }
46  catch ( const boost::bad_function_call& ) {
47  rodsLog( LOG_ERROR, "boost::split threw boost::bad_function_call" );
48  token_vec.clear();
49  }
50  if ( token_vec.size() != 2 ) {
51  std::stringstream msg;
52  msg << "token vector size != 2 during parsing of ["
53  << _token
54  << "]";
55  return ERROR(
57  msg.str() );
58  }
59 
60  _kvp[ token_vec[0] ] = token_vec[1];
61 
62  return SUCCESS();
63 
64  } // parse_token_into_kvp
65 
70  const std::string& _string,
71  kvp_map_t& _kvp,
72  const std::string& _assoc,
73  const std::string& _delim ) {
74 
75  // =-=-=-=-=-=-=-
76  // parse the string into tokens split by the delimiter
77  std::vector< std::string > tokens;
78  try {
79  boost::split( tokens, _string, boost::is_any_of( _delim ) );
80  }
81  catch ( const boost::bad_function_call& ) {
82  rodsLog( LOG_ERROR, "boost::split threw boost::bad_function_call" );
83  return ERROR(BAD_FUNCTION_CALL, "bad function call to boost::split in parse_kvp_string");
84  }
85  for( const auto& token : tokens ) {
86  if( token.empty() ) {
87  continue;
88  }
89 
90  // =-=-=-=-=-=-=-
91  // now that the string is broken into tokens we need to
92  // extract the key and value to put them into the map
93  error ret = parse_token_into_kvp( token, _kvp, _assoc );
94  if( !ret.ok() ) {
95  return PASS( ret );
96  }
97  }
98 
99  return SUCCESS();
100 
101  } // parse_kvp_string
102 
107  const std::string& _string,
108  kvp_map_t& _kvp,
109  const std::string& _assoc,
110  const std::string& _delim,
111  const std::string& _escape ) {
112  if ( _delim.empty() || _assoc.empty() || _escape.empty() ) {
113  return ERROR( SYS_BAD_INPUT, "_delim, _assoc, and _escape may not be empty" );
114  }
115  if ( _delim == _escape || _delim == _assoc || _assoc == _escape ||
116  boost::starts_with( _assoc, _delim ) || boost::starts_with( _delim, _assoc ) ) {
117  return ERROR( SYS_BAD_INPUT, "_delim, _assoc, and _escape must all be distinct in calls to parse_kvp_string" );
118  }
119  if ( _assoc.find( _delim ) != std::string::npos || _assoc.find( _escape ) != std::string::npos ||
120  _delim.find( _assoc ) != std::string::npos || _delim.find( _escape ) != std::string::npos ||
121  _escape.find( _assoc ) != std::string::npos || _escape.find( _delim ) != std::string::npos ) {
122  return ERROR( SYS_BAD_INPUT, "_delim, _assoc, and _escape may not contain each other in calls to parse_kvp_string" );
123  }
124  std::stringstream key;
125  std::stringstream value;
126  bool assoc_encountered = false;
127  for ( size_t i = 0; i < _string.size(); ) {
128  if ( boost::starts_with( _string.substr( i ), _escape ) ) {
129  i += _escape.size();
130  if ( i >= _string.size() ) {
131  return ERROR( SYS_BAD_INPUT, "kvp ended in an unescaped _escape token" );
132  }
133  }
134  else if ( boost::starts_with( _string.substr( i ), _assoc ) ) {
135  if ( assoc_encountered ) {
136  return ERROR( SYS_BAD_INPUT, "unescaped _assoc token encountered in key or value" );
137  }
138  assoc_encountered = true;
139  i += _assoc.size();
140  continue;
141  }
142  else if ( boost::starts_with( _string.substr( i ), _delim ) ) {
143  if ( !assoc_encountered ) {
144  return ERROR( SYS_BAD_INPUT,
145  "no unescaped _assoc token encountered before unescaped delimiter when parsing kvp" );
146  }
147  _kvp[ key.str() ] = value.str();
148  assoc_encountered = false;
149  key.str( "" );
150  value.str( "" );
151  i += _delim.size();
152  continue;
153  }
154 
155  ( assoc_encountered ? value : key ) << _string[i];
156  ++i;
157  }
158 
159  if ( !key.str().empty() && !assoc_encountered ) {
160  return ERROR( SYS_BAD_INPUT,
161  "no unescaped _assoc token encountered before end of string when parsing kvp" );
162  }
163  else if ( assoc_encountered ) {
164  _kvp[ key.str() ] = value.str();
165  }
166  return SUCCESS();
167  }
168 
169  std::string kvp_string(
170  const kvp_map_t& _kvp ) {
171  std::stringstream str;
172  bool first = true;
173  for ( kvp_map_t::const_iterator it = _kvp.begin(); it != _kvp.end(); ++it ) {
174  if ( first ) {
175  first = false;
176  }
177  else {
178  str << kvp_delimiter();
179  }
180  str << it->first << kvp_association() << it->second;
181  }
182  return str.str();
183  }
184 
185  std::string escape_string( const std::string& _string,
186  const std::string& _escape_token,
187  const std::set<std::string>& _special_tokens ) {
188  std::stringstream escaped_str;
189  for ( size_t i = 0; i < _string.size(); ) {
190  std::set<std::string>::const_iterator tok;
191  for ( tok = _special_tokens.begin(); tok != _special_tokens.end(); ++tok ) {
192  if ( boost::starts_with( _string.substr( i ), *tok ) ) {
193  escaped_str << _escape_token << *tok;
194  i += tok->size();
195  break;
196  }
197  }
198  if ( tok != _special_tokens.end() ) {
199  continue;
200  }
201  else if ( _special_tokens.count( _escape_token ) == 0 &&
202  boost::starts_with( _string.substr( i ), _escape_token ) ) {
203  escaped_str << _escape_token << _escape_token;
204  i += _escape_token.size();
205  continue;
206  }
207  escaped_str << _string[i];
208  ++i;
209  }
210  return escaped_str.str();
211  }
212 
213 
214  std::string escaped_kvp_string(
215  const kvp_map_t& _kvp ) {
216  std::stringstream str;
217  std::set<std::string> special_tokens;
218  special_tokens.insert( kvp_delimiter() );
219  special_tokens.insert( kvp_association() );
220  bool first = true;
221  for ( kvp_map_t::const_iterator it = _kvp.begin(); it != _kvp.end(); ++it ) {
222  if ( first ) {
223  first = false;
224  }
225  else {
226  str << kvp_delimiter();
227  }
228  str << escape_string( it->first, kvp_escape(), special_tokens );
229  str << kvp_association();
230  str << escape_string( it->second, kvp_escape(), special_tokens );
231  }
232  return str.str();
233  }
234 } // namespace irods
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
irods::kvp_escape
std::string kvp_escape()
Definition: irods_kvp_string_parser.cpp:29
irods_stacktrace.hpp
PASS
#define PASS(prev_error_)
Definition: irods_error.hpp:118
irods::KVP_DEF_DELIMITER
static const std::string KVP_DEF_DELIMITER(";")
irods::kvp_delimiter
std::string kvp_delimiter()
Definition: irods_kvp_string_parser.cpp:17
irods::escaped_kvp_string
std::string escaped_kvp_string(const kvp_map_t &_kvp)
Definition: irods_kvp_string_parser.cpp:214
token
Definition: restructs.hpp:293
irods::parse_token_into_kvp
static error parse_token_into_kvp(const std::string &_token, kvp_map_t &_kvp, const std::string &_assoc)
Definition: irods_kvp_string_parser.cpp:36
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
SUCCESS
#define SUCCESS()
Definition: irods_error.hpp:121
irods::parse_escaped_kvp_string
error parse_escaped_kvp_string(const std::string &_str, kvp_map_t &_kvp, const std::string &_association=KVP_DEF_ASSOCIATION, const std::string &_delimeter=KVP_DEF_DELIMITER, const std::string &_escape=KVP_DEF_ESCAPE)
Definition: irods_kvp_string_parser.cpp:106
irods
Definition: apiHandler.hpp:35
irods::kvp_string
std::string kvp_string(const kvp_map_t &_kvp)
Definition: irods_kvp_string_parser.cpp:169
get_irods_version.value
dictionary value
Definition: get_irods_version.py:27
ERROR
#define ERROR(code_, message_)
Definition: irods_error.hpp:117
irods::KVP_DEF_ESCAPE
static const std::string KVP_DEF_ESCAPE("\\")
irods::error
Definition: irods_error.hpp:23
irods::escape_string
std::string escape_string(const std::string &_string, const std::string &_escape_token, const std::set< std::string > &_special_tokens)
Definition: irods_kvp_string_parser.cpp:185
irods::parse_kvp_string
error parse_kvp_string(const std::string &_str, kvp_map_t &_kvp, const std::string &_association=KVP_DEF_ASSOCIATION, const std::string &_delimeter=KVP_DEF_DELIMITER)
Definition: irods_kvp_string_parser.cpp:69
irods_kvp_string_parser.hpp
irods::kvp_association
std::string kvp_association()
Definition: irods_kvp_string_parser.cpp:23
rodsErrorTable.h
BAD_FUNCTION_CALL
@ BAD_FUNCTION_CALL
Definition: rodsErrorTable.h:772
irods::kvp_map_t
std::map< std::string, std::string > kvp_map_t
Definition: irods_kvp_string_parser.hpp:30
irods::error::ok
bool ok()
Definition: irods_error.cpp:258
irods_log.hpp
irods::KVP_DEF_ASSOCIATION
static const std::string KVP_DEF_ASSOCIATION("=")
SYS_BAD_INPUT
@ SYS_BAD_INPUT
Definition: rodsErrorTable.h:215