25 #ifndef __AMPS_FIELD_HPP__
26 #define __AMPS_FIELD_HPP__
28 #define _AMPS_SKIP_AMPSPLUSPLUS
30 #undef _AMPS_SKIP_AMPSPLUSPLUS
31 #include <amps/AMPSException.hpp>
37 #define AMPS_UNSET_INDEX (size_t)-1
38 #define AMPS_TIMESTAMP_LEN 16
39 #define AMPS_TIMESTAMP_LEN_LONG 23
40 #define AMPS_MAX_BOOKMARK_LEN 42
42 #define AMPS_MAX_SUBID_LEN 1048576
44 #if (_MSC_VER >= 1400)
45 #define AMPS_snprintf(buf_, sz_, ...) _snprintf_s(buf_, sz_, _TRUNCATE, __VA_ARGS__)
46 #define AMPS_snprintf_amps_uint64_t(buf,sz,val) sprintf_s(buf,sz,"%I64u",val)
48 #define AMPS_snprintf_sizet(buf,sz,val) sprintf_s(buf,sz,"%lu",val)
50 #define AMPS_snprintf_sizet(buf,sz,val) sprintf_s(buf,sz,"%u",val)
53 #define AMPS_snprintf _snprintf
55 #define AMPS_snprintf_sizet(buf,sz,val) _sprintf(buf,sz,"%lu",val)
57 #define AMPS_snprintf_sizet(buf,sz,val) _sprintf(buf,sz,"%u",val)
61 #define AMPS_snprintf snprintf
62 #if defined(__x86_64__) || defined(__aarch64__)
63 #define AMPS_snprintf_amps_uint64_t(buf,sz,val) snprintf(buf,sz,"%lu", (unsigned long)val)
64 #define AMPS_snprintf_sizet(buf,sz,val) snprintf(buf,sz,"%lu",val)
66 #define AMPS_snprintf_amps_uint64_t(buf,sz,val) snprintf(buf,sz,"%llu",val)
67 #define AMPS_snprintf_sizet(buf,sz,val) snprintf(buf,sz,"%u",val)
93 Field() : _data(NULL), _len(0) {;}
94 Field(
const char* data_)
97 _len = ::strlen(data_);
99 Field(
const char* data_,
size_t len_)
115 Field(
const std::string& string_)
117 _data = string_.c_str();
118 _len = string_.length();
121 bool contains(
const char* searchString,
size_t len)
const
123 const char* dataEnd = _data + _len;
124 return std::search(_data, dataEnd, searchString, searchString +
len) != dataEnd;
137 operator std::string ()
const
139 return _len ? std::string(_data, _len) : std::string();
149 if ( _len == rhs_._len )
151 return ::memcmp(_data, rhs_._data, _len) == 0;
165 return (!_data && !rhs_);
167 return (_len == strlen(rhs_)) && (::strncmp(_data, rhs_, _len) == 0);
170 bool operator<(
const Field& rhs)
const;
179 if ( _len == rhs_._len )
181 return ::memcmp(_data, rhs_._data, _len) != 0;
193 return (_len != strlen(rhs_)) || (::memcmp(_data, rhs_, _len) != 0);
203 return rhs_.compare(0, rhs_.length(), _data, _len) != 0;
213 return rhs_.compare(0, rhs_.length(), _data, _len) == 0;
224 _data = (
char*)malloc(orig_._len);
230 ::memcpy(
static_cast<void*
>(
const_cast<char*
>(_data)),
231 orig_._data, orig_._len);
254 const char* tmpBuf = copy_._data;
255 size_t len = copy_._len;
268 Field newField(_strdup(str_));
270 Field newField(strdup(str_));
304 void assign(
const char* ptr,
size_t len)
311 inline size_t hash_function()
const
314 const char* p_ = _data;
318 c = (
unsigned long) * p_;
327 size_t operator()(
const Field& f)
const
329 return f.hash_function();
332 bool operator()(
const Field& f1,
const Field& f2)
const
334 if (f1.len() < f2.len())
338 if (f1.len() > f2.len())
347 return ::memcmp(f1.data(), f2.data(), f2.len()) < 0;
352 static bool isTimestamp(
const Field& field_)
354 return (field_.len() >= AMPS_TIMESTAMP_LEN
355 && field_.len() <= AMPS_TIMESTAMP_LEN_LONG
356 && field_.data()[8] ==
'T');
359 static std::vector<Field> parseBookmarkList(
const Field& field_)
361 std::vector<Field> list;
362 const char* start = field_.data();
363 size_t remain = field_.len();
364 const char* comma = (
const char*)memchr((
const void*)start,
368 size_t len = (size_t)(comma - start);
371 list.emplace_back(Field(start,
len));
374 remain = field_.len() - (size_t)(start - field_.data());
375 comma = (
const char*)memchr((
const void*)start,
380 list.emplace_back(Field(start, remain));
386 static void parseBookmark(
const Field& field_,
387 amps_uint64_t& publisherId_,
388 amps_uint64_t& sequenceNumber_)
390 publisherId_ = sequenceNumber_ = (amps_uint64_t)0;
395 const char*
data = field_.data();
396 size_t len = field_.len();
398 if (isTimestamp(field_))
403 for ( ; i <
len; ++i)
405 if (!isdigit(
data[i]))
410 publisherId_ += (amps_uint64_t)(
data[i] -
'0');
415 publisherId_ = sequenceNumber_ = (amps_uint64_t)0;
418 for (i = i + 1; i <
len; ++i)
420 if (!isdigit(
data[i]))
424 sequenceNumber_ *= 10;
425 sequenceNumber_ += (amps_uint64_t)(
data[i] -
'0');
431 class BookmarkRange :
public Field
434 static bool isRange(
const Field& bookmark_)
436 return bookmark_.data() && bookmark_.len()
437 ? memchr(bookmark_.data(),
':', bookmark_.len()) != NULL
442 : Field(), _start(), _end(), _open(AMPS_UNSET_INDEX)
443 , _capacity(AMPS_UNSET_INDEX)
448 BookmarkRange(
const Field& field_)
449 : Field(), _start(), _end(), _open(AMPS_UNSET_INDEX)
450 , _capacity(field_.len())
455 void set(
const Field& field_)
458 if (_data == field_.data() ||
operator==(field_))
467 bool foundSeparator =
false;
468 bool foundClose =
false;
469 for (
size_t i = 0; i < _len; ++i)
477 if (foundClose || _open != AMPS_UNSET_INDEX)
502 if (foundClose || _open == AMPS_UNSET_INDEX)
507 else if (foundSeparator)
511 _end.assign(_data + i, 0);
514 else if (!_start.data())
516 _start.assign(_data + i, 0);
523 if (foundSeparator || foundClose || _open == AMPS_UNSET_INDEX
529 foundSeparator =
true;
531 if (_start.len() == 0)
534 _start.assign(_start.data(), i - (
size_t)(_start.data() - _data));
542 if (foundClose || _open == AMPS_UNSET_INDEX || !_end.data())
553 _end.assign(_end.data(), i - (
size_t)(_end.data() - _data));
560 if (_end.data() && _end.len() == 0)
563 _end.assign(_end.data(), i - (
size_t)(_end.data() - _data));
566 else if (_start.data() && _start.len() == 0)
569 _start.assign(_start.data(), i - (
size_t)(_start.data() - _data));
581 if (_start.empty() || _end.empty())
599 _open = AMPS_UNSET_INDEX;
612 bool isStartInclusive()
const
614 return _data[_open] ==
'[';
619 void makeStartExclusive()
621 const_cast<char*
>(_data)[_open] =
'(';
626 bool isEndInclusive()
const
628 return _data[_len - 1] ==
']';
633 void makeEndExclusive()
635 const_cast<char*
>(_data)[_len - 1] =
')';
640 const Field& getStart()
const
645 const Field& getEnd()
const
652 void replaceStart(
const Field& start_,
bool makeExclusive_ =
false)
656 if (_capacity >= (start_.len() + _end.len() + 3))
658 char* data =
const_cast<char*
>(_data);
665 data[0] = _data[_open];
668 if ((
size_t)(_end.data() - _data - 2) < start_.len())
670 size_t newLen = start_.len() + _end.len() + 3;
674 for (
size_t dest = newLen - 1, src = _len - 1;
675 src > _start.len(); --src, --dest)
677 data[dest] = _data[src];
679 if (data[src] ==
':')
681 _end.assign(data + dest + 1, _end.len());
688 ::memcpy(
static_cast<void*
>(data + 1), start_.data(), start_.len());
689 _start.assign(data + 1, start_.len());
691 if ((
size_t)(_end.data() - _start.data()) > _start.len() + 1UL)
694 for (
size_t dest = _start.len() + 1, src = (
size_t)(_end.data() - data - 1);
695 src < _len; ++dest, ++src)
697 data[dest] = data[src];
698 if (data[src] ==
']' || data[src] ==
')')
700 _end.assign(data + _start.len() + 2, _end.len());
704 _len = _start.len() + _end.len() + 3;
711 _capacity = (4UL * AMPS_MAX_BOOKMARK_LEN + 6UL
712 >= start_.len() + _end.len() + 3UL)
713 ? (4UL * AMPS_MAX_BOOKMARK_LEN + 6UL)
714 : (start_.len() + _end.len() + 3UL);
715 char* data = (
char*)malloc(_capacity);
718 throw AMPSException(
"Failed to allocate memory for replacement field",
AMPS_E_MEMORY);
726 data[0] = _data[_open];
729 ::memcpy(
static_cast<void*
>(data + 1), start_.data(), start_.len());
730 _start.assign(data + 1, start_.len());
731 data[start_.len() + 1] =
':';
732 ::memcpy(
static_cast<void*
>(data + start_.len() + 2), _end.data(),
734 _end.assign(data + start_.len() + 2, _end.len());
735 size_t len = start_.len() + 3 + _end.len();
736 data[len - 1] = _data[_len - 1];
Core type and function declarations for the AMPS C client.
@ AMPS_E_MEMORY
A memory error occurred.
Definition: amps.h:225
Base class for all exceptions in AMPS.
Definition: AMPSException.hpp:41
Field represents the value of a single field in a Message.
Definition: Field.hpp:88
bool operator==(const Field &rhs_) const
Comparison operator Returns ‘true’ if self and rhs are equivalent, ‘false’ otherwise.
Definition: Field.hpp:147
void clear()
Deletes the data associated with this Field, should only be used on Fields that were created as deepC...
Definition: Field.hpp:278
bool operator==(const char *rhs_) const
String comparison operator Returns ‘true’ if self and rhs are equivalent, ‘false’ otherwise.
Definition: Field.hpp:161
bool empty() const
Returns 'true' if empty, 'false' otherwise.
Definition: Field.hpp:129
void swap(Field ©_)
Swaps the buffers/lengths in this with copy.
Definition: Field.hpp:252
void deepCopy(const Field &orig_)
Makes self a deep copy of the original field.
Definition: Field.hpp:219
size_t len() const
Returns the length of the data underlying this field.
Definition: Field.hpp:298
bool operator!=(const std::string &rhs_) const
String comparison operator Returns ‘true’ if self and rhs are not equivalent.
Definition: Field.hpp:201
bool operator!=(const Field &rhs_) const
Comparison operator Returns true if self and rhs are not equivalent.
Definition: Field.hpp:177
bool operator==(const std::string &rhs_) const
String comparison operator Returns ‘true’ if self and rhs are equivalent.
Definition: Field.hpp:211
static Field stringCopy(const char *str_)
Makes a copy of str_ in a new Field.
Definition: Field.hpp:265
const char * data() const
Returns the (non-null-terminated) data underlying this field.
Definition: Field.hpp:291
Field deepCopy() const
Makes a deep copy of self, returns it.
Definition: Field.hpp:243
bool operator!=(const char *rhs_) const
String comparison operator Returns true if self and rhs are not equivalent.
Definition: Field.hpp:191