forked from rbeeli/websocketclient-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsockutils.cpp
107 lines (92 loc) · 2.48 KB
/
sockutils.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <string.h>
#include <assert.h>
#include "sockutils.hpp"
namespace NNet {
TLineSplitter::TLineSplitter(int maxLen)
: WPos(0)
, RPos(0)
, Size(0)
, Cap(maxLen * 2)
, Data(Cap, 0)
, View(Data)
{ }
TLine TLineSplitter::Pop() {
auto end = View.substr(RPos, Size);
auto begin = View.substr(0, Size - end.size());
auto p1 = end.find('\n');
if (p1 == std::string_view::npos) {
auto p2 = begin.find('\n');
if (p2 == std::string_view::npos) {
return {};
}
RPos = p2 + 1;
Size -= end.size() + p2 + 1;
return TLine { end, begin.substr(0, p2 + 1) };
} else {
RPos += p1 + 1;
Size -= p1 + 1;
return TLine { end.substr(0, p1 + 1), {} };
}
}
void TLineSplitter::Push(const char* buf, size_t size) {
if (Size + size > Data.size()) {
throw std::runtime_error("Overflow");
}
auto first = std::min(size, Cap - WPos);
memcpy(&Data[WPos], buf, first);
memcpy(&Data[0], buf + first, std::max<size_t>(0, size - first));
WPos = (WPos + size) % Cap;
Size = Size + size;
}
TZeroCopyLineSplitter::TZeroCopyLineSplitter(int maxLen)
: WPos(0)
, RPos(0)
, Size(0)
, Cap(maxLen * 2)
, Data(Cap, 0)
, View(Data)
{ }
TLine TZeroCopyLineSplitter::Pop() {
auto end = View.substr(RPos, Size);
auto begin = View.substr(0, Size - end.size());
auto p1 = end.find('\n');
if (p1 == std::string_view::npos) {
auto p2 = begin.find('\n');
if (p2 == std::string_view::npos) {
return {};
}
RPos = p2 + 1;
Size -= end.size() + p2 + 1;
return TLine { end, begin.substr(0, p2 + 1) };
} else {
RPos += p1 + 1;
Size -= p1 + 1;
return TLine { end.substr(0, p1 + 1), {} };
}
}
std::span<char> TZeroCopyLineSplitter::Acquire(size_t size) {
size = std::min(size, Cap - Size);
if (size == 0) {
throw std::runtime_error("Overflow");
}
auto first = std::min(size, Cap - WPos);
if (first) {
return {&Data[WPos], first};
} else {
return {&Data[0], size};
}
}
void TZeroCopyLineSplitter::Commit(size_t size) {
WPos = (WPos + size) % Cap;
Size += size;
}
void TZeroCopyLineSplitter::Push(const char* p, size_t len) {
while (len != 0) {
auto buf = Acquire(len);
memcpy(buf.data(), p, buf.size());
Commit(buf.size());
len -= buf.size();
p += buf.size();
}
}
} // namespace NNet