This is Unofficial EPICS BASE Doxygen Site
serializeHelper.cpp
Go to the documentation of this file.
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 /*
6  * serializeHelper.cpp
7  *
8  * Created on: Oct 22, 2010
9  * Author: Miha Vitorovic
10  */
11 
12 #include <algorithm>
13 
14 #include <epicsEndian.h>
15 
16 #define epicsExportSharedSymbols
17 #include <pv/pvType.h>
18 #include <pv/byteBuffer.h>
19 #include <pv/epicsException.h>
20 #include <pv/byteBuffer.h>
21 #include <pv/serializeHelper.h>
22 
23 using namespace std;
24 
25 namespace epics {
26  namespace pvData {
27 
28  void SerializeHelper::writeSize(std::size_t s, ByteBuffer* buffer,
29  SerializableControl* flusher) {
30  flusher->ensureBuffer(sizeof(int64)+1);
31  SerializeHelper::writeSize(s, buffer);
32  }
33 
34  void SerializeHelper::writeSize(std::size_t s, ByteBuffer* buffer) {
35  if(s==(std::size_t)-1) // null not a size, but used in PVUnion::serialize()
36  buffer->putByte(-1);
37  else if(s<254)
38  buffer->putByte(static_cast<int8>(s));
39  else
40  {
41  buffer->putByte(-2);
42  buffer->putInt(static_cast<uint32>(s)); // (byte)-2 + size
43  }
44  }
45 
46  std::size_t SerializeHelper::readSize(ByteBuffer* buffer,
47  DeserializableControl* control) {
48  control->ensureData(1);
49  int8 b = buffer->getByte();
50  if(b==-1)
51  return -1;
52  else if(b==-2) {
53  control->ensureData(sizeof(int32));
54  int32 s = buffer->getInt();
55  if(s<0) THROW_BASE_EXCEPTION("negative size");
56  return s;
57  }
58  else
59  return (std::size_t)(b<0 ? b+256 : b);
60  }
61 
62  void SerializeHelper::serializeString(const string& value,
63  ByteBuffer* buffer, SerializableControl* flusher) {
64  std::size_t len = value.length();
65  SerializeHelper::writeSize(len, buffer, flusher);
66  if (len<=0) return;
67  std::size_t i = 0;
68  while(true) {
69  std::size_t maxToWrite = min(len-i, buffer->getRemaining());
70  buffer->put(value.data(), i, maxToWrite); // ASCII
71  i += maxToWrite;
72  if(i<len)
73  flusher->flushSerializeBuffer();
74  else
75  break;
76  }
77  }
78 
79  void SerializeHelper::serializeSubstring(const string& value,
80  std::size_t offset, std::size_t count, ByteBuffer* buffer,
81  SerializableControl* flusher) {
82  /*if(offset<0)
83  offset = 0;
84  else*/ if(offset>value.length()) offset = value.length();
85 
86  if(offset+count>value.length()) count = value.length()-offset;
87 
88  SerializeHelper::writeSize(count, buffer, flusher);
89  /*if (count<=0)*/ return;
90  std::size_t i = 0;
91  while(true) {
92  std::size_t maxToWrite = min(count-i, buffer->getRemaining());
93  buffer->put(value.data(), offset+i, maxToWrite); // ASCII
94  i += maxToWrite;
95  if(i<count)
96  flusher->flushSerializeBuffer();
97  else
98  break;
99  }
100  }
101 
102  string SerializeHelper::deserializeString(ByteBuffer* buffer,
103  DeserializableControl* control) {
104 
105  std::size_t size = SerializeHelper::readSize(buffer, control);
106  if(size!=(size_t)-1) // TODO null strings check, to be removed in the future
107  {
108  if (buffer->getRemaining()>=size)
109  {
110  // entire string is in buffer, simply create a string out of it (copy)
111  std::size_t pos = buffer->getPosition();
112  string str(buffer->getBuffer()+pos, size);
113  buffer->setPosition(pos+size);
114  return str;
115  }
116  else
117  {
118  string str;
119  str.reserve(size);
120  try {
121  std::size_t i = 0;
122  while(true) {
123  std::size_t toRead = min(size-i, buffer->getRemaining());
124  std::size_t pos = buffer->getPosition();
125  str.append(buffer->getBuffer()+pos, toRead);
126  buffer->setPosition(pos+toRead);
127  i += toRead;
128  if(i<size)
129  control->ensureData(1); // at least one
130  else
131  break;
132  }
133  return str;
134  } catch(...) {
135  throw;
136  }
137  }
138  }
139  else
140  return std::string();
141  }
142  }
143 }
144 
145 namespace {
146 using namespace epics::pvData;
147 
148 struct ToString : public epics::pvData::SerializableControl
149 {
150  typedef std::vector<epicsUInt8> buf_type;
151  buf_type buf;
152  buf_type& out;
153  ByteBuffer bufwrap;
154 
155  ToString(buf_type& out, int byteOrder = EPICS_BYTE_ORDER)
156  :buf(16*1024)
157  ,out(out)
158  ,bufwrap((char*)&buf[0], buf.size(), byteOrder)
159  {}
160 
161  virtual void flushSerializeBuffer()
162  {
163  size_t N = out.size();
164  out.resize(out.size()+bufwrap.getPosition());
165  std::copy(buf.begin(),
166  buf.begin()+bufwrap.getPosition(),
167  out.begin()+N);
168  bufwrap.clear();
169  }
170 
171  virtual void ensureBuffer(std::size_t size)
172  {
173  flushSerializeBuffer();
174  assert(bufwrap.getRemaining()>0);
175  }
176 
177  virtual void alignBuffer(std::size_t alignment)
178  {
179  if(bufwrap.getRemaining()<alignment)
180  flushSerializeBuffer();
181  assert(bufwrap.getRemaining()>=alignment);
182  bufwrap.align(alignment);
183  }
184 
185  virtual bool directSerialize(
186  ByteBuffer *existingBuffer,
187  const char* toSerialize,
188  std::size_t elementCount,
189  std::size_t elementSize)
190  {
191  return false;
192  }
193 
194  virtual void cachedSerialize(
195  std::tr1::shared_ptr<const Field> const & field,
196  ByteBuffer* buffer)
197  {
198  field->serialize(buffer, this);
199  }
200 };
201 
202 } // namespace
203 
204 namespace epics {
205  namespace pvData {
207  int byteOrder,
208  std::vector<epicsUInt8>& out)
209  {
210  ToString TS(out, byteOrder);
211  S->serialize(&TS.bufwrap, &TS);
212  TS.flushSerializeBuffer();
213  assert(TS.bufwrap.getPosition()==0);
214  }
215  }
216 }
217 
218 namespace {
219 struct FromString : public epics::pvData::DeserializableControl
220 {
221  ByteBuffer &buf;
223 
224  FromString(ByteBuffer& b)
225  :buf(b)
227  {}
228 
229  virtual void ensureData(std::size_t size)
230  {
231  if(size>buf.getRemaining())
232  throw std::logic_error("Incomplete buffer");
233  }
234 
235  virtual void alignData(std::size_t alignment)
236  {
237  size_t pos = buf.getPosition(), k = alignment-1;
238  if(pos&k) {
239  std::size_t npad = alignment-(pos&k);
240  ensureData(npad);
241  buf.align(alignment);
242  }
243  }
244 
245  virtual bool directDeserialize(
246  ByteBuffer *existingBuffer,
247  char* deserializeTo,
248  std::size_t elementCount,
249  std::size_t elementSize)
250  {
251  return false;
252  }
253  virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
254  ByteBuffer* buffer)
255  {
256  return create->deserialize(buffer, this);
257  }
258 };
259 }
260 
261 namespace epics {
262  namespace pvData {
264  ByteBuffer& buf)
265  {
266  FromString F(buf);
267  S->deserialize(&buf, &F);
268  }
269  }
270 }
int8_t int8
Definition: pvType.h:75
Definition: link.h:174
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
virtual void serialize(ByteBuffer *buffer, SerializableControl *flusher) const =0
size_t elementSize(ScalarType id)
gives sizeof(T) where T depends on the scalar type id.
Definition: TypeFunc.cpp:82
EPICS_ALWAYS_INLINE int8 getByte()
Definition: byteBuffer.h:617
int i
Definition: scan.c:967
EPICS_ALWAYS_INLINE void putInt(int32 value)
Definition: byteBuffer.h:537
const char * getBuffer() const
Definition: byteBuffer.h:294
#define min(x, y)
Definition: flexdef.h:78
Base class for serialization.
Definition: serialize.h:140
void epicsShareFunc deserializeFromBuffer(Serializable *S, ByteBuffer &in)
deserializeFromBuffer Deserialize into S from provided vector
Definition: memory.hpp:41
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
#define str(v)
Callback class for deserialization.
Definition: serialize.h:89
void align(std::size_t size, char fill='\0')
Definition: byteBuffer.h:504
std::size_t getPosition() const
Definition: byteBuffer.h:346
void copy(PVValueArray< T > &pvFrom, size_t fromOffset, size_t fromStride, PVValueArray< T > &pvTo, size_t toOffset, size_t toStride, size_t count)
Copy a subarray from one scalar array to another.
EPICS_ALWAYS_INLINE int32 getInt()
Definition: byteBuffer.h:629
void setPosition(std::size_t pos)
Definition: byteBuffer.h:357
pvData
Definition: monitor.h:428
EPICS_ALWAYS_INLINE void putByte(int8 value)
Definition: byteBuffer.h:525
This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
Definition: byteBuffer.h:233
std::size_t getRemaining() const
Definition: byteBuffer.h:391
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
int64_t int64
Definition: pvType.h:87
#define THROW_BASE_EXCEPTION(msg)
std::tr1::shared_ptr< FieldCreate > FieldCreatePtr
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *flusher)=0
virtual void ensureBuffer(std::size_t size)=0
Callback class for serialization.
Definition: serialize.h:34
virtual void ensureData(std::size_t size)=0
#define EPICS_BYTE_ORDER
Definition: osdWireConfig.h:16
void epicsShareFunc serializeToVector(const Serializable *S, int byteOrder, std::vector< epicsUInt8 > &out)
Push serialize and append to the provided byte vector. No caching is done. Only complete serializatio...
int32_t int32
Definition: pvType.h:83