Marine Library  1.0
C++ library for Linux Networking Development
data_stream_impl.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Zhao DAI <daidodo@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or any
7  * later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see accompanying file LICENSE.txt
16  * or <http://www.gnu.org/licenses/>.
17  */
18 
26 #ifndef DOZERG_DATA_STREAM_IMPL_H_20081016
27 #define DOZERG_DATA_STREAM_IMPL_H_20081016
28 
29 #include <string>
30 #include "../to_string.hh"
31 #include "../char_buffer.hh"
32 #include "../tools/net.hh" //tools::HostByteOrder
33 #include "../tools/debug.hh" //tools::DumpXXX
34 #include "../template.hh"
35 
36 NS_IMPL_BEGIN
37 
43 {
44  typedef bool (CDataStreamBase::*__SafeBool)() const;
45 public:
47  static const bool kByteOrderDefault = true;
53  void status(int code){status_ = code;}
58  int status() const{return status_;}
73  bool operator !() const{return !good();}
89  operator __SafeBool() const{return (good() ? &CDataStreamBase::good : NULL);}
104  bool good() const{return (0 == status_);}
111  void netByteOrder(bool nb){dataByteOrder_ = bo(nb);}
118  void littleEndian(bool endian){dataByteOrder_ = endian;}
119  //return:
120  // true little endian
121  // false big endian(net byte order)
128  bool littleEndian() const{return dataByteOrder_;}
129 protected:
130  explicit CDataStreamBase(bool netByteOrder = kByteOrderDefault, int code = 0)
131  : status_(code)
132  , hostByteOrder_(tools::HostByteOrder())
133  , dataByteOrder_(bo(netByteOrder))
134  {}
135  bool needReverse() const{return (hostByteOrder_ != dataByteOrder_);}
136  void pushStub(size_t pos){
137  if(good())
138  stubs_.push_back(pos);
139  }
140  bool popStub(size_t * pos){
141  if(!good())
142  return false;
143  if(stubs_.empty()){
144  status(1);
145  return false;
146  }
147  if(pos)
148  *pos = stubs_.back();
149  stubs_.pop_back();
150  return true;
151  }
152  bool checkStub(size_t pos){
153  if(!good())
154  return false;
155  if(stubs_.empty())
156  return true;
157  if(pos > stubs_.back()){
158  status(1);
159  return false;
160  }
161  return true;
162  }
163  size_t getStub(size_t end) const{
164  if(stubs_.empty())
165  return end;
166  return std::min(end, stubs_.back());
167  }
168  bool clearStub(){
169  if(!good())
170  return false;
171  stubs_.clear();
172  return true;
173  }
174  std::string toString() const{
175  CToString oss;
176  oss<<"{status_="<<status_
177  <<", hostByteOrder_="<<(hostByteOrder_ ? "LittleEndian" : "BigEndian")
178  <<", dataByteOrder_="<<(dataByteOrder_ ? "LittleEndian" : "BigEndian");
179  if(!stubs_.empty()){
180  oss<<", stubs_={";
181  for(size_t i = 0;i < stubs_.size();++i){
182  if(i)
183  oss<<", ";
184  oss<<stubs_[i];
185  }
186  oss<<'}';
187  }
188  oss<<'}';
189  return oss.str();
190  }
191 private:
192  bool bo(bool net){return (net ? false : hostByteOrder_);}
193  //fields
194  int status_; // Error status
195  const bool hostByteOrder_; // Byte order of the environment:
196  // true: little endian
197  // false: big endian
198  bool dataByteOrder_; // Byte order of the data:
199  // true: little endian
200  // false: big endian
201  std::vector<size_t> stubs_;
202 };
203 
204 #ifndef DOX_UNDOCUMENT_FLAG
205 
206 template<typename Char>
207 inline void __buf_copy(Char * dst, const Char * src, size_t sz)
208 {
209  typedef std::char_traits<Char> __Traits;
210  assert(sz);
211  if(1 == sz)
212  __Traits::assign(*dst, *src);
213  else
214  __Traits::copy(dst, src, sz);
215 }
216 
217 template<typename Char>
218 inline void __buf_move(Char * dst, const Char * src, size_t sz)
219 {
220  typedef std::char_traits<Char> __Traits;
221  assert(sz);
222  if(1 == sz)
223  __Traits::assign(*dst, *src);
224  else
225  __Traits::move(dst, src, sz);
226 }
227 
228 inline std::string dumpBufPart(const char * buf, size_t sz, size_t part)
229 {
230  if(!buf)
231  return std::string("(NULL)");
232  CToString oss;
233  oss<<'('<<sz<<')'
234  <<tools::DumpHex(buf, part, ' ', false)
235  <<" | ";
236  if(sz > part)
237  oss<<tools::DumpHex(buf + part, sz - part, ' ', false);
238  return oss.str();
239 }
240 
241 template<class Buf>
242 class __buf_ref_data
243 {
244 public:
245  typedef Buf __Buf;
246  typedef typename __Buf::value_type __Char;
247 private:
248  typedef __buf_ref_data<__Buf> __Myt;
249 public:
250  explicit __buf_ref_data(__Buf & buf)
251  : buf_(buf)
252  , begin_(buf.size())
253  , cur_(0)
254  {}
255  __buf_ref_data(__Buf & buf, size_t begin)
256  : buf_(buf)
257  , begin_(begin)
258  , cur_(0)
259  {}
260  size_t cur() const{return cur_;}
261  __Char * data(size_t i){return &buf_[offset(i)];}
262  bool ensure(size_t len){
263  const size_t old = buf_.size();
264  if(offset(cur_ + len) > old)
265  buf_.resize(old + (old >> 1) + len);
266  return true;
267  }
268  bool seek(size_t pos){
269  if(pos > cur_ && !ensure(pos - cur_))
270  return false;
271  cur_ = pos;
272  return true;
273  }
274  void append(const __Char * buf, size_t sz){
275  insert(cur_, buf, sz);
276  }
277  void append(__Char c){
278  assert(offset(cur_ + 1) <= buf_.size());
279  *data(cur_++) = c;
280  }
281  void insert(size_t off, const __Char * buf, size_t sz){
282  assert(off <= cur_);
283  assert(sz && offset(cur_ + sz) <= buf_.size());
284  assert(buf);
285  const size_t c = cur_ - off;
286  if(c)
287  __buf_move(&buf_[offset(off + sz)], data(off), c);
288  __buf_copy(data(off), buf, sz);
289  cur_ += sz;
290  }
291  bool exportData(){
292  buf_.resize(offset(cur_));
293  begin_ = cur_ = 0;
294  return true;
295  }
296  template<typename SizeT>
297  bool exportData(SizeT * sz){
298  if(!exportData())
299  return false;
300  if(sz)
301  *sz = buf_.size();
302  return true;
303  }
304  bool exportData(__Buf & buf){
305  if(!exportData())
306  return false;
307  const size_t old = buf.size();
308  buf.resize(old + buf_.size());
309  __buf_copy(&buf[old], &buf_[0], buf_.size());
310  return true;
311  }
312  template<typename CharT>
313  bool exportData(CharT * buf, size_t * sz){
314  if(!buf || !sz || *sz < offset(cur_) || !exportData())
315  return false;
316  __buf_copy(buf, &buf_[0], buf_.size());
317  *sz = buf_.size();
318  return true;
319  }
320  std::string toString() const{
321  CToString oss;
322  oss<<"{begin_="<<begin_
323  <<", buf_="<<dumpBufPart(&buf_[0], begin_ + cur_, begin_)
324  <<"}";
325  return oss.str();
326  }
327 private:
328  size_t offset(size_t i) const{return begin_ + i;}
329  //members
330  __Buf & buf_;
331  size_t begin_;
332  size_t cur_;
333 };
334 
335 template<class Buf>
336 class __buf_data
337 {
338 public:
339  typedef Buf __Buf;
340  typedef typename __Buf::value_type __Char;
341 private:
342  typedef __buf_ref_data<__Buf> __Ref;
343  typedef __buf_data<__Buf> __Myt;
344 public:
345  explicit __buf_data(size_t reserve)
346  : buf_(reserve, 0)
347  , ref_(buf_, 0)
348  {}
349  size_t cur() const{return ref_.cur();}
350  __Char * data(size_t i){return ref_.data(i);}
351  bool ensure(size_t len){return ref_.ensure(len);}
352  bool seek(size_t pos){return ref_.seek(pos);}
353  void append(const __Char * buf, size_t sz){ref_.append(buf, sz);}
354  void append(__Char c){ref_.append(c);}
355  void insert(size_t offset, const __Char * buf, size_t sz){ref_.insert(offset, buf, sz);}
356  bool exportData(__Buf & buf){
357  ref_.exportData();
358  if(buf.empty()){
359  buf.swap(buf_);
360  }else{
361  const size_t old = buf.size();
362  buf.resize(old + buf_.size());
363  __buf_copy(&buf[old], data(0), buf_.size());
364  }
365  return true;
366  }
367  template<typename CharT>
368  bool exportData(CharT * buf, size_t * sz){
369  if(!buf || !sz || *sz < cur() || !ref_.exportData())
370  return false;
371  __buf_copy(buf, data(0), buf_.size());
372  *sz = buf_.size();
373  return true;
374  }
375  std::string toString() const{return ref_.toString();}
376 private:
377  //members
378  __Buf buf_;
379  __Ref ref_;
380 };
381 
382 template<typename Char>
383 class __buf_data<NS_SERVER::CCharBuffer<Char> >
384 {
385 public:
386  typedef CCharBuffer<Char> __Buf;
387  typedef typename __Buf::value_type __Char;
388 private:
389  typedef __buf_data<__Buf> __Myt;
390 public:
391  explicit __buf_data(__Char * buf, size_t sz)
392  : buf_(buf, sz, sz)
393  , cur_(0)
394  {}
395  size_t cur() const{return cur_;}
396  __Char * data(size_t i){return &buf_[i];}
397  const __Char * data(size_t i) const{return &buf_[i];}
398  bool ensure(size_t len){return (cur_ + len <= buf_.size());}
399  bool seek(size_t pos){
400  if(pos > buf_.size())
401  return false;
402  cur_ = pos;
403  return true;
404  }
405  void append(const __Char * buf, size_t sz){
406  insert(cur_, buf, sz);
407  }
408  void append(__Char c){
409  assert(cur_ + 1 <= buf_.size());
410  *data(cur_++) = c;
411  }
412  void insert(size_t off, const __Char * buf, size_t sz){
413  assert(off <= cur_);
414  assert(sz && cur_ + sz <= buf_.size());
415  assert(buf);
416  const size_t c = cur_ - off;
417  if(c)
418  __buf_move(data(off + sz), data(off), c);
419  __buf_copy(data(off), buf, sz);
420  cur_ += sz;
421  }
422  bool exportData(){
423  cur_ = 0;
424  return true;
425  }
426  template<typename SizeT>
427  bool exportData(SizeT * sz){
428  if(sz)
429  *sz = cur();
430  return exportData();
431  }
432  template<typename CharT>
433  bool exportData(CharT * buf, size_t * sz){
434  if(!buf || !sz || *sz < cur())
435  return false;
436  __buf_copy(buf, data(0), cur());
437  *sz = cur();
438  return exportData();
439  }
440  std::string toString() const{
441  CToString oss;
442  oss<<"{capacity="<<buf_.capacity()
443  <<", buf_="<<tools::DumpHex(data(0), cur_)
444  <<"}";
445  return oss.str();
446  }
447 private:
448  //members
449  __Buf buf_;
450  size_t cur_;
451 };
452 
453 //manipulators
454 
455 template<typename LenT, class T>
456 struct CManipulatorArrayPtr
457 {
458  T * c_;
459  size_t sz1_;
460  LenT * sz2_;
461  CManipulatorArrayPtr(T * c, size_t sz, LenT * p)
462  : c_(c)
463  , sz1_(sz)
464  , sz2_(p)
465  {}
466 };
467 
468 template<typename LenT, class T>
469 struct CManipulatorArrayCont
470 {
471  T & c_;
472  LenT max_;
473  CManipulatorArrayCont(T & c, LenT max_size)
474  : c_(c)
475  , max_(max_size)
476  {}
477 };
478 
479 template<typename LenT, class Iter>
480 struct CManipulatorArrayRange
481 {
482  Iter beg_, end_;
483  LenT * sz_;
484  CManipulatorArrayRange(Iter first, Iter last, LenT * sz)
485  : beg_(first)
486  , end_(last)
487  , sz_(sz)
488  {}
489 };
490 
491 template<class T>
492 struct CManipulatorRawPtr
493 {
494  T * c_;
495  size_t sz_;
496  CManipulatorRawPtr(T * c, size_t sz):c_(c),sz_(sz){}
497 };
498 
499 template<class T>
500 struct CManipulatorRawCont
501 {
502  T & c_;
503  size_t sz_;
504  size_t * sz2_;
505  CManipulatorRawCont(T & c, size_t sz, size_t * sz2)
506  : c_(c)
507  , sz_(sz)
508  , sz2_(sz2)
509  {}
510 };
511 
512 template<class Iter>
513 struct CManipulatorRawRange
514 {
515  Iter beg_,end_;
516  size_t * sz_;
517  CManipulatorRawRange(Iter first, Iter last, size_t * sz)
518  : beg_(first)
519  , end_(last)
520  , sz_(sz)
521  {}
522 };
523 
524 template<class T>
525 struct CManipulatorValueByteOrder
526 {
527  typedef void (*__Fun)(CDataStreamBase &);
528  T & c_;
529  __Fun fun_;
530  CManipulatorValueByteOrder(T & c, __Fun f):c_(c),fun_(f){}
531 };
532 
533 struct CManipulatorSeek
534 {
535  size_t pos_;
536  explicit CManipulatorSeek(size_t p):pos_(p){}
537 };
538 
539 struct CManipulatorSkip
540 {
541  ssize_t off_;
542  explicit CManipulatorSkip(ssize_t off):off_(off){}
543 };
544 
545 struct CManipulatorSkipFill
546 {
547  ssize_t off_;
548  int fill_;
549  explicit CManipulatorSkipFill(ssize_t off, int fill):off_(off),fill_(fill){}
550 };
551 
552 template<typename T>
553 struct CManipulatorSkipPtr
554 {
555  T * off_;
556  explicit CManipulatorSkipPtr(T * off):off_(off){}
557 };
558 
559 template<typename T>
560 struct CManipulatorSkipPtrFill
561 {
562  T * off_;
563  int fill_;
564  explicit CManipulatorSkipPtrFill(T * off, int fill):off_(off),fill_(fill){}
565 };
566 
567 template<class T>
568 struct CManipulatorOffsetValue
569 {
570  T & c_;
571  size_t pos_;
572  CManipulatorOffsetValue(size_t p, T & c):c_(c),pos_(p){}
573 };
574 
575 template<class T>
576 struct CManipulatorInsert
577 {
578  const T & c_;
579  size_t pos_;
580  CManipulatorInsert(size_t p, const T & c):c_(c),pos_(p){}
581 };
582 
583 template<class T>
584 struct CManipulatorProtobuf
585 {
586  typedef T __Msg;
587  __Msg & c_;
588  size_t sz_;
589  CManipulatorProtobuf(__Msg & c, size_t sz):c_(c),sz_(sz){}
590 };
591 
592 template<typename T>
593 class CManipulatorVarint
594 {
596 public:
597  typedef typename __Traits::__Signed __Signed;
598  typedef typename __Traits::__Unsigned __Unsigned;
599  CManipulatorVarint(T & c):c_(c){}
600  __Unsigned toUnsigned() const{
601  __Unsigned r = 0;
602  return trans(c_, r);
603  }
604  void fromUnsigned(__Unsigned v) const{
605  trans(v, c_);
606  }
607 private:
608  template<typename U>
609  static U trans(U v, U & t){return (t = v);}
610  static __Unsigned trans(__Signed v, __Unsigned & t){
611  return (t = (v << 1) ^ (v >> (__Traits::kMaxBits - 1)));
612  }
613  static __Signed trans(__Unsigned v, __Signed & t){
614  return (t = (v >> 1) ^ (-(v & 1)));
615  }
616  T & c_;
617 };
618 
619 struct CManipulatorStubPush
620 {
621  size_t sz_;
622  explicit CManipulatorStubPush(size_t sz):sz_(sz){}
623 };
624 
625 struct CManipulatorStubPop
626 {
627  bool align_, check_;
628  CManipulatorStubPop(bool align, bool check):align_(align), check_(check){}
629 };
630 
631 template<class T, class S>
632 struct CManipulatorEnd;
633 
634 template<>
635 struct CManipulatorEnd<void, void>{};
636 
637 template<class SizeT>
638 struct CManipulatorEnd<SizeT *, void>
639 {
640  SizeT * sz_;
641  explicit CManipulatorEnd(SizeT * s):sz_(s){}
642 };
643 
644 template<class CharT>
645 struct CManipulatorEnd<CharT *, size_t *>
646 {
647  CharT * buf_;
648  size_t * sz_;
649  CManipulatorEnd(CharT * buf, size_t * sz):buf_(buf),sz_(sz){}
650 };
651 
652 template<class BufT>
653 struct CManipulatorEnd<BufT, void>
654 {
655  BufT & buf_;
656  explicit CManipulatorEnd(BufT & buf):buf_(buf){}
657 };
658 
659 #endif // DOX_UNDOCUMENT_FLAG
660 
661 NS_IMPL_END
662 
663 #endif
bool littleEndian() const
Get byte order.
Definition: data_stream_impl.hh:128
Definition: to_string.hh:43
Provide interfaces similar to std::string for raw byte array.
Definition: char_buffer.hh:49
Definition: template.hh:23
void littleEndian(bool endian)
Set byte order.
Definition: data_stream_impl.hh:118
bool operator!() const
Test if current error status is NOT 0.
Definition: data_stream_impl.hh:73
void status(int code)
Set error status.
Definition: data_stream_impl.hh:53
static const bool kByteOrderDefault
Byte order of the underlying data buffer, default Net Byte Order.
Definition: data_stream_impl.hh:47
bool good() const
Test if current error status is 0, same as operator __SafeBool().
Definition: data_stream_impl.hh:104
void netByteOrder(bool nb)
Set byte order.
Definition: data_stream_impl.hh:111
NS_IMPL::CManipulatorEnd< void, void > end()
End operations for CInByteStream, COutByteStreamStrRef, COutByteStreamVecRef.
Definition: data_stream.hh:929
int status() const
Get error status.
Definition: data_stream_impl.hh:58
Base class of CInByteStream, COutByteStreamBasic.
Definition: data_stream_impl.hh:42