values.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 
8 #ifndef SOCI_VALUES_H_INCLUDED
9 #define SOCI_VALUES_H_INCLUDED
10 
11 #include "statement.h"
12 #include "into-type.h"
13 #include "use-type.h"
14 // std
15 #include <cstddef>
16 #include <map>
17 #include <sstream>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 namespace soci
23 {
24 
25 namespace details
26 {
27 
28 class copy_base
29 {
30 public:
31  virtual ~copy_base() {}
32 };
33 
34 template <typename T>
35 struct copy_holder : public copy_base
36 {
37  copy_holder(T const & v) : value_(v) {}
38 
39  T value_;
40 };
41 
42 } // namespace details
43 
45 {
47  friend class details::into_type<values>;
48  friend class details::use_type<values>;
49 
50 public:
51 
52  values() : row_(NULL), currentPos_(0), uppercaseColumnNames_(false) {}
53 
54  indicator get_indicator(std::size_t pos) const;
55  indicator get_indicator(std::string const & name) const;
56 
57  template <typename T>
58  T get(std::size_t pos) const
59  {
60  if (row_ != NULL)
61  {
62  return row_->get<T>(pos);
63  }
64  else if (*indicators_[pos] != i_null)
65  {
66  return get_from_uses<T>(pos);
67  }
68  else
69  {
70  std::ostringstream msg;
71  msg << "Column at position "
72  << static_cast<unsigned long>(pos)
73  << " contains NULL value and no default was provided";
74  throw soci_error(msg.str());
75  }
76  }
77 
78  template <typename T>
79  T get(std::size_t pos, T const & nullValue) const
80  {
81  if (row_ != NULL)
82  {
83  return row_->get<T>(pos, nullValue);
84  }
85  else if (*indicators_[pos] == i_null)
86  {
87  return nullValue;
88  }
89  else
90  {
91  return get_from_uses<T>(pos);
92  }
93  }
94 
95  template <typename T>
96  T get(std::string const & name) const
97  {
98  return row_ != NULL ? row_->get<T>(name) : get_from_uses<T>(name);
99  }
100 
101  template <typename T>
102  T get(std::string const & name, T const & nullValue) const
103  {
104  return row_ != NULL
105  ? row_->get<T>(name, nullValue)
106  : get_from_uses<T>(name, nullValue);
107  }
108 
109  template <typename T>
110  values const & operator>>(T & value) const
111  {
112  if (row_ != NULL)
113  {
114  // row maintains its own position counter
115  // which is automatically reset when needed
116 
117  *row_ >> value;
118  }
119  else if (*indicators_[currentPos_] != i_null)
120  {
121  // if there is no row object, then the data can be
122  // extracted from the locally stored use elements,
123  // but for this the position counter has to be maintained
124  // as well
125 
126  value = get_from_uses<T>(currentPos_);
127  ++currentPos_;
128  }
129  else
130  {
131  std::ostringstream msg;
132  msg << "Column at position "
133  << static_cast<unsigned long>(currentPos_)
134  << " contains NULL value and no default was provided";
135  throw soci_error(msg.str());
136  }
137 
138  return *this;
139  }
140 
141  void skip(std::size_t num = 1) const
142  {
143  if (row_ != NULL)
144  {
145  row_->skip(num);
146  }
147  else
148  {
149  currentPos_ += num;
150  }
151  }
152 
153  void reset_get_counter() const
154  {
155  if (row_ != NULL)
156  {
157  row_->reset_get_counter();
158  }
159  else
160  {
161  currentPos_ = 0;
162  }
163  }
164 
165  template <typename T>
166  void set(std::string const & name, T const & value, indicator indic = i_ok)
167  {
168  typedef typename type_conversion<T>::base_type base_type;
169  if(index_.find(name) == index_.end())
170  {
171  index_.insert(std::make_pair(name, uses_.size()));
172 
173  indicator * pind = new indicator(indic);
174  indicators_.push_back(pind);
175 
176  base_type baseValue;
177  if (indic == i_ok)
178  {
179  type_conversion<T>::to_base(value, baseValue, *pind);
180  }
181 
183  new details::copy_holder<base_type>(baseValue);
184  deepCopies_.push_back(pcopy);
185 
186  uses_.push_back(new details::use_type<base_type>(
187  pcopy->value_, *pind, name));
188  }
189  else
190  {
191  size_t index = index_.find(name)->second;
192  *indicators_[index] = indic;
193  if (indic == i_ok)
194  {
196  value,
197  static_cast<details::copy_holder<base_type>*>(deepCopies_[index])->value_,
198  *indicators_[index]);
199  }
200  }
201  }
202 
203  template <typename T>
204  void set(const T & value, indicator indic = i_ok)
205  {
206  indicator * pind = new indicator(indic);
207  indicators_.push_back(pind);
208 
209  typedef typename type_conversion<T>::base_type base_type;
210  base_type baseValue;
211  type_conversion<T>::to_base(value, baseValue, *pind);
212 
214  new details::copy_holder<base_type>(baseValue);
215  deepCopies_.push_back(pcopy);
216 
217  uses_.push_back(new details::use_type<base_type>(
218  pcopy->value_, *pind));
219  }
220 
221  template <typename T>
222  values & operator<<(T const & value)
223  {
224  set(value);
225  return *this;
226  }
227 
228  void uppercase_column_names(bool forceToUpper)
229  {
230  uppercaseColumnNames_ = forceToUpper;
231  }
232 
233  column_properties const& get_properties(std::size_t pos) const;
234  column_properties const& get_properties(std::string const &name) const;
235 
236 private:
237 
238  //TODO To make values generally usable outside of type_conversion's,
239  // these should be reference counted smart pointers
241  std::vector<details::standard_use_type *> uses_;
242  std::map<details::use_type_base *, indicator *> unused_;
243  std::vector<indicator *> indicators_;
244  std::map<std::string, std::size_t> index_;
245  std::vector<details::copy_base *> deepCopies_;
246 
247  mutable std::size_t currentPos_;
248 
250 
251  // When type_conversion::to() is called, a values object is created
252  // without an underlying row object. In that case, get_from_uses()
253  // returns the underlying field values
254  template <typename T>
255  T get_from_uses(std::string const & name, T const & nullValue) const
256  {
257  std::map<std::string, std::size_t>::const_iterator pos = index_.find(name);
258  if (pos != index_.end())
259  {
260  if (*indicators_[pos->second] == i_null)
261  {
262  return nullValue;
263  }
264 
265  return get_from_uses<T>(pos->second);
266  }
267  throw soci_error("Value named " + name + " not found.");
268  }
269 
270  template <typename T>
271  T get_from_uses(std::string const & name) const
272  {
273  std::map<std::string, std::size_t>::const_iterator pos = index_.find(name);
274  if (pos != index_.end())
275  {
276  return get_from_uses<T>(pos->second);
277  }
278  throw soci_error("Value named " + name + " not found.");
279  }
280 
281  template <typename T>
282  T get_from_uses(std::size_t pos) const
283  {
284  details::standard_use_type* u = uses_[pos];
285 
286  typedef typename type_conversion<T>::base_type base_type;
287 
288  if (dynamic_cast<details::use_type<base_type> *>(u))
289  {
290  base_type const & baseValue = *static_cast<base_type*>(u->get_data());
291 
292  T val;
293  indicator ind = *indicators_[pos];
294  type_conversion<T>::from_base(baseValue, ind, val);
295  return val;
296  }
297  else
298  {
299  std::ostringstream msg;
300  msg << "Value at position "
301  << static_cast<unsigned long>(pos)
302  << " was set using a different type"
303  " than the one passed to get()";
304  throw soci_error(msg.str());
305  }
306  }
307 
309  {
310  row_ = new row();
311  row_->uppercase_column_names(uppercaseColumnNames_);
312 
313  return * row_;
314  }
315 
316  // this is called by Statement::bind(values)
318  {
319  static_cast<details::standard_use_type *>(u)->convert_to_base();
320  unused_.insert(std::make_pair(u, i));
321  }
322 
323  // this is called by details::into_type<values>::clean_up()
324  // and use_type<values>::clean_up()
325  void clean_up()
326  {
327  delete row_;
328  row_ = NULL;
329 
330  // delete any uses and indicators which were created by set() but
331  // were not bound by the Statement
332  // (bound uses and indicators are deleted in Statement::clean_up())
333  for (std::map<details::use_type_base *, indicator *>::iterator pos =
334  unused_.begin(); pos != unused_.end(); ++pos)
335  {
336  delete pos->first;
337  delete pos->second;
338  }
339 
340  for (std::size_t i = 0; i != deepCopies_.size(); ++i)
341  {
342  delete deepCopies_[i];
343  }
344  }
345 };
346 
347 } // namespace soci
348 
349 #endif // SOCI_VALUES_H_INCLUDED
void clean_up()
Definition: values.h:325
values & operator<<(T const &value)
Definition: values.h:222
Definition: row.h:41
std::map< details::use_type_base *, indicator * > unused_
Definition: values.h:242
copy_holder(T const &v)
Definition: values.h:37
static void to_base(T const &in, base_type &out, indicator &ind)
bool uppercaseColumnNames_
Definition: values.h:249
#define SOCI_DECL
Definition: soci-config.h:31
std::map< std::string, std::size_t > index_
Definition: values.h:244
row & get_row()
Definition: values.h:308
void skip(std::size_t num=1) const
Definition: values.h:141
T get_from_uses(std::string const &name, T const &nullValue) const
Definition: values.h:255
void add_unused(details::use_type_base *u, indicator *i)
Definition: values.h:317
row * row_
Definition: values.h:240
std::vector< indicator * > indicators_
Definition: values.h:243
static void from_base(base_type const &in, indicator ind, T &out)
std::vector< details::standard_use_type * > uses_
Definition: values.h:241
void uppercase_column_names(bool forceToUpper)
Definition: values.h:228
T get_from_uses(std::string const &name) const
Definition: values.h:271
virtual void * get_data()
Definition: use-type.h:74
std::size_t currentPos_
Definition: values.h:247
T get_from_uses(std::size_t pos) const
Definition: values.h:282
void uppercase_column_names(bool forceToUpper)
Definition: row.cpp:29
std::vector< details::copy_base * > deepCopies_
Definition: values.h:245
void reset_get_counter() const
Definition: values.h:153
virtual ~copy_base()
Definition: values.h:31
values const & operator>>(T &value) const
Definition: values.h:110


asr_lib_ism
Author(s): Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Wed Jan 8 2020 04:02:41