Merge "Implement a simple logger for bsdiff"
diff --git a/Android.bp b/Android.bp
index 0910688..898f833 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,6 +43,7 @@
         "extents.cc",
         "extents_file.cc",
         "file.cc",
+        "logging.cc",
         "memory_file.cc",
         "patch_reader.cc",
         "sink_file.cc",
@@ -62,6 +63,7 @@
         "compressor_interface.cc",
         "diff_encoder.cc",
         "endsley_patch_writer.cc",
+        "logging.cc",
         "patch_writer.cc",
         "patch_writer_factory.cc",
         "split_patch_writer.cc",
diff --git a/Makefile b/Makefile
index 4906dd8..f6848f0 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,7 @@
     compressor_interface.cc \
     diff_encoder.cc \
     endsley_patch_writer.cc \
+    logging.cc \
     patch_writer.cc \
     patch_writer_factory.cc \
     split_patch_writer.cc \
@@ -55,6 +56,7 @@
     extents.cc \
     extents_file.cc \
     file.cc \
+    logging.cc \
     memory_file.cc \
     patch_reader.cc \
     sink_file.cc \
diff --git a/brotli_compressor.cc b/brotli_compressor.cc
index 6adc3e8..c6d39d2 100644
--- a/brotli_compressor.cc
+++ b/brotli_compressor.cc
@@ -6,8 +6,6 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace {
 // TODO(xunchang) set brotli compression parameters based on input options.
 const size_t kBufferSize = 1024 * 1024;
@@ -22,7 +20,7 @@
   brotli_encoder_state_ =
       BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);
   if (!brotli_encoder_state_) {
-    LOG(ERROR) << "Failed to initialize brotli decoder state" << endl;
+    LOG(ERROR) << "Failed to initialize brotli decoder state";
   } else {
     BrotliEncoderSetParameter(brotli_encoder_state_, BROTLI_PARAM_QUALITY,
                               kBrotliQuality);
@@ -50,7 +48,7 @@
             brotli_encoder_state_, BROTLI_OPERATION_PROCESS, &avail_in,
             &next_in, &avail_out, &next_out, nullptr)) {
       LOG(ERROR) << "BrotliCompressor failed to compress " << avail_in
-                 << " bytes of data." << endl;
+                 << " bytes of data.";
       return false;
     }
 
@@ -74,7 +72,7 @@
     if (!BrotliEncoderCompressStream(
             brotli_encoder_state_, BROTLI_OPERATION_FINISH, &avail_in, &next_in,
             &avail_out, &next_out, nullptr)) {
-      LOG(ERROR) << "BrotliCompressor failed to finish compression" << endl;
+      LOG(ERROR) << "BrotliCompressor failed to finish compression";
       return false;
     }
 
diff --git a/brotli_decompressor.cc b/brotli_decompressor.cc
index f173a75..20a1b14 100644
--- a/brotli_decompressor.cc
+++ b/brotli_decompressor.cc
@@ -6,15 +6,13 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace bsdiff {
 
 bool BrotliDecompressor::SetInputData(const uint8_t* input_data, size_t size) {
   brotli_decoder_state_ =
       BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
   if (brotli_decoder_state_ == nullptr) {
-    LOG(ERROR) << "Failed to initialize brotli decoder." << endl;
+    LOG(ERROR) << "Failed to initialize brotli decoder.";
     return false;
   }
   next_in_ = input_data;
@@ -36,12 +34,10 @@
     if (result == BROTLI_DECODER_RESULT_ERROR) {
       LOG(ERROR) << "Decompression failed with "
                  << BrotliDecoderErrorString(
-                        BrotliDecoderGetErrorCode(brotli_decoder_state_))
-                 << endl;
+                        BrotliDecoderGetErrorCode(brotli_decoder_state_));
       return false;
     } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
-      LOG(ERROR) << "Decompressor reached EOF while reading from input stream."
-                 << endl;
+      LOG(ERROR) << "Decompressor reached EOF while reading from input stream.";
       return false;
     }
   }
@@ -55,7 +51,7 @@
   // and return true.
   if (BrotliDecoderIsUsed(brotli_decoder_state_) &&
       !BrotliDecoderIsFinished(brotli_decoder_state_)) {
-    LOG(ERROR) << "Unfinished brotli decoder." << endl;
+    LOG(ERROR) << "Unfinished brotli decoder.";
     return false;
   }
 
diff --git a/bsdiff.gyp b/bsdiff.gyp
index 61d2430..72444ba 100644
--- a/bsdiff.gyp
+++ b/bsdiff.gyp
@@ -53,6 +53,7 @@
         'compressor_interface.cc',
         'diff_encoder.cc',
         'endsley_patch_writer.cc',
+        'logging.cc',
         'patch_writer.cc',
         'patch_writer_factory.cc',
         'split_patch_writer.cc',
@@ -101,6 +102,7 @@
         'extents.cc',
         'extents_file.cc',
         'file.cc',
+        'logging.cc',
         'memory_file.cc',
         'patch_reader.cc',
         'sink_file.cc',
diff --git a/bz2_compressor.cc b/bz2_compressor.cc
index fa3661c..50d4b2d 100644
--- a/bz2_compressor.cc
+++ b/bz2_compressor.cc
@@ -8,8 +8,6 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace {
 
 // The BZ2 compression level used. Smaller compression levels are nowadays
@@ -25,7 +23,7 @@
   int bz_err = BZ2_bzCompressInit(&bz_strm_, kCompressionLevel,
                                   0 /* verbosity */, 0 /* workFactor */);
   if (bz_err != BZ_OK) {
-    LOG(ERROR) << "Initializing bz_strm, bz_error=" << bz_err << endl;
+    LOG(ERROR) << "Initializing bz_strm, bz_error=" << bz_err;
   } else {
     bz_strm_initialized_ = true;
   }
@@ -36,7 +34,7 @@
     return;
   int bz_err = BZ2_bzCompressEnd(&bz_strm_);
   if (bz_err != BZ_OK) {
-    LOG(ERROR) << "Deleting the compressor stream, bz_error=" << bz_err << endl;
+    LOG(ERROR) << "Deleting the compressor stream, bz_error=" << bz_err;
   }
 }
 
@@ -54,7 +52,7 @@
     bz_strm_.avail_out = comp_buffer_.buffer_size();
     int bz_err = BZ2_bzCompress(&bz_strm_, BZ_RUN);
     if (bz_err != BZ_RUN_OK) {
-      LOG(ERROR) << "Compressing data, bz_error=" << bz_err << endl;
+      LOG(ERROR) << "Compressing data, bz_error=" << bz_err;
       return false;
     }
 
@@ -84,13 +82,13 @@
     }
   }
   if (bz_err != BZ_STREAM_END) {
-    LOG(ERROR) << "Finishing compressing data, bz_error=" << bz_err << endl;
+    LOG(ERROR) << "Finishing compressing data, bz_error=" << bz_err;
     return false;
   }
   bz_err = BZ2_bzCompressEnd(&bz_strm_);
   bz_strm_initialized_ = false;
   if (bz_err != BZ_OK) {
-    LOG(ERROR) << "Deleting the compressor stream, bz_error=" << bz_err << endl;
+    LOG(ERROR) << "Deleting the compressor stream, bz_error=" << bz_err;
     return false;
   }
   return true;
diff --git a/bz2_decompressor.cc b/bz2_decompressor.cc
index 99ecd71..2fc6512 100644
--- a/bz2_decompressor.cc
+++ b/bz2_decompressor.cc
@@ -11,14 +11,12 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace bsdiff {
 
 bool BZ2Decompressor::SetInputData(const uint8_t* input_data, size_t size) {
   // TODO(xunchang) update the avail_in for size > 2GB.
   if (size > std::numeric_limits<unsigned int>::max()) {
-    LOG(ERROR) << "Oversized input data" << size << endl;
+    LOG(ERROR) << "Oversized input data" << size;
     return false;
   }
 
@@ -29,7 +27,7 @@
   stream_.opaque = nullptr;
   int bz2err = BZ2_bzDecompressInit(&stream_, 0, 0);
   if (bz2err != BZ_OK) {
-    LOG(ERROR) << "Failed to bzinit control stream: " << bz2err << endl;
+    LOG(ERROR) << "Failed to bzinit control stream: " << bz2err;
     return false;
   }
   return true;
@@ -45,7 +43,7 @@
     int bz2err = BZ2_bzDecompress(&stream_);
     if (bz2err != BZ_OK && bz2err != BZ_STREAM_END) {
       LOG(ERROR) << "Failed to decompress " << output_size
-                 << " bytes of data, error: " << bz2err << endl;
+                 << " bytes of data, error: " << bz2err;
       return false;
     }
     bytes_to_output -= (output_size - stream_.avail_out);
@@ -56,7 +54,7 @@
 bool BZ2Decompressor::Close() {
   int bz2err = BZ2_bzDecompressEnd(&stream_);
   if (bz2err != BZ_OK) {
-    LOG(ERROR) << "BZ2_bzDecompressEnd returns with " << bz2err << endl;
+    LOG(ERROR) << "BZ2_bzDecompressEnd returns with " << bz2err;
     return false;
   }
   return true;
diff --git a/compressor_buffer.cc b/compressor_buffer.cc
index 5a62169..299b024 100644
--- a/compressor_buffer.cc
+++ b/compressor_buffer.cc
@@ -25,8 +25,7 @@
 void CompressorBuffer::AddDataToChunks(size_t data_size) {
   if (data_size > comp_buffer_.size()) {
     LOG(ERROR) << "data size: " << data_size
-               << " is larger than buffer size: " << comp_buffer_.size()
-               << std::endl;
+               << " is larger than buffer size: " << comp_buffer_.size();
     return;
   }
   comp_chunks_.emplace_back(comp_buffer_.data(),
diff --git a/compressor_interface.cc b/compressor_interface.cc
index 9ceb6bc..80c0921 100644
--- a/compressor_interface.cc
+++ b/compressor_interface.cc
@@ -18,7 +18,7 @@
       return std::unique_ptr<CompressorInterface>(new BrotliCompressor());
     default:
       LOG(ERROR) << "unsupported compressor type: "
-                 << static_cast<uint8_t>(type) << std::endl;
+                 << static_cast<uint8_t>(type);
       return nullptr;
   }
 }
diff --git a/decompressor_interface.cc b/decompressor_interface.cc
index f5fdb2d..31cbd47 100644
--- a/decompressor_interface.cc
+++ b/decompressor_interface.cc
@@ -18,7 +18,7 @@
       return std::unique_ptr<DecompressorInterface>(new BrotliDecompressor());
     default:
       LOG(ERROR) << "unsupported compressor type: "
-                 << static_cast<uint8_t>(type) << std::endl;
+                 << static_cast<uint8_t>(type);
       return nullptr;
   }
 }
diff --git a/diff_encoder.cc b/diff_encoder.cc
index baa5565..d687736 100644
--- a/diff_encoder.cc
+++ b/diff_encoder.cc
@@ -8,8 +8,6 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace {
 
 // The maximum positive number that we should encode. A number larger than this
@@ -27,19 +25,19 @@
 
 bool DiffEncoder::AddControlEntry(const ControlEntry& entry) {
   if (entry.diff_size > kMaxEncodedUint64Value) {
-    LOG(ERROR) << "Encoding value out of range " << entry.diff_size << endl;
+    LOG(ERROR) << "Encoding value out of range " << entry.diff_size;
     return false;
   }
 
   if (entry.extra_size > kMaxEncodedUint64Value) {
-    LOG(ERROR) << "Encoding value out of range " << entry.extra_size << endl;
+    LOG(ERROR) << "Encoding value out of range " << entry.extra_size;
     return false;
   }
 
   // entry.diff_size + entry.extra_size don't overflow in uint64_t since we
   // checked the kMaxEncodedUint64Value limit before.
   if (entry.diff_size + entry.extra_size > new_size_ - written_output_) {
-    LOG(ERROR) << "Wrote more output than the declared new_size" << endl;
+    LOG(ERROR) << "Wrote more output than the declared new_size";
     return false;
   }
 
@@ -48,7 +46,7 @@
        static_cast<uint64_t>(old_pos_) + entry.diff_size > old_size_)) {
     LOG(ERROR) << "The pointer in the old stream [" << old_pos_ << ", "
                << (static_cast<uint64_t>(old_pos_) + entry.diff_size)
-               << ") is out of bounds [0, " << old_size_ << ")" << endl;
+               << ") is out of bounds [0, " << old_size_ << ")";
     return false;
   }
 
@@ -62,15 +60,14 @@
     diff[i] = new_buf_[written_output_ + i] - old_buf_[old_pos_ + i];
   }
   if (!patch_->WriteDiffStream(diff.data(), diff.size())) {
-    LOG(ERROR) << "Writing " << diff.size() << " bytes to the diff stream"
-               << endl;
+    LOG(ERROR) << "Writing " << diff.size() << " bytes to the diff stream";
     return false;
   }
 
   if (!patch_->WriteExtraStream(new_buf_ + written_output_ + entry.diff_size,
                                 entry.extra_size)) {
-    LOG(ERROR) << "Writing " << entry.extra_size << " bytes to the extra stream"
-               << endl;
+    LOG(ERROR) << "Writing " << entry.extra_size
+               << " bytes to the extra stream";
     return false;
   }
 
@@ -82,7 +79,7 @@
 
 bool DiffEncoder::Close() {
   if (written_output_ != new_size_) {
-    LOG(ERROR) << "Close() called but not all the output was written" << endl;
+    LOG(ERROR) << "Close() called but not all the output was written";
     return false;
   }
   return patch_->Close();
diff --git a/endsley_patch_writer.cc b/endsley_patch_writer.cc
index 4e4a3f1..cb23f46 100644
--- a/endsley_patch_writer.cc
+++ b/endsley_patch_writer.cc
@@ -10,8 +10,6 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace {
 
 constexpr uint8_t kEndsleyMagicHeader[] = "ENDSLEY/BSDIFF43";
@@ -110,13 +108,12 @@
   Flush();
 
   if (pending_diff_ || pending_extra_ || !control_.empty()) {
-    LOG(ERROR) << "Insufficient data sent to diff/extra streams" << endl;
+    LOG(ERROR) << "Insufficient data sent to diff/extra streams";
     return false;
   }
 
   if (!diff_data_.empty() || !extra_data_.empty()) {
-    LOG(ERROR) << "Pending data to diff/extra not flushed out on Close()"
-               << endl;
+    LOG(ERROR) << "Pending data to diff/extra not flushed out on Close()";
     return false;
   }
   return true;
diff --git a/logging.cc b/logging.cc
new file mode 100644
index 0000000..eb1a952
--- /dev/null
+++ b/logging.cc
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "bsdiff/logging.h"
+
+#include <ctime>
+
+LogMessage::LogMessage(const char* file,
+                       unsigned int line,
+                       const char* severity)
+    : LogMessage(file, line, severity, -1) {}
+
+
+LogMessage::LogMessage(const char* file,
+                       unsigned int line,
+                       const char* severity,
+                       int error)
+    : error_(error) {
+  std::time_t t = std::time(nullptr);
+  char timestamp[32];
+  strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", std::localtime(&t));
+
+  stream_ << severity << " " << timestamp << " " << file << ":" << line << ": ";
+}
+
+LogMessage::~LogMessage() {
+  if (error_ != -1) {
+    stream_ << ": " << strerror(error_);
+  }
+  std::cerr << stream_.str() << std::endl;
+}
diff --git a/logging.h b/logging.h
index 5e09d55..0a3bc13 100644
--- a/logging.h
+++ b/logging.h
@@ -5,11 +5,36 @@
 #ifndef _BSDIFF_LOGGING_H_
 #define _BSDIFF_LOGGING_H_
 
+#include <string.h>
+
 #include <iostream>
+#include <sstream>
 
 // Simple error logging macro to avoid dependencies in other base libraries.
-// Unfortunately, you must pass std::endl as the last element on the stream to
-// produce the new line.
-#define LOG(X) (std::cerr << #X << " " << __FILE__ << ":" << __LINE__ << ": ")
+#define LOG(severity) LogMessage(__FILE__, __LINE__, #severity).stream()
+
+// A variant of LOG that also logs the current errno value.
+#define PLOG(severity) LogMessage(__FILE__, __LINE__, #severity, errno).stream()
+
+// A temporarily scoped object used by LOG & PLOG.
+class LogMessage {
+ public:
+  LogMessage(const char* file, unsigned int line, const char* severity);
+
+  LogMessage(const char* file,
+             unsigned int line,
+             const char* severity,
+             int error);
+
+  ~LogMessage();
+
+  // Returns the stream associated with the message, the LogMessage performs
+  // output when it goes out of scope.
+  std::ostream& stream() { return stream_; }
+
+ private:
+  std::ostringstream stream_;
+  int error_;  // The saved errno value.
+};
 
 #endif  // _BSDIFF_LOGGING_H_
diff --git a/patch_reader.cc b/patch_reader.cc
index 80a61f8..9f46857 100644
--- a/patch_reader.cc
+++ b/patch_reader.cc
@@ -15,8 +15,6 @@
 #include "bsdiff/logging.h"
 #include "bsdiff/utils.h"
 
-using std::endl;
-
 namespace bsdiff {
 
 bool BsdiffPatchReader::Init(const uint8_t* patch_data, size_t patch_size) {
@@ -33,7 +31,7 @@
   // extra block; seek forwards in oldfile by z bytes".
 
   if (patch_size < 32) {
-    LOG(ERROR) << "Too small to be a bspatch." << endl;
+    LOG(ERROR) << "Too small to be a bspatch.";
     return false;
   }
   // Check for appropriate magic.
@@ -59,12 +57,12 @@
           break;
         default:
           LOG(ERROR) << "Unsupported compression type: "
-                     << static_cast<int>(type) << endl;
+                     << static_cast<int>(type);
           return false;
       }
     }
   } else {
-    LOG(ERROR) << "Not a bsdiff patch." << endl;
+    LOG(ERROR) << "Not a bsdiff patch.";
     return false;
   }
 
@@ -77,7 +75,7 @@
     LOG(ERROR) << "Corrupt patch.  ctrl_len: " << ctrl_len
                << ", data_len: " << diff_len
                << ", new_file_size: " << signed_newsize
-               << ", patch_size: " << patch_size << endl;
+               << ", patch_size: " << patch_size;
     return false;
   }
   new_file_size_ = signed_newsize;
@@ -86,21 +84,21 @@
   diff_stream_ = CreateDecompressor(compression_type[1]);
   extra_stream_ = CreateDecompressor(compression_type[2]);
   if (!(ctrl_stream_ && diff_stream_ && extra_stream_)) {
-    LOG(ERROR) << "uninitialized decompressor stream" << endl;
+    LOG(ERROR) << "uninitialized decompressor stream";
     return false;
   }
 
   size_t offset = 32;
   if (!ctrl_stream_->SetInputData(const_cast<uint8_t*>(patch_data) + offset,
                                   ctrl_len)) {
-    LOG(ERROR) << "Failed to init ctrl stream, ctrl_len: " << ctrl_len << endl;
+    LOG(ERROR) << "Failed to init ctrl stream, ctrl_len: " << ctrl_len;
     return false;
   }
 
   offset += ctrl_len;
   if (!diff_stream_->SetInputData(const_cast<uint8_t*>(patch_data) + offset,
                                   diff_len)) {
-    LOG(ERROR) << "Failed to init ctrl stream, diff_len: " << diff_len << endl;
+    LOG(ERROR) << "Failed to init ctrl stream, diff_len: " << diff_len;
     return false;
   }
 
@@ -108,7 +106,7 @@
   if (!extra_stream_->SetInputData(const_cast<uint8_t*>(patch_data) + offset,
                                    patch_size - offset)) {
     LOG(ERROR) << "Failed to init extra stream, extra_offset: " << offset
-               << ", patch_size: " << patch_size << endl;
+               << ", patch_size: " << patch_size;
     return false;
   }
   return true;
@@ -130,7 +128,7 @@
   // Sanity check.
   if (diff_size < 0 || extra_size < 0) {
     LOG(ERROR) << "Corrupt patch; diff_size: " << diff_size
-               << ", extra_size: " << extra_size << endl;
+               << ", extra_size: " << extra_size;
     return false;
   }
 
@@ -154,17 +152,17 @@
 
 bool BsdiffPatchReader::Finish() {
   if (!ctrl_stream_->Close()) {
-    LOG(ERROR) << "Failed to close the control stream" << endl;
+    LOG(ERROR) << "Failed to close the control stream";
     return false;
   }
 
   if (!diff_stream_->Close()) {
-    LOG(ERROR) << "Failed to close the diff stream" << endl;
+    LOG(ERROR) << "Failed to close the diff stream";
     return false;
   }
 
   if (!extra_stream_->Close()) {
-    LOG(ERROR) << "Failed to close the extra stream" << endl;
+    LOG(ERROR) << "Failed to close the extra stream";
     return false;
   }
   return true;
diff --git a/patch_writer.cc b/patch_writer.cc
index f4f7930..9c906c6 100644
--- a/patch_writer.cc
+++ b/patch_writer.cc
@@ -12,8 +12,6 @@
 #include "bsdiff/control_entry.h"
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace {
 
 void EncodeInt64(int64_t x, uint8_t* buf) {
@@ -46,13 +44,13 @@
 
 bool BsdiffPatchWriter::Init(size_t /* new_size */) {
   if (!(ctrl_stream_ && diff_stream_ && extra_stream_)) {
-    LOG(ERROR) << "uninitialized compressor stream" << endl;
+    LOG(ERROR) << "uninitialized compressor stream";
     return false;
   }
 
   fp_ = fopen(patch_filename_.c_str(), "w");
   if (!fp_) {
-    LOG(ERROR) << "Opening " << patch_filename_ << endl;
+    LOG(ERROR) << "Opening " << patch_filename_;
     return false;
   }
   return true;
@@ -80,13 +78,13 @@
 
 bool BsdiffPatchWriter::Close() {
   if (!fp_) {
-    LOG(ERROR) << "File not open." << endl;
+    LOG(ERROR) << "File not open.";
     return false;
   }
 
   if (!ctrl_stream_->Finish() || !diff_stream_->Finish() ||
       !extra_stream_->Finish()) {
-    LOG(ERROR) << "Finalizing compressed streams." << endl;
+    LOG(ERROR) << "Finalizing compressed streams.";
     return false;
   }
 
@@ -98,20 +96,20 @@
     return false;
 
   if (fwrite(ctrl_data.data(), 1, ctrl_data.size(), fp_) != ctrl_data.size()) {
-    LOG(ERROR) << "Writing ctrl_data." << endl;
+    LOG(ERROR) << "Writing ctrl_data.";
     return false;
   }
   if (fwrite(diff_data.data(), 1, diff_data.size(), fp_) != diff_data.size()) {
-    LOG(ERROR) << "Writing diff_data." << endl;
+    LOG(ERROR) << "Writing diff_data.";
     return false;
   }
   if (fwrite(extra_data.data(), 1, extra_data.size(), fp_) !=
       extra_data.size()) {
-    LOG(ERROR) << "Writing extra_data." << endl;
+    LOG(ERROR) << "Writing extra_data.";
     return false;
   }
   if (fclose(fp_) != 0) {
-    LOG(ERROR) << "Closing the patch file." << endl;
+    LOG(ERROR) << "Closing the patch file.";
     return false;
   }
   fp_ = nullptr;
@@ -146,7 +144,7 @@
     header[6] = static_cast<uint8_t>(diff_stream_->Type());
     header[7] = static_cast<uint8_t>(extra_stream_->Type());
   } else {
-    LOG(ERROR) << "Unsupported bsdiff format." << endl;
+    LOG(ERROR) << "Unsupported bsdiff format.";
     return false;
   }
 
@@ -154,7 +152,7 @@
   EncodeInt64(diff_size, header + 16);
   EncodeInt64(written_output_, header + 24);
   if (fwrite(header, sizeof(header), 1, fp_) != 1) {
-    LOG(ERROR) << "writing to the patch file" << endl;
+    LOG(ERROR) << "writing to the patch file";
     return false;
   }
   return true;
diff --git a/split_patch_writer.cc b/split_patch_writer.cc
index 3e0d6e7..f863484 100644
--- a/split_patch_writer.cc
+++ b/split_patch_writer.cc
@@ -8,8 +8,6 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace bsdiff {
 
 bool SplitPatchWriter::Init(size_t new_size) {
@@ -24,7 +22,7 @@
   if (expected_patches != patches_.size()) {
     LOG(ERROR) << "Expected " << expected_patches << " for a new file of size "
                << new_size_ << " split in chunks of " << new_chunk_size_
-               << " but got " << patches_.size() << " instead." << endl;
+               << " but got " << patches_.size() << " instead.";
     return false;
   }
 
@@ -70,12 +68,12 @@
     if (remaining.diff_size + remaining.extra_size > 0) {
       current_patch_++;
       if (current_patch_ >= patches_.size()) {
-        LOG(ERROR) << "Writing past the last patch" << endl;
+        LOG(ERROR) << "Writing past the last patch";
         return false;
       }
       if (!patches_[current_patch_]->Init(std::min(
               new_size_ - current_patch_ * new_chunk_size_, new_chunk_size_))) {
-        LOG(ERROR) << "Failed to initialize patch " << current_patch_ << endl;
+        LOG(ERROR) << "Failed to initialize patch " << current_patch_;
         return false;
       }
       if (!remaining.diff_size) {
@@ -112,7 +110,7 @@
     missing_bytes += size;
   if (missing_bytes > 0) {
     LOG(ERROR) << "Close() called but there are " << missing_bytes
-               << " bytes missing from Write*Stream() calls" << endl;
+               << " bytes missing from Write*Stream() calls";
     return false;
   }
 
@@ -120,9 +118,8 @@
   // patches in the list those have not been initialized/closed, which is a
   // programming error.
   if (current_patch_ + 1 != patches_.size()) {
-    LOG(ERROR) << "Close() called but no bytes habe been written to the last "
-                  "patch"
-               << endl;
+    LOG(ERROR)
+        << "Close() called but no bytes habe been written to the last patch";
     return false;
   }
 
@@ -141,7 +138,7 @@
     return true;
 
   if (current_patch_ >= patches_.size()) {
-    LOG(ERROR) << "Writing past the last patch" << endl;
+    LOG(ERROR) << "Writing past the last patch";
     return false;
   }
   old_pos_ += entry.diff_size + entry.offset_increment;
diff --git a/suffix_array_index.cc b/suffix_array_index.cc
index 27d6cb3..b02655c 100644
--- a/suffix_array_index.cc
+++ b/suffix_array_index.cc
@@ -12,8 +12,6 @@
 
 #include "bsdiff/logging.h"
 
-using std::endl;
-
 namespace {
 
 // libdivsufsort C++ overloaded functions used to allow calling the right
@@ -77,12 +75,12 @@
 bool SuffixArrayIndex<SAIDX>::Init(const uint8_t* text, size_t n) {
   if (!sa_.empty()) {
     // Already initialized.
-    LOG(ERROR) << "SuffixArray already initialized" << endl;
+    LOG(ERROR) << "SuffixArray already initialized";
     return false;
   }
   if (static_cast<uint64_t>(n) >
       static_cast<uint64_t>(std::numeric_limits<SAIDX>::max())) {
-    LOG(ERROR) << "Input too big (" << n << ") for this implementation" << endl;
+    LOG(ERROR) << "Input too big (" << n << ") for this implementation";
     return false;
   }
   text_ = text;
@@ -90,7 +88,7 @@
   sa_.resize(n + 1);
 
   if (n > 0 && CallDivSufSort(text_, sa_.data(), n) != 0) {
-    LOG(ERROR) << "divsufsrot() failed" << endl;
+    LOG(ERROR) << "divsufsrot() failed";
     return false;
   }