Return if we handle any error messages to avoid unnecessarily calling recv/send
[folly.git] / folly / io / Cursor.cpp
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <folly/io/Cursor.h>
18
19 #include <cstdio>
20
21 #include <folly/ScopeGuard.h>
22
23 namespace folly {
24 namespace io {
25
26 void Appender::printf(const char* fmt, ...) {
27   va_list ap;
28   va_start(ap, fmt);
29   vprintf(fmt, ap);
30   va_end(ap);
31 }
32
33 void Appender::vprintf(const char* fmt, va_list ap) {
34   // Make a copy of ap in case we need to retry.
35   // We use ap on the first attempt, so it always gets advanced
36   // passed the used arguments.  We'll only use apCopy if we need to retry.
37   va_list apCopy;
38   va_copy(apCopy, ap);
39   SCOPE_EXIT {
40     va_end(apCopy);
41   };
42
43   // First try writing into our available data space.
44   int ret = vsnprintf(reinterpret_cast<char*>(writableData()), length(),
45                       fmt, ap);
46   if (ret < 0) {
47     throw std::runtime_error("error formatting printf() data");
48   }
49   auto len = size_t(ret);
50   // vsnprintf() returns the number of characters that would be printed,
51   // not including the terminating nul.
52   if (len < length()) {
53     // All of the data was successfully written.
54     append(len);
55     return;
56   }
57
58   // There wasn't enough room for the data.
59   // Allocate more room, and then retry.
60   ensure(len + 1);
61   ret = vsnprintf(reinterpret_cast<char*>(writableData()), length(),
62                   fmt, apCopy);
63   if (ret < 0) {
64     throw std::runtime_error("error formatting printf() data");
65   }
66   len = size_t(ret);
67   if (len >= length()) {
68     // This shouldn't ever happen.
69     throw std::runtime_error("unexpectedly out of buffer space on second "
70                              "vsnprintf() attmept");
71   }
72   append(len);
73 }
74 } // namespace io
75 } // namespace folly