CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Buffer.cpp
Views: 1401
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
Buffer::Buffer() { }
11
Buffer::~Buffer() { }
12
13
char *Buffer::Append(size_t length) {
14
if (length > 0) {
15
size_t old_size = data_.size();
16
data_.resize(old_size + length);
17
return &data_[0] + old_size;
18
} else {
19
return nullptr;
20
}
21
}
22
23
void Buffer::Append(const std::string &str) {
24
char *ptr = Append(str.size());
25
if (ptr) {
26
memcpy(ptr, str.data(), str.size());
27
}
28
}
29
30
void Buffer::Append(const char *str) {
31
size_t len = strlen(str);
32
char *dest = Append(len);
33
memcpy(dest, str, len);
34
}
35
36
void Buffer::Append(const Buffer &other) {
37
size_t len = other.size();
38
if (len > 0) {
39
char *dest = Append(len);
40
memcpy(dest, &other.data_[0], len);
41
}
42
}
43
44
void Buffer::AppendValue(int value) {
45
char buf[16];
46
// This is slow.
47
snprintf(buf, sizeof(buf), "%i", value);
48
Append(buf);
49
}
50
51
void Buffer::Take(size_t length, std::string *dest) {
52
if (length > data_.size()) {
53
ERROR_LOG(Log::IO, "Truncating length in Buffer::Take()");
54
length = data_.size();
55
}
56
dest->resize(length);
57
if (length > 0) {
58
Take(length, &(*dest)[0]);
59
}
60
}
61
62
void Buffer::Take(size_t length, char *dest) {
63
memcpy(dest, &data_[0], length);
64
data_.erase(data_.begin(), data_.begin() + length);
65
}
66
67
int Buffer::TakeLineCRLF(std::string *dest) {
68
int after_next_line = OffsetToAfterNextCRLF();
69
if (after_next_line < 0) {
70
return after_next_line;
71
} else {
72
_dbg_assert_(after_next_line >= 2);
73
if (after_next_line != 2)
74
Take((size_t)after_next_line - 2, dest);
75
Skip(2); // Skip the CRLF
76
return after_next_line - 2;
77
}
78
}
79
80
void Buffer::Skip(size_t length) {
81
if (length > data_.size()) {
82
ERROR_LOG(Log::IO, "Truncating length in Buffer::Skip()");
83
length = data_.size();
84
}
85
data_.erase(data_.begin(), data_.begin() + length);
86
}
87
88
int Buffer::SkipLineCRLF() {
89
int after_next_line = OffsetToAfterNextCRLF();
90
if (after_next_line < 0) {
91
return after_next_line;
92
} else {
93
Skip(after_next_line);
94
return after_next_line - 2;
95
}
96
}
97
98
int Buffer::OffsetToAfterNextCRLF() {
99
for (int i = 0; i < (int)data_.size() - 1; i++) {
100
if (data_[i] == '\r' && data_[i + 1] == '\n') {
101
return i + 2;
102
}
103
}
104
return -1;
105
}
106
107
void Buffer::Printf(const char *fmt, ...) {
108
char buffer[2048];
109
va_list vl;
110
va_start(vl, fmt);
111
size_t retval = vsnprintf(buffer, sizeof(buffer), fmt, vl);
112
if ((int)retval >= (int)sizeof(buffer)) {
113
// Output was truncated. TODO: Do something.
114
ERROR_LOG(Log::IO, "Buffer::Printf truncated output");
115
}
116
if ((int)retval < 0) {
117
ERROR_LOG(Log::IO, "Buffer::Printf failed");
118
}
119
va_end(vl);
120
char *ptr = Append(retval);
121
memcpy(ptr, buffer, retval);
122
}
123
124
bool Buffer::FlushToFile(const Path &filename) {
125
FILE *f = File::OpenCFile(filename, "wb");
126
if (!f)
127
return false;
128
if (data_.size()) {
129
fwrite(&data_[0], 1, data_.size(), f);
130
}
131
fclose(f);
132
return true;
133
}
134
135
void Buffer::PeekAll(std::string *dest) {
136
dest->resize(data_.size());
137
memcpy(&(*dest)[0], &data_[0], data_.size());
138
}
139
140