Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/moses-smt/mosesdecoder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'util/fake_ofstream.hh')
-rw-r--r--util/fake_ofstream.hh118
1 files changed, 71 insertions, 47 deletions
diff --git a/util/fake_ofstream.hh b/util/fake_ofstream.hh
index 8299ba9ac..d35bf0d83 100644
--- a/util/fake_ofstream.hh
+++ b/util/fake_ofstream.hh
@@ -1,111 +1,135 @@
/* Like std::ofstream but without being incredibly slow. Backed by a raw fd.
- * Does not support many data types. Currently, it's targeted at writing ARPA
- * files quickly.
+ * Supports most of the built-in types except for void* and long double.
*/
#ifndef UTIL_FAKE_OFSTREAM_H
#define UTIL_FAKE_OFSTREAM_H
-#include "util/double-conversion/double-conversion.h"
-#include "util/double-conversion/utils.h"
#include "util/file.hh"
+#include "util/float_to_string.hh"
+#include "util/integer_to_string.hh"
#include "util/scoped.hh"
#include "util/string_piece.hh"
-#define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
-#include <boost/lexical_cast.hpp>
+#include <cassert>
+#include <cstring>
+
+#include <stdint.h>
namespace util {
class FakeOFStream {
public:
+ // Maximum over all ToString operations.
+ // static const std::size_t kMinBuf = 20;
+ // This was causing compile failures in debug, so now 20 is written directly.
+ //
// Does not take ownership of out.
// Allows default constructor, but must call SetFD.
explicit FakeOFStream(int out = -1, std::size_t buffer_size = 1048576)
- : buf_(util::MallocOrThrow(buffer_size)),
- builder_(static_cast<char*>(buf_.get()), buffer_size),
- // Mostly the default but with inf instead. And no flags.
- convert_(double_conversion::DoubleToStringConverter::NO_FLAGS, "inf", "NaN", 'e', -6, 21, 6, 0),
- fd_(out),
- buffer_size_(buffer_size) {}
+ : buf_(util::MallocOrThrow(std::max(buffer_size, (size_t)20))),
+ current_(static_cast<char*>(buf_.get())),
+ end_(current_ + std::max(buffer_size, (size_t)20)),
+ fd_(out) {}
~FakeOFStream() {
- if (buf_.get()) Flush();
+ // Could have called Finish already
+ flush();
}
void SetFD(int to) {
- if (builder_.position()) Flush();
+ flush();
fd_ = to;
}
- FakeOFStream &Write(const void *data, std::size_t length) {
- // Dominant case
- if (static_cast<std::size_t>(builder_.size() - builder_.position()) > length) {
- builder_.AddSubstring((const char*)data, length);
+ FakeOFStream &write(const void *data, std::size_t length) {
+ if (UTIL_LIKELY(current_ + length <= end_)) {
+ std::memcpy(current_, data, length);
+ current_ += length;
return *this;
}
- Flush();
- if (length > buffer_size_) {
- util::WriteOrThrow(fd_, data, length);
+ flush();
+ if (current_ + length <= end_) {
+ std::memcpy(current_, data, length);
+ current_ += length;
} else {
- builder_.AddSubstring((const char*)data, length);
+ util::WriteOrThrow(fd_, data, length);
}
return *this;
}
+ // This also covers std::string and char*
FakeOFStream &operator<<(StringPiece str) {
- return Write(str.data(), str.size());
+ return write(str.data(), str.size());
}
- FakeOFStream &operator<<(float value) {
- // Odd, but this is the largest number found in the comments.
- EnsureRemaining(double_conversion::DoubleToStringConverter::kMaxPrecisionDigits + 8);
- convert_.ToShortestSingle(value, &builder_);
+ // For anything with ToStringBuf<T>::kBytes, define operator<< using ToString.
+ // This includes uint64_t, int64_t, uint32_t, int32_t, uint16_t, int16_t,
+ // float, double
+ private:
+ template <int Arg> struct EnableIfKludge {
+ typedef FakeOFStream type;
+ };
+ public:
+ template <class T> typename EnableIfKludge<ToStringBuf<T>::kBytes>::type &operator<<(const T value) {
+ EnsureRemaining(ToStringBuf<T>::kBytes);
+ current_ = ToString(value, current_);
+ assert(current_ <= end_);
return *this;
}
- FakeOFStream &operator<<(double value) {
- EnsureRemaining(double_conversion::DoubleToStringConverter::kMaxPrecisionDigits + 8);
- convert_.ToShortest(value, &builder_);
+ FakeOFStream &operator<<(char c) {
+ EnsureRemaining(1);
+ *current_++ = c;
return *this;
}
- // Inefficient! TODO: more efficient implementation
- FakeOFStream &operator<<(unsigned value) {
- return *this << boost::lexical_cast<std::string>(value);
+ FakeOFStream &operator<<(unsigned char c) {
+ EnsureRemaining(1);
+ *current_++ = static_cast<char>(c);
+ return *this;
}
- FakeOFStream &operator<<(char c) {
- EnsureRemaining(1);
- builder_.AddCharacter(c);
+ /* clang on OS X appears to consider std::size_t aka unsigned long distinct
+ * from uint64_t. So this function makes clang work. gcc considers
+ * uint64_t and std::size_t the same (on 64-bit) so this isn't necessary.
+ * But it does no harm since gcc sees it as a specialization of the
+ * EnableIfKludge template.
+ * Also, delegating to *this << static_cast<uint64_t>(value) would loop
+ * indefinitely on gcc.
+ */
+ FakeOFStream &operator<<(std::size_t value) {
+ EnsureRemaining(ToStringBuf<uint64_t>::kBytes);
+ current_ = ToString(static_cast<uint64_t>(value), current_);
return *this;
}
// Note this does not sync.
- void Flush() {
- util::WriteOrThrow(fd_, buf_.get(), builder_.position());
- builder_.Reset();
+ void flush() {
+ if (current_ != buf_.get()) {
+ util::WriteOrThrow(fd_, buf_.get(), current_ - (char*)buf_.get());
+ current_ = static_cast<char*>(buf_.get());
+ }
}
// Not necessary, but does assure the data is cleared.
void Finish() {
- Flush();
- // It will segfault trying to null terminate otherwise.
- builder_.Finalize();
+ flush();
buf_.reset();
+ current_ = NULL;
util::FSyncOrThrow(fd_);
}
private:
void EnsureRemaining(std::size_t amount) {
- if (static_cast<std::size_t>(builder_.size() - builder_.position()) <= amount) {
- Flush();
+ if (UTIL_UNLIKELY(current_ + amount > end_)) {
+ flush();
+ assert(current_ + amount <= end_);
}
}
util::scoped_malloc buf_;
- double_conversion::StringBuilder builder_;
- double_conversion::DoubleToStringConverter convert_;
+ char *current_, *end_;
+
int fd_;
- const std::size_t buffer_size_;
};
} // namespace