tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

output.cc (2109B)


      1 // Copyright 2017 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "absl/strings/internal/str_format/output.h"
     16 
     17 #include <errno.h>
     18 #include <cstring>
     19 
     20 namespace absl {
     21 ABSL_NAMESPACE_BEGIN
     22 namespace str_format_internal {
     23 
     24 namespace {
     25 struct ClearErrnoGuard {
     26  ClearErrnoGuard() : old_value(errno) { errno = 0; }
     27  ~ClearErrnoGuard() {
     28    if (!errno) errno = old_value;
     29  }
     30  int old_value;
     31 };
     32 }  // namespace
     33 
     34 void BufferRawSink::Write(string_view v) {
     35  size_t to_write = std::min(v.size(), size_);
     36  if (to_write > 0) {
     37    std::memcpy(buffer_, v.data(), to_write);
     38    buffer_ += to_write;
     39    size_ -= to_write;
     40  }
     41  total_written_ += v.size();
     42 }
     43 
     44 void FILERawSink::Write(string_view v) {
     45  while (!v.empty() && !error_) {
     46    // Reset errno to zero in case the libc implementation doesn't set errno
     47    // when a failure occurs.
     48    ClearErrnoGuard guard;
     49 
     50    if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) {
     51      // Some progress was made.
     52      count_ += result;
     53      v.remove_prefix(result);
     54    } else {
     55      if (errno == EINTR) {
     56        continue;
     57      } else if (errno) {
     58        error_ = errno;
     59      } else if (std::ferror(output_)) {
     60        // Non-POSIX compliant libc implementations may not set errno, so we
     61        // have check the streams error indicator.
     62        error_ = EBADF;
     63      } else {
     64        // We're likely on a non-POSIX system that encountered EINTR but had no
     65        // way of reporting it.
     66        continue;
     67      }
     68    }
     69  }
     70 }
     71 
     72 }  // namespace str_format_internal
     73 ABSL_NAMESPACE_END
     74 }  // namespace absl