forked from rethinkdb/rethinkdb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprintf_buffer.cc
More file actions
99 lines (73 loc) · 2.7 KB
/
printf_buffer.cc
File metadata and controls
99 lines (73 loc) · 2.7 KB
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
// Copyright 2010-2013 RethinkDB, all rights reserved.
#include "containers/printf_buffer.hpp"
printf_buffer_t::printf_buffer_t() : length_(0), ptr_(data_) {
data_[0] = 0;
}
printf_buffer_t::printf_buffer_t(const char *format, ...) : length_(0), ptr_(data_) {
data_[0] = 0;
va_list ap;
va_start(ap, format);
vappendf(format, ap);
va_end(ap);
}
printf_buffer_t::printf_buffer_t(va_list ap, const char *format) : length_(0), ptr_(data_) {
data_[0] = 0;
vappendf(format, ap);
}
printf_buffer_t::~printf_buffer_t() {
if (ptr_ != data_) {
delete[] ptr_;
}
}
void printf_buffer_t::appendf(const char *format, ...) {
va_list ap;
va_start(ap, format);
vappendf(format, ap);
va_end(ap);
}
__attribute__((format (printf, 5, 0)))
inline void alloc_copy_and_format(const char *buf, int64_t length, int append_size, int64_t alloc_limit, const char *fmt, va_list ap, char **buf_out) {
char *new_ptr = new char[alloc_limit];
memcpy(new_ptr, buf, length);
DEBUG_VAR int size = vsnprintf(new_ptr + length, size_t(append_size) + 1, fmt, ap);
rassert(size == append_size);
*buf_out = new_ptr;
}
void printf_buffer_t::vappendf(const char *format, va_list ap) {
va_list aq;
va_copy(aq, ap);
if (ptr_ == data_) {
rassert(length_ < STATIC_DATA_SIZE);
// the snprintfs return the number of characters they _would_
// have written, not including the '\0'.
int size = vsnprintf(ptr_ + length_, STATIC_DATA_SIZE - length_, format, ap);
rassert(size >= 0, "vsnprintf failed, bad format string?");
if (size < STATIC_DATA_SIZE - length_) {
length_ += size;
} else {
char *new_ptr;
alloc_copy_and_format(ptr_, length_, size, round_up_to_power_of_two(length_ + size + 1), format, aq, &new_ptr);
// TODO: Have valgrind mark data_ memory undefined.
ptr_ = new_ptr;
length_ += size;
}
} else {
rassert(length_ >= STATIC_DATA_SIZE);
char tmp[1];
int size = vsnprintf(tmp, sizeof(tmp), format, ap);
rassert(size >= 0, "vsnprintf failed, bad format string?");
int64_t alloc_limit = round_up_to_power_of_two(length_ + 1);
if (length_ + size + 1 <= alloc_limit) {
DEBUG_VAR int size2 = vsnprintf(ptr_ + length_, size + 1, format, aq);
rassert(size == size2);
length_ += size;
} else {
char *new_ptr;
alloc_copy_and_format(ptr_, length_, size, round_up_to_power_of_two(length_ + size + 1), format, aq, &new_ptr);
delete[] ptr_;
ptr_ = new_ptr;
length_ += size;
}
}
va_end(aq);
}