| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | // this file is included into struct Parser | 
| 2 |  |  |  |  |  |  | // ! no namespaces here or #includes here ! | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | struct MessageBuilder { | 
| 5 |  |  |  |  |  |  | MessageBuilder (MessageBuilder&&) = default; | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | Opcode      opcode  () const noexcept { return _opcode; } | 
| 8 |  |  |  |  |  |  | DeflateFlag deflate () const noexcept { return _deflate; } | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | MessageBuilder& opcode  (Opcode v)      noexcept { _opcode = v; return *this; } | 
| 11 |  |  |  |  |  |  | MessageBuilder& deflate (DeflateFlag v) noexcept { _deflate = v; return *this; } | 
| 12 | 0 | 0 |  |  |  |  | MessageBuilder& deflate (bool v)        noexcept { _deflate = v ? DeflateFlag::YES : DeflateFlag::NO; return *this; } | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 0 |  |  |  |  |  | StringPair send (string& payload) { | 
| 15 | 0 |  |  |  |  |  | auto apply_deflate = maybe_deflate(payload.length()); | 
| 16 | 0 | 0 |  |  |  |  | return _parser.start_message(_opcode, apply_deflate).send(payload, true); | 
| 17 |  |  |  |  |  |  | } | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | template ())>::type, string>::value>::type> | 
| 20 | 0 |  |  |  |  |  | StringChain send (Begin payload_begin, End payload_end) { | 
| 21 | 0 |  |  |  |  |  | size_t payload_length = 0; | 
| 22 | 0 | 0 |  |  |  |  | for (auto it = payload_begin; it != payload_end; ++it) payload_length += (*it).length(); | 
| 23 | 0 |  |  |  |  |  | auto apply_deflate = maybe_deflate(payload_length); | 
| 24 | 0 | 0 |  |  |  |  | return _parser.start_message(_opcode, apply_deflate).send(payload_begin, payload_end, true); | 
| 25 |  |  |  |  |  |  | } | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | template ::value>::type> | 
| 28 | 0 |  |  |  |  |  | std::vector send (Begin cont_begin, End cont_end) { | 
| 29 | 0 |  |  |  |  |  | std::vector ret; | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 0 |  |  |  |  |  | size_t sz = 0, idx = 0, payload_sz = 0, last_nonempty = 0; | 
| 32 | 0 | 0 |  |  |  |  | auto cont_range = make_iterator_pair(cont_begin, cont_end); | 
| 33 |  |  |  |  |  |  |  | 
| 34 | 0 | 0 |  |  |  |  | for (const auto& range : cont_range) { | 
| 35 | 0 |  |  |  |  |  | size_t piece_sz = 0; | 
| 36 | 0 | 0 |  |  |  |  | for (const auto& it : range) { | 
| 37 | 0 |  |  |  |  |  | auto length = it.length(); | 
| 38 | 0 |  |  |  |  |  | piece_sz += length; | 
| 39 | 0 | 0 |  |  |  |  | if (length) ++sz; | 
| 40 |  |  |  |  |  |  | } | 
| 41 | 0 | 0 |  |  |  |  | if (piece_sz) { last_nonempty = idx; }; | 
| 42 | 0 |  |  |  |  |  | payload_sz += piece_sz; | 
| 43 | 0 |  |  |  |  |  | ++idx; | 
| 44 |  |  |  |  |  |  | }; | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 0 | 0 |  |  |  |  | auto sender = _parser.start_message(_opcode, maybe_deflate(payload_sz)); | 
|  |  | 0 |  |  |  |  |  | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 0 | 0 |  |  |  |  | if (!payload_sz) { | 
| 49 | 0 | 0 |  |  |  |  | ret.reserve(1); | 
| 50 | 0 | 0 |  |  |  |  | ret.push_back(sender.send(true)); | 
|  |  | 0 |  |  |  |  |  | 
| 51 | 0 |  |  |  |  |  | return ret; | 
| 52 |  |  |  |  |  |  | } | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 0 | 0 |  |  |  |  | ret.reserve(sz); | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 0 |  |  |  |  |  | idx = 0; | 
| 57 | 0 | 0 |  |  |  |  | for (auto& range : cont_range) { | 
| 58 | 0 |  |  |  |  |  | size_t piece_sz = 0; | 
| 59 | 0 | 0 |  |  |  |  | for (const auto& it: range) piece_sz += it.length(); | 
| 60 | 0 | 0 |  |  |  |  | if (piece_sz) { | 
| 61 | 0 | 0 |  |  |  |  | auto frame_range = sender.send(range.begin(), range.end(), idx == last_nonempty); | 
| 62 | 0 | 0 |  |  |  |  | for (const auto& s : frame_range) ret.push_back(s); | 
|  |  | 0 |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | } | 
| 64 | 0 | 0 |  |  |  |  | if (idx == last_nonempty) break; | 
| 65 | 0 |  |  |  |  |  | ++idx; | 
| 66 |  |  |  |  |  |  | } | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 0 |  |  |  |  |  | return ret; | 
| 69 |  |  |  |  |  |  | } | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | private: | 
| 72 |  |  |  |  |  |  | friend Parser; | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | Parser&     _parser; | 
| 75 |  |  |  |  |  |  | Opcode      _opcode  = Opcode::BINARY; | 
| 76 |  |  |  |  |  |  | DeflateFlag _deflate = DeflateFlag::DEFAULT; | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 0 |  |  |  |  |  | MessageBuilder (Parser& parser) : _parser(parser) {} | 
| 79 |  |  |  |  |  |  | MessageBuilder (MessageBuilder&) = delete; | 
| 80 |  |  |  |  |  |  |  | 
| 81 | 0 |  |  |  |  |  | DeflateFlag maybe_deflate (size_t payload_length) { | 
| 82 | 0 |  |  |  |  |  | switch (_deflate) { | 
| 83 | 0 |  |  |  |  |  | case DeflateFlag::NO      : return _deflate; | 
| 84 | 0 |  |  |  |  |  | case DeflateFlag::YES     : return _deflate; | 
| 85 |  |  |  |  |  |  | case DeflateFlag::DEFAULT : | 
| 86 | 0 | 0 |  |  |  |  | return _opcode == Opcode::TEXT && | 
| 87 | 0 | 0 |  |  |  |  | _parser._deflate_cfg && | 
| 88 | 0 | 0 |  |  |  |  | _parser._deflate_cfg->compression_threshold <= payload_length && | 
| 89 |  |  |  |  |  |  | payload_length > 0 | 
| 90 | 0 | 0 |  |  |  |  | ? DeflateFlag::YES : DeflateFlag::NO; | 
| 91 |  |  |  |  |  |  | } | 
| 92 | 0 |  |  |  |  |  | return DeflateFlag::NO; | 
| 93 |  |  |  |  |  |  | } | 
| 94 |  |  |  |  |  |  | }; |