Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Buffer.cpp
3185 views
1
#include <cstdarg>
2
#include <cstdlib>
3
#include <cstring>
4
5
#include "Common/Buffer.h"
6
#include "Common/File/FileUtil.h"
7
#include "Common/File/Path.h"
8
#include "Common/Log.h"
9
10
char *Buffer::Append(size_t length) {
11
if (length > 0) {
12
return data_.push_back_write(length);
13
} else {
14
return nullptr;
15
}
16
}
17
18
void Buffer::Append(std::string_view str) {
19
char *ptr = Append(str.size());
20
if (ptr) {
21
memcpy(ptr, str.data(), str.size());
22
}
23
}
24
25
void Buffer::Append(const Buffer &other) {
26
size_t len = other.size();
27
if (len > 0) {
28
// Append other to the current buffer.
29
other.data_.iterate_blocks([&](const char *data, size_t size) {
30
data_.push_back(data, size);
31
return true;
32
});
33
}
34
}
35
36
void Buffer::AppendValue(int value) {
37
char buf[16];
38
// This is slow.
39
snprintf(buf, sizeof(buf), "%i", value);
40
Append(buf);
41
}
42
43
void Buffer::Take(size_t length, std::string *dest) {
44
if (length > data_.size()) {
45
ERROR_LOG(Log::IO, "Truncating length in Buffer::Take()");
46
length = data_.size();
47
}
48
dest->resize(length);
49
if (length > 0) {
50
Take(length, &(*dest)[0]);
51
}
52
}
53
54
void Buffer::Take(size_t length, char *dest) {
55
size_t retval = data_.pop_front_bulk(dest, length);
56
_dbg_assert_(retval == length);
57
}
58
59
int Buffer::TakeLineCRLF(std::string *dest) {
60
int after_next_line = OffsetToAfterNextCRLF();
61
if (after_next_line < 0) {
62
return after_next_line;
63
} else {
64
_dbg_assert_(after_next_line >= 2);
65
if (after_next_line != 2)
66
Take((size_t)after_next_line - 2, dest);
67
Skip(2); // Skip the CRLF
68
return after_next_line - 2;
69
}
70
}
71
72
void Buffer::Skip(size_t length) {
73
if (length > data_.size()) {
74
ERROR_LOG(Log::IO, "Truncating length in Buffer::Skip()");
75
length = data_.size();
76
}
77
data_.skip(length);
78
}
79
80
int Buffer::SkipLineCRLF() {
81
int after_next_line = OffsetToAfterNextCRLF();
82
if (after_next_line < 0) {
83
return after_next_line;
84
} else {
85
Skip(after_next_line);
86
return after_next_line - 2;
87
}
88
}
89
90
// This relies on having buffered data!
91
int Buffer::OffsetToAfterNextCRLF() {
92
int offset = data_.next_crlf_offset();
93
if (offset >= 0) {
94
return offset + 2;
95
} else {
96
return -1;
97
}
98
}
99
100
void Buffer::Printf(const char *fmt, ...) {
101
char buffer[4096];
102
va_list vl;
103
va_start(vl, fmt);
104
int retval = vsnprintf(buffer, sizeof(buffer), fmt, vl);
105
if (retval >= (int)sizeof(buffer)) {
106
// Output was truncated. TODO: Do something.
107
ERROR_LOG(Log::IO, "Buffer::Printf truncated output");
108
}
109
if (retval < 0) {
110
ERROR_LOG(Log::IO, "Buffer::Printf failed, bad args?");
111
return;
112
}
113
va_end(vl);
114
char *ptr = Append(retval);
115
memcpy(ptr, buffer, retval);
116
}
117
118
bool Buffer::FlushToFile(const Path &filename, bool clear) {
119
FILE *f = File::OpenCFile(filename, "wb");
120
if (!f)
121
return false;
122
if (!data_.empty()) {
123
// Write the buffer to the file.
124
data_.iterate_blocks([=](const char *blockData, size_t blockSize) {
125
return fwrite(blockData, 1, blockSize, f) == blockSize;
126
});
127
if (clear) {
128
data_.clear();
129
}
130
}
131
fclose(f);
132
return true;
133
}
134
135
void Buffer::PeekAll(std::string *dest) {
136
dest->resize(data_.size());
137
data_.iterate_blocks(([=](const char *blockData, size_t blockSize) {
138
dest->append(blockData, blockSize);
139
return true;
140
}));
141
}
142
143