Streaming C++ API  11.0.0.2
Tuple.hpp
1 // Copyright (c) 2004-2022 TIBCO Software Inc. All rights reserved.
2 
3 #ifndef STREAMBASE_TUPLE_H
4 #define STREAMBASE_TUPLE_H
5 
6 #include "StreamBase.hpp"
7 
8 #include "Timestamp.hpp"
9 #include "Schema.hpp"
10 #include "Field.hpp"
11 #include "Exceptions.hpp"
12 #include "Errors.hpp"
13 #include <NMSTL/platform.hpp>
14 #include <streambase/impl/Memory.hpp>
15 #include "TuplePrivate.hpp"
16 #include "TupleExceptions.hpp"
17 #include "FieldValue.hpp"
18 
19 #ifdef WIN32
20 #pragma warning( push )
21 #pragma warning(disable:4127)
22 #endif
23 
24 SB_INTERNAL_FWD(TupleUtil);
25 SB_INTERNAL_FWD(Errors);
26 
27 SB_NAMESPACE_BEGIN;
28 
29 class Tuple;
30 class Function;
31 
32 
33 template <typename T>
34 T Tuple_do_get(const Tuple& tuple, const Field &field);
35 template <typename T>
36 void Tuple_do_set(Tuple& tuple, const Field &field, T value);
37 
38 /**
39  * Tuples are value types that can be copied and modified separately thus
40  *
41  * t2 = t1;<br>
42  * t2.setId(0); // does not modify t1
43  *
44  * They will only make copies of the underlying data as needed, so
45  * they are relatively cheap to pass around by value
46  */
47 class Tuple {
48 public:
49  Tuple();
50 
51  /// Copy constructor
52  Tuple(const Tuple& t);
53 
54  /// Construct a tuple of the specified schema
55  Tuple(const Schema& s);
56 
57  /// Destructor
58  ~Tuple();
59 
60  const Tuple& operator=(const Tuple& rhs);
61 
62  bool operator==(const Tuple& rhs) const;
63 
64  /** verify that the tuple is valid
65  * Throws StreamBaseException on invalid tuple */
66  void verify() const;
67 
68  /** null all fields in the tuple */
69  void clear() {
70  if(!getSchema()) { return; }
71  for(size_t i = 0; i < getNumFields(); ++i) {
72  setNull(i);
73  }
74  }
75 
76  /** @return the schema */
77  const Schema &getSchema() const;
78  /** set the schema */
79  void setSchema(const Schema &);
80 
81  /** @return the number of fields in the tuple's schema */
82  size_t getNumFields() const {
83  const Schema& s = getSchema();
84  return s ? s.getNumFields() : 0;
85  }
86 
87  /** @return the serialized size of this tuple */
88  size_t getSize() const;
89 
90  /** Flags that can be passed to setString(). TRUNCATE: starting in StreamBase 6.3 the
91  * string type does not have a declared length and strings are never truncated.
92  */
93  enum Flags {
94  NONE = 0,
95  TRUNCATE = 1
96  };
97 
98 
99  //@{
100  /** Return the value of the given field of type T. T must be one of
101  * string, int, double, bool, long, or Timestamp, and correspond to the
102  * field's actual type.
103  *
104  * The Field objects used to set and get Tuple field values must be
105  * obtained via the Tuple's Schema object. A Schema.Field object that has
106  * been created by the user or retrieved from a different Schema may not work.
107  *
108  * @return the value of the field. */
109  template <typename T> T get(const Field &f) const {
110  return Tuple_do_get<T>(*this, f);
111  }
112  template <typename T> T get(size_t i) const {
113  return get<T>(getSchema().getField(i));
114  }
115  template <typename T> T get(const std::string &field_name) const {
116  return get<T>(getSchema().getField(field_name));
117  }
118  //@}
119 
120  //@{
121  /** Set a field to a specific value. Supported values are string,
122  * int, double, bool and Timestamp. field must be a of a matching
123  * DataType.
124  *
125  * The Field objects used to set and get Tuple field values must be
126  * obtained via the Tuple's Schema object. A Schema.Field object that has
127  * been created by the user or retrieved from a different Schema may not work.
128  */
129  template <typename T> void set(const Field &field, T value) {
130  return Tuple_do_set<T>(*this, field, value);
131  }
132  template <typename T> void set(int fieldNum, T value) {
133  set(getSchema().getField(fieldNum), value);
134  }
135  template <typename T> void set(const std::string &field_name, T value) {
136  set(getSchema().getField(field_name), value);
137  }
138  //@}
139 
140  //@{
141  /** Test the null setting for field f
142  *
143  * The Field objects used to set and get Tuple field values must be
144  * obtained via the Tuple's Schema object. A Schema.Field object that has
145  * been created by the user or retrieved from a different Schema may not work.
146  *
147  * @return true if field is null, false otherwise */
148  bool isNull(const Field &f) const;
149  bool isNull(size_t i) const {
150  return isNull(getSchema().getField(i));
151  }
152  bool isNull(const std::string& n) const {
153  return isNull(getSchema().getField(n));
154  }
155  //@}
156 
157  //@{
158  /** Set the null setting for field f
159  *
160  * The Field objects used to set and get Tuple field values must be
161  * obtained via the Tuple's Schema object. A Schema.Field object that has
162  * been created by the user or retrieved from a different Schema may not work.
163  */
164  void setNull(const Field &f);
165  void setNull(size_t i) { setNull(getSchema().getField(i)); }
166  void setNull(const std::string& n) { setNull(getSchema().getField(n)); }
167  //@}
168 
169 
170  //@{
171  /** Return the value of a Boolean field.
172  *
173  * The Field objects used to set and get Tuple field values must be
174  * obtained via the Tuple's Schema object. A Schema.Field object that has
175  * been created by the user or retrieved from a different Schema may not work.
176  *
177  * @return the Boolean value. */
178  bool getBool(const Field &f) const;
179  bool getBool(size_t i) const {
180  return getBool(getSchema().getField(i));
181  }
182  bool getBool(const std::string& n) const {
183  return getBool(getSchema().getField(n));
184  }
185  //@}
186 
187  //@{
188  /** Set the value of a Boolean field.
189  *
190  * The Field objects used to set and get Tuple field values must be
191  * obtained via the Tuple's Schema object. A Schema.Field object that has
192  * been created by the user or retrieved from a different Schema may not work.
193  */
194  void setBool(const Field &f, bool v);
195  void setBool(size_t i, bool v) {
196  setBool(getSchema().getField(i), v);
197  }
198  void setBool(const std::string& n, bool v) {
199  setBool(getSchema().getField(n), v);
200  }
201  //@}
202 
203 
204  //@{
205  /** Return the value of an int field.
206  *
207  * The Field objects used to set and get Tuple field values must be
208  * obtained via the Tuple's Schema object. A Schema.Field object that has
209  * been created by the user or retrieved from a different Schema may not work.
210  *
211  * @return the int value. */
212  int getInt(const Field &f) const;
213  int getInt(size_t i) const {
214  return getInt(getSchema().getField(i));
215  }
216  int getInt(const std::string& n) const {
217  return getInt(getSchema().getField(n));
218  }
219  //@}
220 
221  //@{
222  /** Set the value of an integer field.
223  *
224  * The Field objects used to set and get Tuple field values must be
225  * obtained via the Tuple's Schema object. A Schema.Field object that has
226  * been created by the user or retrieved from a different Schema may not work.
227  */
228  void setInt(const Field &f, int v);
229  void setInt(size_t i, int v) {
230  setInt(getSchema().getField(i), v);
231  }
232  void setInt(const std::string& n, int v) {
233  setInt(getSchema().getField(n), v);
234  }
235  //@}
236 
237 
238  //@{
239  /** Return the value of a long field.
240  *
241  * The Field objects used to set and get Tuple field values must be
242  * obtained via the Tuple's Schema object. A Schema.Field object that has
243  * been created by the user or retrieved from a different Schema may not work.
244  *
245  * @return the long value. */
246  long long getLong(const Field &f) const;
247  long long getLong(size_t i) const {
248  return getLong(getSchema().getField(i));
249  }
250  long long getLong(const std::string& n) const {
251  return getLong(getSchema().getField(n));
252  }
253  //@}
254 
255  //@{
256  /** Set the value of a long field.
257  *
258  * The Field objects used to set and get Tuple field values must be
259  * obtained via the Tuple's Schema object. A Schema.Field object that has
260  * been created by the user or retrieved from a different Schema may not work.
261  */
262  void setLong(const Field &f, long long v);
263  void setLong(size_t i, long long v) {
264  setLong(getSchema().getField(i), v);
265  }
266  void setLong(const std::string& n, long long v) {
267  setLong(getSchema().getField(n), v);
268  }
269  //@}
270 
271 
272  //@{
273  /** Return the value of a double field.
274  *
275  * The Field objects used to set and get Tuple field values must be
276  * obtained via the Tuple's Schema object. A Schema.Field object that has
277  * been created by the user or retrieved from a different Schema may not work.
278  *
279  * @return the double value. */
280  double getDouble(const Field &f) const;
281  double getDouble(size_t i) const {
282  return getDouble(getSchema().getField(i));
283  }
284  double getDouble(const std::string& n) const {
285  return getDouble(getSchema().getField(n));
286  }
287  //@}
288 
289  //@{
290  /** Set the value of a double field.
291  *
292  * The Field objects used to set and get Tuple field values must be
293  * obtained via the Tuple's Schema object. A Schema.Field object that has
294  * been created by the user or retrieved from a different Schema may not work.
295  */
296  void setDouble(const Field &f, double v);
297  void setDouble(size_t i, double v) {
298  setDouble(getSchema().getField(i), v);
299  }
300  void setDouble(const std::string& n, double v) {
301  setDouble(getSchema().getField(n), v);
302  }
303  //@}
304 
305 
306  //@{
307  /** Return the value of a Timestamp field.
308  *
309  * The Field objects used to set and get Tuple field values must be
310  * obtained via the Tuple's Schema object. A Schema.Field object that has
311  * been created by the user or retrieved from a different Schema may not work.
312  *
313  * @return the Timestamp value. */
314  Timestamp getTimestamp(const Field &f) const;
315  Timestamp getTimestamp(size_t i) const {
316  return getTimestamp(getSchema().getField(i));
317  }
318  Timestamp getTimestamp(const std::string& n) const {
319  return getTimestamp(getSchema().getField(n));
320  }
321  //@}
322 
323  //@{
324  /** Set the value of a Timestamp field.
325  *
326  * The Field objects used to set and get Tuple field values must be
327  * obtained via the Tuple's Schema object. A Schema.Field object that has
328  * been created by the user or retrieved from a different Schema may not work.
329  */
330  void setTimestamp(const Field &f, const Timestamp& v);
331  void setTimestamp(size_t i, const Timestamp& v) {
332  setTimestamp(getSchema().getField(i), v);
333  }
334  void setTimestamp(const std::string& n, const Timestamp& v) {
335  setTimestamp(getSchema().getField(n), v);
336  }
337  //@}
338 
339 
340 
341  //@{
342  /** Return the value of a BLOB field.
343  *
344  * The Field objects used to set and get Tuple field values must be
345  * obtained via the Tuple's Schema object. A Schema.Field object that has
346  * been created by the user or retrieved from a different Schema may not work.
347  *
348  * @return the BLOB value. */
349  const std::string& getBlobBuffer(const Field &f) const;
350  const std::string& getBlobBuffer(size_t i) const {
351  return getBlobBuffer(getSchema().getField(i));
352  }
353  const std::string& getBlobBuffer(const std::string& n) const {
354  return getBlobBuffer(getSchema().getField(n));
355  }
356  //@}
357 
358  //@{
359  /** Set the value of a BLOB field.
360  *
361  * The Field objects used to set and get Tuple field values must be
362  * obtained via the Tuple's Schema object. A Schema.Field object that has
363  * been created by the user or retrieved from a different Schema may not work.
364  */
365  void setBlobBuffer(const Field &f, const std::string& v);
366  void setBlobBuffer(size_t i, const std::string& v) {
367  setBlobBuffer(getSchema().getField(i), v);
368  }
369  void setBlobBuffer(const std::string& n, const std::string& v) {
370  setBlobBuffer(getSchema().getField(n), v);
371  }
372  //@}
373 
374 
375  //@{
376  /** Return the value of a LIST field.
377  *
378  * The Schema::Field objects used to set and get Tuple field values must be
379  * obtained via the Tuple's Schema object. A Schema.Field object that has
380  * been created by the user or retrieved from a different Schema may not work.
381  *
382  * @return the LIST value. */
383  const std::vector<FieldValue>& getList(const Schema::Field &f) const;
384  const std::vector<FieldValue>& getList(size_t i) const {
385  return getList(getSchema().getField(i));
386  }
387  const std::vector<FieldValue>& getList(const std::string& n) const {
388  return getList(getSchema().getField(n));
389  }
390  //@}
391 
392  //@{
393  /** Set the value of a LIST field.
394  *
395  * The Schema::Field objects used to set and get Tuple field values must be
396  * obtained via the Tuple's Schema object. A Schema.Field object that has
397  * been created by the user or retrieved from a different Schema may not work.
398  */
399  void setList(const Schema::Field &f, const std::vector<FieldValue>& v);
400  void setList(size_t i, const std::vector<FieldValue>& v) {
401  setList(getSchema().getField(i), v);
402  }
403  void setList(const std::string& n, const std::vector<FieldValue>& v) {
404  setList(getSchema().getField(n), v);
405  }
406  //@}
407 
408  //@{
409  /** Return the value of a string field.
410  *
411  * The Field objects used to set and get Tuple field values must be
412  * obtained via the Tuple's Schema object. A Schema.Field object that has
413  * been created by the user or retrieved from a different Schema may not work.
414  *
415  * @return the string value. */
416  const std::string& getString(const Field &f) const;
417  const std::string& getString(size_t i) const {
418  return getString(getSchema().getField(i));
419  }
420  const std::string& getString(const std::string& n) const {
421  return getString(getSchema().getField(n));
422  }
423  //@}
424 
425 
426  //@{
427  /** Set the value of a string field.
428  *
429  * The Field objects used to set and get Tuple field values must be
430  * obtained via the Tuple's Schema object. A Schema.Field object that has
431  * been created by the user or retrieved from a different Schema may not work.
432  */
433  void setString(const Field &field,
434  const std::string &value, Flags flags = NONE);
435  void setString(size_t field,
436  const char* data, size_t len, Flags flags = NONE) {
437  setString(field, std::string(data, len), flags);
438  }
439  void setString(const std::string& field,
440  const char* data, size_t len, Flags flags = NONE) {
441  setString(field, std::string(data, len), flags);
442  }
443  void setString(const Field& field,
444  const char* data, size_t len, Flags flags = NONE) {
445  setString(field, std::string(data, len), flags);
446  }
447  void setString(size_t field_index,
448  const std::string &value, Flags flags = NONE) {
449  setString(getSchema().getField(field_index), value, flags);
450  }
451  void setString(const std::string& field_name,
452  const std::string& value, Flags flags = NONE) {
453  setString(getSchema().getField(field_name), value, flags);
454  }
455  //@}
456 
457 
458  //@{
459  /** Return the value of a nested tuple field.
460  *
461  * The Field objects used to set and get Tuple field values must be
462  * obtained via the Tuple's Schema object. A Schema.Field object that has
463  * been created by the user or retrieved from a different Schema may not work.
464  *
465  * @return the nested tuple value. */
466  const Tuple& getTuple(const Field &f) const;
467  const Tuple& getTuple(size_t i) const {
468  return getTuple(getSchema().getField(i));
469  }
470  const Tuple& getTuple(const std::string& n) const {
471  return getTuple(getSchema().getField(n));
472  }
473  //@}
474 
475  //@{
476  /** Return the value of a function field.
477  *
478  * The Field objects used to set and get Tuple field values must be
479  * obtained via the Tuple's Schema object. A Schema.Field object that has
480  * been created by the user or retrieved from a different Schema may not work.
481  *
482  * @return the function value.
483  */
484  const Function& getFunction(const Field& f) const;
485  const Function& getFunction(size_t i) const {
486  return getFunction(getSchema().getField(i));
487  }
488  const Function& getFunction(const std::string& n) const {
489  return getFunction(getSchema().getField(n));
490  }
491  //@}
492 
493  private:
494  Tuple& getTupleMutable(const Field &f);
495 
496  public:
497 
498  //@{
499  /** Set the value of a nested tuple field.
500  *
501  * The Field objects used to set and get Tuple field values must be
502  * obtained via the Tuple's Schema object. A Schema.Field object that has
503  * been created by the user or retrieved from a different Schema may not work.
504  */
505  void setTuple(const Field &f, const Tuple& v);
506  void setTuple(size_t i, const Tuple& v) {
507  setTuple(getSchema().getField(i), v);
508  }
509  void setTuple(const std::string& n, const Tuple& v) {
510  setTuple(getSchema().getField(n), v);
511  }
512  //@}
513 
514  //@{
515  /**
516  * Set the value of a function field
517  *
518  * The Field objects used to set and get Tuple field values must be
519  * obtained via the Tuple's Schema object. A Schema.Field object that has
520  * been created by the user or retrieved from a different Schema may not work.
521  */
522  void setFunction(const Field& f, const Function& v);
523  void setFunction(size_t i, const Function& v) {
524  setFunction(getSchema().getField(i), v);
525  }
526  void setFunction(const std::string& n, const Function& v) {
527  setFunction(getSchema().getField(n), v);
528  }
529  //@}
530 
531  /// Takes a field with a path and returns the field at the target of that path
532  FieldValue& getFieldValue(const Field& f);
533  /// Takes a field with a path and returns the field at the target of that path
534  const FieldValue& getFieldValue(const Schema::Field& f) const;
535 
536  /// Takes the index of a field in this tuple's schema, returns the corresponding
537  /// field value.
538  FieldValue& getFieldValue(size_t field_num);
539  /// Takes the index of a field in this tuple's schema, returns the corresponding
540  /// field value.
541  const FieldValue& getFieldValue(size_t field_num) const;
542 
543  /// Takes the name of a field in this tuple's schema, returns the corresponding
544  /// field value.
545  FieldValue& getFieldValue(const std::string& field_name);
546  /// Takes the name of a field in this tuple's schema, returns the corresponding
547  /// field value.
548  const FieldValue& getFieldValue(const std::string& field_name) const;
549 
550  /// Takes a field with a path and sets the value of the field at the target of
551  /// that path to that of the provided FieldValue.
552  void setFieldValue(const Field& f, const FieldValue& fv);
553  /// Takes the index of a field in this tuple's schema and sets the corresponding
554  /// field value.
555  void setFieldValue(size_t field_num, const FieldValue& fv);
556  /// Takes the name of a field in this tuple's schema and sets the corresponding
557  /// field value.
558  void setFieldValue(const std::string& field_name, const FieldValue& fv);
559 
560 
561  /** @return true if tuple has a header, false otherwise */
562  bool hasHeader() const { return getSchema().hasHeader(); }
563 
564 
565  /** @return The id for this tuple */
566  unsigned int getId() const;
567  /** set the id */
568  void setId(unsigned int tid);
569 
570  /** Return a human-readable string value representing this tuple
571  * in its entirety (including all header values, if applicable).
572  * @return the string value. */
573  std::string as_string() const;
574 
575  /** Return a human-readable string value representing this tuple.
576  * It compares to as_string by allowing a user-specified delimiter
577  * between fields, making the header timestamp stand out, and
578  * omitting the TupleId header field.
579  * null_string is written out for any null field.
580  * @return the string value */
581  std::string as_string_external(char delimiter = ',',
582  const std::string& null_string = getNullString()) const;
583 
584  /** Return a string value representing this tuple, separated by
585  * the given delimiter.
586  *
587  * @param delimiter the string to put between fields
588  * @param null_string the string used to represent null values
589  * @param include_names whether to preface each field with "<name>="
590  * @param quote_all_strings whether to put quotes around all strings,
591  * regardless of need
592  *
593  * @return the result string
594  */
595  std::string toDelimitedString(const std::string &delimiter,
596  const std::string& null_string = getNullString(),
597  bool include_names = false, bool quote_all_strings = false) const;
598 
599 #ifndef DOXYGEN_INTERNAL_ONLY
600  /** Generates a CSV string with a column for each field in the tuple.
601  * null_string is written out for any null field. */
602  void writeCSVString(std::ostream& out, char delim, char quote,
603  const std::string& null_string = getNullString()) const;
604 #endif
605 
606  /** Return the default string used to represent null, i.e., null. */
607  static const std::string& getNullString() {
608  static std::string NULL_STRING = "null";
609  return NULL_STRING;
610  }
611 
612 #ifndef DOXYGEN_INTERNAL_ONLY
613  /** @brief copy the tuple into the buffer of the given size
614  * - if the tuple does not fit in the buffer, the required size is
615  * returned and the buffer is left in an undefined state
616  * - otherwise the tuple is copied into the buffer in a packed representation
617  * and the amount of the buffer used is returned
618  *
619  * @param buf the buffer into which to copy data (NULL is a safe value to pass)
620  * @param len the size of the buffer in bytes
621  * @param byteswap whether to swap the bytes coming from the buffer
622  * @return the space required/used to serialize the tuple in bytes
623  * <em>Note: this method is not public API, and is for internal StreamBase use only</em>
624  */
625  size_t copyIntoBuffer(void* buf, size_t len, bool byteswap) const;
626 
627  /** Set the contents of this tuple from a buffer containing a packed
628  * representation of a tuple
629  *
630  * @param buf the buffer into which to copy data (NULL is a safe value to pass)
631  * @param buf_len the size of the buffer in bytes
632  * @param byteswap whether to swap the bytes coming from the buffer
633  * @param s the Schema to use
634  * @return the size in bytes used from the buffer
635  */
636  size_t setFromPackedBuffer(
637  const void* buf, size_t buf_len, bool byteswap, const Schema& s);
638 
639  static Tuple createFromPackedBuffer(size_t* size_used,
640  const void* buf, size_t buf_len, bool byteswap, const Schema& s);
641 #endif
642 
643 private:
644  std::shared_ptr<TuplePrivateImpl> _;
645  /// These methods are used to implement copy-on-write
646  /// ensureUnique() should be called as the first line of any non-const method
647  /// ensureAllocated() should be called as the first line of any const method
648  void ensureUnique();
649  void ensureAllocated() const;
650 
651  Tuple& resolveField(const Field& f);
652  const Tuple& resolveField(const Field& f) const;
653 
654 };
655 
656 #define DO_ACCESSOR(type, getter) \
657 template <> inline type Tuple_do_get<type>(const Tuple& t, const Field& f) { return t.get ## getter(f); } \
658 template <> inline void Tuple_do_set<type>(Tuple& t, const Field& f, type v) { return t.set ## getter(f, v); }
659 
660 DO_ACCESSOR(bool, Bool)
661 DO_ACCESSOR(int, Int)
662 DO_ACCESSOR(long long, Long)
663 DO_ACCESSOR(double, Double)
664 DO_ACCESSOR(std::string, String)
665 DO_ACCESSOR(Timestamp, Timestamp)
666 
667 #undef DO_ACCESSOR
668 
669 
670 #ifdef WIN32
671 #pragma warning( pop )
672 #endif
673 
674 SB_NAMESPACE_END;
675 
676 inline std::ostream& operator << (std::ostream& os, const sb::Tuple& tuple) {
677  os << tuple.as_string();
678  return os;
679 }
680 
681 
682 #endif // TUPLE_H