YARP
Yet Another Robot Platform
Header.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <yarp/os/Header.h>
8 
9 #include <yarp/os/Bottle.h>
13 #include <yarp/os/Time.h>
14 
15 #include <algorithm>
16 
17 
18 using yarp::os::Header;
21 
22 namespace {
23 YARP_OS_LOG_COMPONENT(HEADER, "yarp.os.Header");
24 }
25 
27 {
28 public:
31  std::string&& frameId) :
32  sequenceNumber(count),
33  timeStamp(time),
34  frameId(std::move(frameId))
35  {
36  }
37 
38  Private() = default;
39 
40  void clear()
41  {
42  sequenceNumber = Header::npos;
43  timeStamp = 0.0;
44  frameId.clear();
45  }
46 
48  {
50  if (sequenceNumber == Header::npos) {
51  // npos is not used to store a valid header, just restart the
52  // counter
53  sequenceNumber = 0;
54  }
55  timeStamp = time;
56  }
57 
60  std::string frameId;
61 };
62 
63 
64 Header::Header(Header::count_t count, yarp::conf::float64_t time, std::string frameId) :
65  mPriv(new Private(count, time, std::move(frameId)))
66 {
67  yCAssert(HEADER, mPriv->frameId.find(' ') == std::string::npos);
68 }
69 
71  mPriv(new Private())
72 {
73 }
74 
75 Header::Header(const Header& rhs) :
76  mPriv(new Private(*(rhs.mPriv)))
77 {
78 }
79 
80 Header::Header(Header&& rhs) noexcept :
81  mPriv(std::exchange(rhs.mPriv, nullptr))
82 {
83 }
84 
86 {
87  delete mPriv;
88 }
89 
91 {
92  if (&rhs != this) {
93  *mPriv = *(rhs.mPriv);
94  }
95  return *this;
96 }
97 
99 {
100  if (&rhs != this) {
101  std::swap(mPriv, rhs.mPriv);
102  }
103  return *this;
104 }
105 
107 {
108  return mPriv->sequenceNumber;
109 }
110 
112 {
113  return mPriv->timeStamp;
114 }
115 
116 std::string Header::frameId() const
117 {
118  return mPriv->frameId;
119 }
120 
121 bool Header::isValid() const
122 {
123  return mPriv->sequenceNumber != npos;
124 }
125 
127 {
128  if (connection.isTextMode()) {
129  std::string stampStr = connection.expectText();
130  Header::count_t seqNum;
132  int used;
133 
134  int ret = std::sscanf(stampStr.c_str(), "%u %lg %n", &seqNum, &ts, &used);
135  if (ret != 2 && used > 0) {
136  mPriv->clear();
137  return false;
138  }
139  mPriv->sequenceNumber = seqNum;
140  mPriv->timeStamp = ts;
141  mPriv->frameId = stampStr.substr((size_t)used, stampStr.find(' ', used));
142  } else {
143  connection.convertTextMode();
144 
145  // Read list length (must be 3 or 2 for compatibility with Stamp)
146  std::int32_t header = connection.expectInt32();
147  if (header != BOTTLE_TAG_LIST) {
148  mPriv->clear();
149  return false;
150  }
151  std::int32_t len = connection.expectInt32();
152  if (len != 2 && len != 3) {
153  mPriv->clear();
154  return false;
155  }
156 
157  // Read sequence number
158  std::int32_t code = connection.expectInt32();
159  if (code != BOTTLE_TAG_INT32) {
160  mPriv->clear();
161  return false;
162  }
163  mPriv->sequenceNumber = static_cast<Header::count_t>(connection.expectInt32());
164 
165  // Read timestamp
166  code = connection.expectInt32();
167  if (code != BOTTLE_TAG_FLOAT64) {
168  mPriv->clear();
169  return false;
170  }
171  mPriv->timeStamp = connection.expectFloat64();
172 
173  // Read frameId (unless receiving a Stamp)
174  if (len == 3) {
175  code = connection.expectInt32();
176  if (code != BOTTLE_TAG_STRING) {
177  mPriv->clear();
178  return false;
179  }
180  mPriv->frameId = connection.expectString();
181  yCAssert(HEADER, mPriv->frameId.find(' ') == std::string::npos);
182  } else {
183  mPriv->frameId.clear();
184  }
185 
186  if (connection.isError()) {
187  mPriv->clear();
188  return false;
189  }
190  }
191  return !connection.isError();
192 }
193 
194 
195 // In order to keep the Header class as much compatible as possible with
196 // Stamp, if the frameId is empty, it is not serialized at all.
197 bool Header::write(ConnectionWriter& connection) const
198 {
199  if (connection.isTextMode()) {
200  static constexpr size_t buf_size = 512;
201  char buf[buf_size];
202  if (!mPriv->frameId.empty()) {
203  std::snprintf(buf, buf_size, "%d %.*g %s", mPriv->sequenceNumber, DBL_DIG, mPriv->timeStamp, mPriv->frameId.c_str());
204  } else {
205  std::snprintf(buf, buf_size, "%d %.*g", mPriv->sequenceNumber, DBL_DIG, mPriv->timeStamp);
206  }
207  connection.appendText(buf);
208  } else {
209  connection.appendInt32(BOTTLE_TAG_LIST); // nested structure
210  connection.appendInt32(mPriv->frameId.empty() ? 2 : 3); // with two or three elements
211  connection.appendInt32(BOTTLE_TAG_INT32);
212  connection.appendInt32(static_cast<std::int32_t>(mPriv->sequenceNumber));
213  connection.appendInt32(BOTTLE_TAG_FLOAT64);
214  connection.appendFloat64(mPriv->timeStamp);
215  if (!mPriv->frameId.empty()) {
216  connection.appendInt32(BOTTLE_TAG_STRING);
217  connection.appendString(mPriv->frameId);
218  }
219  connection.convertTextMode();
220  }
221  return !connection.isError();
222 }
223 
225 {
226  mPriv->update(Time::now());;
227 }
228 
230 {
231  mPriv->update(time);
232 }
233 
234 void Header::setFrameId(std::string frameId)
235 {
236  mPriv->frameId = std::move(frameId);
237 }
#define BOTTLE_TAG_FLOAT64
Definition: Bottle.h:25
#define BOTTLE_TAG_INT32
Definition: Bottle.h:21
#define BOTTLE_TAG_STRING
Definition: Bottle.h:26
#define BOTTLE_TAG_LIST
Definition: Bottle.h:28
bool ret
Private(Header::count_t count, yarp::conf::float64_t time, std::string &&frameId)
Definition: Header.cpp:29
yarp::conf::float64_t timeStamp
Definition: Header.cpp:59
void update(yarp::conf::float64_t time)
Definition: Header.cpp:47
Header::count_t sequenceNumber
Definition: Header.cpp:58
An interface for reading from a network connection.
virtual std::string expectString()
Read a string from the network connection.
virtual bool isTextMode() const =0
Check if the connection is text mode.
virtual std::int32_t expectInt32()=0
Read a 32-bit integer from the network connection.
virtual std::string expectText(const char terminatingChar='\n')=0
Read some text from the network connection.
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary.
virtual bool isError() const =0
virtual yarp::conf::float64_t expectFloat64()=0
Read a 64-bit floating point number from the network connection.
An interface for writing to a network connection.
virtual bool isError() const =0
virtual bool isTextMode() const =0
Check if the connection is text mode.
virtual void appendText(const std::string &str, const char terminate='\n')=0
Send a terminated string to the network connection.
virtual bool convertTextMode()=0
Converts a standard description in binary into a textual description, if the connection is in text-mo...
virtual void appendInt32(std::int32_t data)=0
Send a representation of a 32-bit integer to the network connection.
virtual void appendFloat64(yarp::conf::float64_t data)=0
Send a representation of a 64-bit floating point number to the network connection.
virtual void appendString(const char *str, const char terminate='\n') final
Send a character sequence to the network connection.
An abstraction for a sequence number, time stamp and/or frame id.
Definition: Header.h:25
std::uint32_t count_t
Definition: Header.h:27
bool write(ConnectionWriter &connection) const override
Write this object to a network connection.
Definition: Header.cpp:197
~Header() override
Destructor.
Definition: Header.cpp:85
bool read(ConnectionReader &connection) override
Read this object from a network connection.
Definition: Header.cpp:126
Header & operator=(const Header &rhs)
Copy assignment operator.
Definition: Header.cpp:90
yarp::conf::float64_t timeStamp() const
Get the time stamp.
Definition: Header.cpp:111
bool isValid() const
Check if this Header is valid.
Definition: Header.cpp:121
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Header.cpp:224
static constexpr count_t npos
Maximum sequence number, after which an incrementing sequence should return to zero.
Definition: Header.h:33
void setFrameId(std::string frameId)
Set the frame id for this header.
Definition: Header.cpp:234
Header()
Construct an invalid Header.
Definition: Header.cpp:70
std::string frameId() const
Get the frame id.
Definition: Header.cpp:116
count_t count() const
Get the sequence number.
Definition: Header.cpp:106
#define yCAssert(component, x)
Definition: LogComponent.h:169
#define YARP_OS_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:35
yarp::rosmsg::std_msgs::Header Header
Definition: Header.h:21
double float64_t
Definition: numeric.h:77
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:121