1 | // Protocol Buffers - Google's data interchange format |
2 | // Copyright 2008 Google Inc. All rights reserved. |
3 | // https://developers.google.com/protocol-buffers/ |
4 | // |
5 | // Redistribution and use in source and binary forms, with or without |
6 | // modification, are permitted provided that the following conditions are |
7 | // met: |
8 | // |
9 | // * Redistributions of source code must retain the above copyright |
10 | // notice, this list of conditions and the following disclaimer. |
11 | // * Redistributions in binary form must reproduce the above |
12 | // copyright notice, this list of conditions and the following disclaimer |
13 | // in the documentation and/or other materials provided with the |
14 | // distribution. |
15 | // * Neither the name of Google Inc. nor the names of its |
16 | // contributors may be used to endorse or promote products derived from |
17 | // this software without specific prior written permission. |
18 | // |
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | |
31 | // Author: kenton@google.com (Kenton Varda) |
32 | |
33 | #include <google/protobuf/stubs/common.h> |
34 | |
35 | #include <atomic> |
36 | #include <errno.h> |
37 | #include <sstream> |
38 | #include <stdio.h> |
39 | #include <vector> |
40 | |
41 | #ifdef _WIN32 |
42 | #ifndef WIN32_LEAN_AND_MEAN |
43 | #define WIN32_LEAN_AND_MEAN // We only need minimal includes |
44 | #endif |
45 | #include <windows.h> |
46 | #define snprintf _snprintf // see comment in strutil.cc |
47 | #endif |
48 | #if defined(__ANDROID__) |
49 | #include <android/log.h> |
50 | #endif |
51 | |
52 | #include <google/protobuf/stubs/callback.h> |
53 | #include <google/protobuf/stubs/logging.h> |
54 | #include <google/protobuf/stubs/once.h> |
55 | #include <google/protobuf/stubs/status.h> |
56 | #include <google/protobuf/stubs/stringpiece.h> |
57 | #include <google/protobuf/stubs/strutil.h> |
58 | #include <google/protobuf/stubs/int128.h> |
59 | |
60 | #include <google/protobuf/port_def.inc> |
61 | |
62 | namespace google { |
63 | namespace protobuf { |
64 | |
65 | namespace internal { |
66 | |
67 | void VerifyVersion(int , |
68 | int minLibraryVersion, |
69 | const char* filename) { |
70 | if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) { |
71 | // Library is too old for headers. |
72 | GOOGLE_LOG(FATAL) |
73 | << "This program requires version " << VersionString(version: minLibraryVersion) |
74 | << " of the Protocol Buffer runtime library, but the installed version " |
75 | "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update " |
76 | "your library. If you compiled the program yourself, make sure that " |
77 | "your headers are from the same version of Protocol Buffers as your " |
78 | "link-time library. (Version verification failed in \"" |
79 | << filename << "\".)" ; |
80 | } |
81 | if (headerVersion < kMinHeaderVersionForLibrary) { |
82 | // Headers are too old for library. |
83 | GOOGLE_LOG(FATAL) |
84 | << "This program was compiled against version " |
85 | << VersionString(version: headerVersion) << " of the Protocol Buffer runtime " |
86 | "library, which is not compatible with the installed version (" |
87 | << VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program " |
88 | "author for an update. If you compiled the program yourself, make " |
89 | "sure that your headers are from the same version of Protocol Buffers " |
90 | "as your link-time library. (Version verification failed in \"" |
91 | << filename << "\".)" ; |
92 | } |
93 | } |
94 | |
95 | std::string VersionString(int version) { |
96 | int major = version / 1000000; |
97 | int minor = (version / 1000) % 1000; |
98 | int micro = version % 1000; |
99 | |
100 | // 128 bytes should always be enough, but we use snprintf() anyway to be |
101 | // safe. |
102 | char buffer[128]; |
103 | snprintf(s: buffer, maxlen: sizeof(buffer), format: "%d.%d.%d" , major, minor, micro); |
104 | |
105 | // Guard against broken MSVC snprintf(). |
106 | buffer[sizeof(buffer)-1] = '\0'; |
107 | |
108 | return buffer; |
109 | } |
110 | |
111 | } // namespace internal |
112 | |
113 | // =================================================================== |
114 | // emulates google3/base/logging.cc |
115 | |
116 | // If the minimum logging level is not set, we default to logging messages for |
117 | // all levels. |
118 | #ifndef GOOGLE_PROTOBUF_MIN_LOG_LEVEL |
119 | #define GOOGLE_PROTOBUF_MIN_LOG_LEVEL LOGLEVEL_INFO |
120 | #endif |
121 | |
122 | namespace internal { |
123 | |
124 | #if defined(__ANDROID__) |
125 | inline void DefaultLogHandler(LogLevel level, const char* filename, int line, |
126 | const std::string& message) { |
127 | if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { |
128 | return; |
129 | } |
130 | static const char* level_names[] = {"INFO" , "WARNING" , "ERROR" , "FATAL" }; |
131 | |
132 | static const int android_log_levels[] = { |
133 | ANDROID_LOG_INFO, // LOG(INFO), |
134 | ANDROID_LOG_WARN, // LOG(WARNING) |
135 | ANDROID_LOG_ERROR, // LOG(ERROR) |
136 | ANDROID_LOG_FATAL, // LOG(FATAL) |
137 | }; |
138 | |
139 | // Bound the logging level. |
140 | const int android_log_level = android_log_levels[level]; |
141 | ::std::ostringstream ostr; |
142 | ostr << "[libprotobuf " << level_names[level] << " " << filename << ":" |
143 | << line << "] " << message.c_str(); |
144 | |
145 | // Output the log string the Android log at the appropriate level. |
146 | __android_log_write(android_log_level, "libprotobuf-native" , |
147 | ostr.str().c_str()); |
148 | // Also output to std::cerr. |
149 | fprintf(stderr, "%s" , ostr.str().c_str()); |
150 | fflush(stderr); |
151 | |
152 | // Indicate termination if needed. |
153 | if (android_log_level == ANDROID_LOG_FATAL) { |
154 | __android_log_write(ANDROID_LOG_FATAL, "libprotobuf-native" , |
155 | "terminating.\n" ); |
156 | } |
157 | } |
158 | |
159 | #else |
160 | void DefaultLogHandler(LogLevel level, const char* filename, int line, |
161 | const std::string& message) { |
162 | if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { |
163 | return; |
164 | } |
165 | static const char* level_names[] = { "INFO" , "WARNING" , "ERROR" , "FATAL" }; |
166 | |
167 | // We use fprintf() instead of cerr because we want this to work at static |
168 | // initialization time. |
169 | fprintf(stderr, format: "[libprotobuf %s %s:%d] %s\n" , |
170 | level_names[level], filename, line, message.c_str()); |
171 | fflush(stderr); // Needed on MSVC. |
172 | } |
173 | #endif |
174 | |
175 | void NullLogHandler(LogLevel /* level */, const char* /* filename */, |
176 | int /* line */, const std::string& /* message */) { |
177 | // Nothing. |
178 | } |
179 | |
180 | static LogHandler* log_handler_ = &DefaultLogHandler; |
181 | static std::atomic<int> log_silencer_count_ = ATOMIC_VAR_INIT(0); |
182 | |
183 | LogMessage& LogMessage::operator<<(const std::string& value) { |
184 | message_ += value; |
185 | return *this; |
186 | } |
187 | |
188 | LogMessage& LogMessage::operator<<(const char* value) { |
189 | message_ += value; |
190 | return *this; |
191 | } |
192 | |
193 | LogMessage& LogMessage::operator<<(const StringPiece& value) { |
194 | message_ += value.ToString(); |
195 | return *this; |
196 | } |
197 | |
198 | LogMessage& LogMessage::operator<<(const util::Status& status) { |
199 | message_ += status.ToString(); |
200 | return *this; |
201 | } |
202 | |
203 | LogMessage& LogMessage::operator<<(const uint128& value) { |
204 | std::ostringstream str; |
205 | str << value; |
206 | message_ += str.str(); |
207 | return *this; |
208 | } |
209 | |
210 | LogMessage& LogMessage::operator<<(char value) { |
211 | return *this << StringPiece(&value, 1); |
212 | } |
213 | |
214 | LogMessage& LogMessage::operator<<(void* value) { |
215 | StrAppend(dest: &message_, a: strings::Hex(reinterpret_cast<uintptr_t>(value))); |
216 | return *this; |
217 | } |
218 | |
219 | #undef DECLARE_STREAM_OPERATOR |
220 | #define DECLARE_STREAM_OPERATOR(TYPE) \ |
221 | LogMessage& LogMessage::operator<<(TYPE value) { \ |
222 | StrAppend(&message_, value); \ |
223 | return *this; \ |
224 | } |
225 | |
226 | DECLARE_STREAM_OPERATOR(int) |
227 | DECLARE_STREAM_OPERATOR(unsigned int) |
228 | DECLARE_STREAM_OPERATOR(long) // NOLINT(runtime/int) |
229 | DECLARE_STREAM_OPERATOR(unsigned long) // NOLINT(runtime/int) |
230 | DECLARE_STREAM_OPERATOR(double) |
231 | DECLARE_STREAM_OPERATOR(long long) // NOLINT(runtime/int) |
232 | DECLARE_STREAM_OPERATOR(unsigned long long) // NOLINT(runtime/int) |
233 | #undef DECLARE_STREAM_OPERATOR |
234 | |
235 | LogMessage::LogMessage(LogLevel level, const char* filename, int line) |
236 | : level_(level), filename_(filename), line_(line) {} |
237 | LogMessage::~LogMessage() {} |
238 | |
239 | void LogMessage::Finish() { |
240 | bool suppress = false; |
241 | |
242 | if (level_ != LOGLEVEL_FATAL) { |
243 | suppress = log_silencer_count_ > 0; |
244 | } |
245 | |
246 | if (!suppress) { |
247 | log_handler_(level_, filename_, line_, message_); |
248 | } |
249 | |
250 | if (level_ == LOGLEVEL_FATAL) { |
251 | #if PROTOBUF_USE_EXCEPTIONS |
252 | throw FatalException(filename_, line_, message_); |
253 | #else |
254 | abort(); |
255 | #endif |
256 | } |
257 | } |
258 | |
259 | void LogFinisher::operator=(LogMessage& other) { |
260 | other.Finish(); |
261 | } |
262 | |
263 | } // namespace internal |
264 | |
265 | LogHandler* SetLogHandler(LogHandler* new_func) { |
266 | LogHandler* old = internal::log_handler_; |
267 | if (old == &internal::NullLogHandler) { |
268 | old = nullptr; |
269 | } |
270 | if (new_func == nullptr) { |
271 | internal::log_handler_ = &internal::NullLogHandler; |
272 | } else { |
273 | internal::log_handler_ = new_func; |
274 | } |
275 | return old; |
276 | } |
277 | |
278 | LogSilencer::LogSilencer() { |
279 | ++internal::log_silencer_count_; |
280 | }; |
281 | |
282 | LogSilencer::~LogSilencer() { |
283 | --internal::log_silencer_count_; |
284 | }; |
285 | |
286 | // =================================================================== |
287 | // emulates google3/base/callback.cc |
288 | |
289 | Closure::~Closure() {} |
290 | |
291 | namespace internal { FunctionClosure0::~FunctionClosure0() {} } |
292 | |
293 | void DoNothing() {} |
294 | |
295 | // =================================================================== |
296 | // emulates google3/util/endian/endian.h |
297 | // |
298 | // TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in |
299 | // google/protobuf/io/coded_stream.h and therefore can not be used here. |
300 | // Maybe move that macro definition here in the future. |
301 | uint32_t ghtonl(uint32_t x) { |
302 | union { |
303 | uint32_t result; |
304 | uint8_t result_array[4]; |
305 | }; |
306 | result_array[0] = static_cast<uint8_t>(x >> 24); |
307 | result_array[1] = static_cast<uint8_t>((x >> 16) & 0xFF); |
308 | result_array[2] = static_cast<uint8_t>((x >> 8) & 0xFF); |
309 | result_array[3] = static_cast<uint8_t>(x & 0xFF); |
310 | return result; |
311 | } |
312 | |
313 | #if PROTOBUF_USE_EXCEPTIONS |
314 | FatalException::~FatalException() throw() {} |
315 | |
316 | const char* FatalException::what() const throw() { |
317 | return message_.c_str(); |
318 | } |
319 | #endif |
320 | |
321 | } // namespace protobuf |
322 | } // namespace google |
323 | |
324 | #include <google/protobuf/port_undef.inc> |
325 | |