join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
view.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_DATA_VIEW_HPP
26#define JOIN_DATA_VIEW_HPP
27
28// libjoin.
29#include <join/utils.hpp>
30
31// C++.
32#include <istream>
33#include <string>
34#include <vector>
35
36// C.
37#include <cstring>
38#include <cstddef>
39
40namespace join
41{
42 namespace details
43 {
44 struct alignas (64) EscapedTable
45 {
46 uint8_t data[256];
47
48 constexpr EscapedTable ()
49 : data{}
50 {
51 for (unsigned i = 0; i < 0x20; ++i)
52 {
53 data[i] = 1;
54 }
55 data['"'] = 1;
56 data['\\'] = 1;
57 }
58 };
59
61
62 struct alignas (64) WhitespaceTable
63 {
64 uint8_t data[256];
65
66 constexpr WhitespaceTable ()
67 : data{}
68 {
69 data['\t'] = 1;
70 data['\n'] = 1;
71 data['\r'] = 1;
72 data[' '] = 1;
73 }
74 };
75
77 }
78
83 {
84 public:
85 using ViewPos = const char*;
86
92 constexpr StringView (const char* in, size_t count)
93 : _cur (in)
94 , _beg (in)
95 , _end (in ? in + count : in)
96 {
97 }
98
104 constexpr StringView (const char* first, const char* last)
105 : _cur (first)
106 , _beg (first)
107 , _end (last)
108 {
109 }
110
115 StringView (const char* in)
116 : _cur (in)
117 , _beg (in)
118 , _end (in ? in + std::char_traits<char>::length (in) : in)
119 {
120 }
121
126 StringView (const StringView& other) = default;
127
133 StringView& operator= (const StringView& other) = default;
134
139 StringView (StringView&& other) = default;
140
146 StringView& operator= (StringView&& other) = default;
147
151 ~StringView () = default;
152
157 inline int peek () const noexcept
158 {
159 if (JOIN_LIKELY (_cur < _end))
160 {
161 return static_cast<unsigned char> (*_cur);
162 }
163 return std::char_traits<char>::eof ();
164 }
165
170 inline int get () noexcept
171 {
172 if (JOIN_LIKELY (_cur < _end))
173 {
174 return static_cast<unsigned char> (*_cur++);
175 }
176 return std::char_traits<char>::eof ();
177 }
178
184 inline bool getIf (char expected) noexcept
185 {
186 if (JOIN_LIKELY (_cur < _end) && (*_cur == expected))
187 {
188 ++_cur;
189 return true;
190 }
191 return false;
192 }
193
199 inline bool getIfNoCase (char expected) noexcept
200 {
201 if (JOIN_LIKELY (_cur < _end))
202 {
203 const char c = *_cur;
204 if ((c | 32) == (expected | 32))
205 {
206 ++_cur;
207 return true;
208 }
209 }
210 return false;
211 }
212
219 inline size_t read (char* buf, size_t count) noexcept
220 {
221 const size_t available = _end - _cur;
222 const size_t nread = (count < available) ? count : available;
223 std::memcpy (buf, _cur, nread);
224 _cur += nread;
225 return nread;
226 }
227
232 inline void readUntilEscaped (std::string& out) noexcept
233 {
234 const char* beg = _cur;
235 const char* cur = _cur;
236 const char* end = _end;
237
238 while (cur < end && !details::escapedLookup.data[static_cast<unsigned char> (*cur)])
239 {
240 ++cur;
241 }
242
243 out.append (beg, static_cast<size_t> (cur - beg));
244 _cur = cur;
245 }
246
251 inline int skipWhitespaces () noexcept
252 {
253 const char* cur = _cur;
254 const char* end = _end;
255
256 while (cur < end && details::whitespaceLookup.data[static_cast<unsigned char> (*cur)])
257 {
258 ++cur;
259 }
260
261 _cur = cur;
262
263 return 0;
264 }
265
270 inline int skipWhitespacesAndComments () noexcept
271 {
272 const char* cur = _cur;
273 const char* end = _end;
274
275 while (cur < end)
276 {
277 while (cur < end && details::whitespaceLookup.data[static_cast<unsigned char> (*cur)])
278 {
279 ++cur;
280 }
281
282 if (cur >= end || *cur != '/')
283 {
284 break;
285 }
286
287 if (++cur >= end)
288 {
289 return -1;
290 }
291
292 if (*cur == '*')
293 {
294 ++cur;
295 bool closed = false;
296 while (cur < end)
297 {
298 if (*cur == '*' && (cur + 1 < end) && *(cur + 1) == '/')
299 {
300 cur += 2;
301 closed = true;
302 break;
303 }
304 ++cur;
305 }
306 if (!closed)
307 {
308 return -1;
309 }
310 }
311 else if (*cur == '/')
312 {
313 ++cur;
314 const char* p = static_cast<const char*> (memchr (cur, '\n', end - cur));
315 cur = p ? p : end;
316 }
317 else
318 {
319 return -1;
320 }
321 }
322
323 _cur = cur;
324
325 return 0;
326 }
327
332 inline ViewPos tell () const noexcept
333 {
334 return _cur;
335 }
336
341 inline void seek (ViewPos pos) noexcept
342 {
343 if (JOIN_LIKELY (pos >= _beg && pos <= _end))
344 {
345 _cur = pos;
346 }
347 else if (pos < _beg)
348 {
349 _cur = _beg;
350 }
351 else
352 {
353 _cur = _end;
354 }
355 }
356
357 private:
359 const char* _cur = nullptr;
360
362 const char* _beg = nullptr;
363
365 const char* _end = nullptr;
366 };
367
371 template <bool Seekable = true>
373 {
374 public:
375 using ViewPos = std::streampos;
376
381 BasicStreamView (std::istream& in)
382 : _in (in.rdbuf ())
383 {
384 }
385
390 BasicStreamView (const BasicStreamView& other) = delete;
391
398
404
411
415 ~BasicStreamView () = default;
416
421 inline int peek () const noexcept
422 {
423 return _in->sgetc ();
424 }
425
430 inline int get () noexcept
431 {
432 return _in->sbumpc ();
433 }
434
440 inline bool getIf (char expected) noexcept
441 {
442 if (_in->sgetc () == static_cast<int> (static_cast<unsigned char> (expected)))
443 {
444 _in->sbumpc ();
445 return true;
446 }
447 return false;
448 }
449
455 inline bool getIfNoCase (char expected) noexcept
456 {
457 const int c = _in->sgetc ();
458 if (JOIN_LIKELY (c != std::char_traits<char>::eof ()))
459 {
460 if ((static_cast<char> (c) | 32) == (expected | 32))
461 {
462 _in->sbumpc ();
463 return true;
464 }
465 }
466 return false;
467 }
468
475 inline size_t read (char* buf, size_t count) noexcept
476 {
477 return _in->sgetn (buf, count);
478 }
479
484 inline void readUntilEscaped (std::string& out) noexcept
485 {
486 int c;
487 while ((c = _in->sgetc ()) != std::char_traits<char>::eof () &&
488 !details::escapedLookup.data[static_cast<unsigned char> (c)])
489 {
490 out.push_back (static_cast<char> (c));
491 _in->sbumpc ();
492 }
493 }
494
499 inline int skipWhitespaces () noexcept
500 {
501 int c;
502 while ((c = _in->sgetc ()) != std::char_traits<char>::eof () &&
503 details::whitespaceLookup.data[static_cast<unsigned char> (c)])
504 {
505 _in->sbumpc ();
506 }
507
508 return 0;
509 }
510
515 inline int skipWhitespacesAndComments () noexcept
516 {
517 int c;
518
519 while ((c = _in->sgetc ()) != std::char_traits<char>::eof ())
520 {
521 while ((c = _in->sgetc ()) != std::char_traits<char>::eof () &&
522 details::whitespaceLookup.data[static_cast<unsigned char> (c)])
523 {
524 _in->sbumpc ();
525 }
526
527 if (c != '/')
528 {
529 break;
530 }
531
532 _in->sbumpc ();
533 c = _in->sgetc ();
534
535 if (c == std::char_traits<char>::eof ())
536 {
537 return -1;
538 }
539
540 if (c == '*')
541 {
542 _in->sbumpc ();
543 bool closed = false;
544
545 while ((c = _in->sbumpc ()) != std::char_traits<char>::eof ())
546 {
547 if (c == '*' && _in->sgetc () == '/')
548 {
549 _in->sbumpc ();
550 closed = true;
551 break;
552 }
553 }
554
555 if (!closed)
556 {
557 return -1;
558 }
559 }
560 else if (c == '/')
561 {
562 _in->sbumpc ();
563
564 while ((c = _in->sbumpc ()) != std::char_traits<char>::eof () && c != '\n')
565 {
566 }
567 }
568 else
569 {
570 return -1;
571 }
572 }
573
574 return 0;
575 }
576
581 template <bool S = Seekable>
582 inline typename std::enable_if<S, ViewPos>::type tell () const noexcept
583 {
584 return _in->pubseekoff (0, std::ios::cur, std::ios::in);
585 }
586
591 template <bool S = Seekable>
592 inline typename std::enable_if<S, void>::type seek (ViewPos pos) noexcept
593 {
594 _in->pubseekpos (pos, std::ios::in);
595 }
596
597 private:
599 std::streambuf* _in;
600 };
601
606
611
616
621 template <typename ViewType>
622 struct is_seekable : std::false_type
623 {
624 };
625
629 template <>
630 struct is_seekable<StringView> : std::true_type
631 {
632 };
633
637 template <>
638 struct is_seekable<BasicStreamView<true>> : std::true_type
639 {
640 };
641
645 template <typename ViewType, bool Seekable = is_seekable<ViewType>::value>
647
651 template <typename ViewType>
652 class BufferingView<ViewType, true>
653 {
654 public:
659 explicit BufferingView (ViewType& view)
660 : _view (view)
661 , _beg (view.tell ())
662 {
663 }
664
669 inline int peek () const noexcept
670 {
671 return _view.peek ();
672 }
673
678 inline int get () noexcept
679 {
680 return _view.get ();
681 }
682
688 inline bool getIf (char expected) noexcept
689 {
690 return _view.getIf (expected);
691 }
692
698 inline bool getIfNoCase (char expected) noexcept
699 {
700 return _view.getIfNoCase (expected);
701 }
702
707 inline void snapshot (std::string& out)
708 {
709 size_t len = _view.tell () - _beg;
710 out.resize (len);
711
712 _view.seek (_beg);
713 _view.read (&out[0], len);
714 }
715
720 inline void consume (std::string& out)
721 {
722 snapshot (out);
723 _beg = _view.tell ();
724 }
725
726 private:
728 ViewType& _view;
729
731 typename ViewType::ViewPos _beg;
732 };
733
737 template <typename ViewType>
738 class BufferingView<ViewType, false>
739 {
740 public:
745 explicit BufferingView (ViewType& view)
746 : _view (view)
747 {
748 static thread_local std::vector<char> buffer;
749 buffer.clear ();
750 buffer.reserve (32);
751 _buf = &buffer;
752 }
753
758 inline int peek () const noexcept
759 {
760 return _view.peek ();
761 }
762
767 inline int get () noexcept
768 {
769 const int c = _view.get ();
770 if (JOIN_LIKELY (c != std::char_traits<char>::eof ()))
771 {
772 _buf->push_back (static_cast<char> (c));
773 }
774 return c;
775 }
776
782 inline bool getIf (char expected) noexcept
783 {
784 if (_view.peek () == static_cast<int> (static_cast<unsigned char> (expected)))
785 {
786 _buf->push_back (static_cast<char> (_view.get ()));
787 return true;
788 }
789 return false;
790 }
791
797 inline bool getIfNoCase (char expected) noexcept
798 {
799 const int c = _view.peek ();
800 if (JOIN_LIKELY (c != std::char_traits<char>::eof ()))
801 {
802 if ((static_cast<char> (c) | 32) == (expected | 32))
803 {
804 _buf->push_back (static_cast<char> (_view.get ()));
805 return true;
806 }
807 }
808 return false;
809 }
810
815 inline void snapshot (std::string& out)
816 {
817 out.assign (_buf->data (), _buf->size ());
818 }
819
824 inline void consume (std::string& out)
825 {
826 snapshot (out);
827 _buf->clear ();
828 }
829
830 private:
832 ViewType& _view;
833
835 std::vector<char>* _buf = nullptr;
836 };
837}
838
839#endif
basic stream view.
Definition view.hpp:373
int get() noexcept
extracts character.
Definition view.hpp:430
std::enable_if< S, void >::type seek(ViewPos pos) noexcept
seek to the specified position.
Definition view.hpp:592
BasicStreamView(const BasicStreamView &other)=delete
copy constructor.
size_t read(char *buf, size_t count) noexcept
read characters.
Definition view.hpp:475
BasicStreamView(BasicStreamView &&other)=delete
move constructor.
void readUntilEscaped(std::string &out) noexcept
read characters until escaped.
Definition view.hpp:484
std::enable_if< S, ViewPos >::type tell() const noexcept
get input position indicator.
Definition view.hpp:582
std::streampos ViewPos
Definition view.hpp:375
~BasicStreamView()=default
destroy instance.
int skipWhitespaces() noexcept
skip whitespaces.
Definition view.hpp:499
int skipWhitespacesAndComments() noexcept
skip whitespaces and comments.
Definition view.hpp:515
int peek() const noexcept
get character without extracting it.
Definition view.hpp:421
bool getIf(char expected) noexcept
extracts expected character.
Definition view.hpp:440
BasicStreamView & operator=(const BasicStreamView &other)=delete
copy assignment.
BasicStreamView(std::istream &in)
default constructor.
Definition view.hpp:381
bool getIfNoCase(char expected) noexcept
extracts expected character (case insensitive, ASCII-only).
Definition view.hpp:455
BufferingView(ViewType &view)
default constructor.
Definition view.hpp:745
bool getIfNoCase(char expected) noexcept
extracts expected character (case insensitive, ASCII-only).
Definition view.hpp:797
void consume(std::string &out)
consume buffered data.
Definition view.hpp:824
void snapshot(std::string &out)
get snapshot.
Definition view.hpp:815
int peek() const noexcept
get character without extracting it.
Definition view.hpp:758
bool getIf(char expected) noexcept
extracts expected character.
Definition view.hpp:782
int get() noexcept
extracts character.
Definition view.hpp:767
int get() noexcept
extracts character.
Definition view.hpp:678
void consume(std::string &out)
consume buffered data.
Definition view.hpp:720
int peek() const noexcept
get character without extracting it.
Definition view.hpp:669
void snapshot(std::string &out)
get snapshot.
Definition view.hpp:707
bool getIfNoCase(char expected) noexcept
extracts expected character (case insensitive, ASCII-only).
Definition view.hpp:698
BufferingView(ViewType &view)
default constructor.
Definition view.hpp:659
bool getIf(char expected) noexcept
extracts expected character.
Definition view.hpp:688
buffering view adapter
Definition view.hpp:646
string view.
Definition view.hpp:83
bool getIfNoCase(char expected) noexcept
extracts expected character (case insensitive, ASCII-only).
Definition view.hpp:199
void readUntilEscaped(std::string &out) noexcept
read characters until escaped.
Definition view.hpp:232
StringView & operator=(const StringView &other)=default
copy assignment.
StringView(const StringView &other)=default
copy constructor.
StringView(const char *in)
default constructor.
Definition view.hpp:115
const char * ViewPos
Definition view.hpp:85
constexpr StringView(const char *in, size_t count)
default constructor.
Definition view.hpp:92
StringView(StringView &&other)=default
move constructor.
int peek() const noexcept
get character without extracting it.
Definition view.hpp:157
ViewPos tell() const noexcept
get input position indicator.
Definition view.hpp:332
~StringView()=default
destroy instance.
void seek(ViewPos pos) noexcept
seek to the specified position.
Definition view.hpp:341
size_t read(char *buf, size_t count) noexcept
read characters.
Definition view.hpp:219
int skipWhitespaces() noexcept
skip whitespaces.
Definition view.hpp:251
int skipWhitespacesAndComments() noexcept
skip whitespaces and comments.
Definition view.hpp:270
int get() noexcept
extracts character.
Definition view.hpp:170
bool getIf(char expected) noexcept
extracts expected character.
Definition view.hpp:184
constexpr StringView(const char *first, const char *last)
default constructor.
Definition view.hpp:104
constexpr WhitespaceTable whitespaceLookup
Definition view.hpp:76
constexpr EscapedTable escapedLookup
Definition view.hpp:60
Definition acceptor.hpp:32
Definition error.hpp:137
Definition view.hpp:45
uint8_t data[256]
Definition view.hpp:46
constexpr EscapedTable()
Definition view.hpp:48
Definition view.hpp:63
constexpr WhitespaceTable()
Definition view.hpp:66
uint8_t data[256]
Definition view.hpp:64
trait to determine if a view type is seekable.
Definition view.hpp:623
#define JOIN_LIKELY(x)
Definition utils.hpp:46