Added slim versions of output streams.
R=bmeurer@chromium.org, mstarzinger@chromium.org Review URL: https://codereview.chromium.org/352823003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22049 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1600681420
commit
e25f833496
4
BUILD.gn
4
BUILD.gn
@ -674,8 +674,10 @@ source_set("v8_base") {
|
||||
"src/objects-visiting.h",
|
||||
"src/objects.cc",
|
||||
"src/objects.h",
|
||||
"src/optimizing-compiler-thread.h",
|
||||
"src/optimizing-compiler-thread.cc",
|
||||
"src/optimizing-compiler-thread.h",
|
||||
"src/ostreams.cc",
|
||||
"src/ostreams.h",
|
||||
"src/parser.cc",
|
||||
"src/parser.h",
|
||||
"src/platform/elapsed-timer.h",
|
||||
|
@ -189,7 +189,8 @@
|
||||
or OS=="netbsd"', {
|
||||
'target_defaults': {
|
||||
'cflags': [ '-Wall', '<(werror)', '-W', '-Wno-unused-parameter',
|
||||
'-pthread', '-fno-exceptions', '-pedantic' ],
|
||||
'-Wno-long-long', '-pthread', '-fno-exceptions',
|
||||
'-pedantic' ],
|
||||
'cflags_cc': [ '-Wnon-virtual-dtor', '-fno-rtti' ],
|
||||
'ldflags': [ '-pthread', ],
|
||||
'conditions': [
|
||||
|
161
src/ostreams.cc
Normal file
161
src/ostreams.cc
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2014 the V8 project 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 <algorithm>
|
||||
|
||||
#include "src/ostreams.h"
|
||||
|
||||
#if V8_CC_MSVC
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Be lazy and delegate the value=>char conversion to snprintf.
|
||||
template<class T>
|
||||
OStream& OStream::print(const char* format, T x) {
|
||||
char buf[32];
|
||||
int n = snprintf(buf, sizeof(buf), format, x);
|
||||
return (n < 0) ? *this : write(buf, n);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(short x) { // NOLINT(runtime/int)
|
||||
return print(hex_ ? "%hx" : "%hd", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(unsigned short x) { // NOLINT(runtime/int)
|
||||
return print(hex_ ? "%hx" : "%hu", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(int x) {
|
||||
return print(hex_ ? "%x" : "%d", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(unsigned int x) {
|
||||
return print(hex_ ? "%x" : "%u", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(long x) { // NOLINT(runtime/int)
|
||||
return print(hex_ ? "%lx" : "%ld", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(unsigned long x) { // NOLINT(runtime/int)
|
||||
return print(hex_ ? "%lx" : "%lu", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(long long x) { // NOLINT(runtime/int)
|
||||
return print(hex_ ? "%llx" : "%lld", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(unsigned long long x) { // NOLINT(runtime/int)
|
||||
return print(hex_ ? "%llx" : "%llu", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(double x) {
|
||||
return print("%g", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(void* x) {
|
||||
return print("%p", x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(char x) {
|
||||
return put(x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(signed char x) {
|
||||
return put(x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::operator<<(unsigned char x) {
|
||||
return put(x);
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::dec() {
|
||||
hex_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OStream& OStream::hex() {
|
||||
hex_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OStream& flush(OStream& os) { // NOLINT(runtime/references)
|
||||
return os.flush();
|
||||
}
|
||||
|
||||
|
||||
OStream& endl(OStream& os) { // NOLINT(runtime/references)
|
||||
return flush(os.put('\n'));
|
||||
}
|
||||
|
||||
|
||||
OStream& hex(OStream& os) { // NOLINT(runtime/references)
|
||||
return os.hex();
|
||||
}
|
||||
|
||||
|
||||
OStream& dec(OStream& os) { // NOLINT(runtime/references)
|
||||
return os.dec();
|
||||
}
|
||||
|
||||
|
||||
OStringStream& OStringStream::write(const char* s, size_t n) {
|
||||
size_t new_size = size_ + n;
|
||||
if (new_size < size_) return *this; // Overflow => no-op.
|
||||
reserve(new_size + 1);
|
||||
memcpy(data_ + size_, s, n);
|
||||
size_ = new_size;
|
||||
data_[size_] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OStringStream& OStringStream::flush() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void OStringStream::reserve(size_t requested_capacity) {
|
||||
if (requested_capacity <= capacity_) return;
|
||||
size_t new_capacity = // Handle possible overflow by not doubling.
|
||||
std::max(std::max(capacity_ * 2, capacity_), requested_capacity);
|
||||
char * new_data = allocate(new_capacity);
|
||||
memcpy(new_data, data_, size_);
|
||||
deallocate(data_, capacity_);
|
||||
capacity_ = new_capacity;
|
||||
data_ = new_data;
|
||||
}
|
||||
|
||||
|
||||
OFStream& OFStream::write(const char* s, size_t n) {
|
||||
if (f_) fwrite(s, n, 1, f_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OFStream& OFStream::flush() {
|
||||
if (f_) fflush(f_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
} } // namespace v8::internal
|
121
src/ostreams.h
Normal file
121
src/ostreams.h
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_OSTREAMS_H_
|
||||
#define V8_OSTREAMS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "include/v8config.h"
|
||||
#include "src/base/macros.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// An abstract base class for output streams with a cut-down standard interface.
|
||||
class OStream {
|
||||
public:
|
||||
OStream() : hex_(false) { }
|
||||
virtual ~OStream() { }
|
||||
|
||||
// For manipulators like 'os << endl' or 'os << flush', etc.
|
||||
OStream& operator<<(OStream& (*manipulator)(OStream& os)) {
|
||||
return manipulator(*this);
|
||||
}
|
||||
|
||||
// Numeric conversions.
|
||||
OStream& operator<<(short x); // NOLINT(runtime/int)
|
||||
OStream& operator<<(unsigned short x); // NOLINT(runtime/int)
|
||||
OStream& operator<<(int x);
|
||||
OStream& operator<<(unsigned int x);
|
||||
OStream& operator<<(long x); // NOLINT(runtime/int)
|
||||
OStream& operator<<(unsigned long x); // NOLINT(runtime/int)
|
||||
OStream& operator<<(long long x); // NOLINT(runtime/int)
|
||||
OStream& operator<<(unsigned long long x); // NOLINT(runtime/int)
|
||||
OStream& operator<<(double x);
|
||||
OStream& operator<<(void* x);
|
||||
|
||||
// Character output.
|
||||
OStream& operator<<(char x);
|
||||
OStream& operator<<(signed char x);
|
||||
OStream& operator<<(unsigned char x);
|
||||
OStream& operator<<(const char* s) { return write(s, strlen(s)); }
|
||||
OStream& put(char c) { return write(&c, 1); }
|
||||
|
||||
// Primitive format flag handling, can be extended if needed.
|
||||
OStream& dec();
|
||||
OStream& hex();
|
||||
|
||||
virtual OStream& write(const char* s, size_t n) = 0;
|
||||
virtual OStream& flush() = 0;
|
||||
|
||||
private:
|
||||
template<class T> OStream& print(const char* format, T x);
|
||||
|
||||
bool hex_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OStream);
|
||||
};
|
||||
|
||||
|
||||
// Some manipulators.
|
||||
OStream& flush(OStream& os); // NOLINT(runtime/references)
|
||||
OStream& endl(OStream& os); // NOLINT(runtime/references)
|
||||
OStream& dec(OStream& os); // NOLINT(runtime/references)
|
||||
OStream& hex(OStream& os); // NOLINT(runtime/references)
|
||||
|
||||
|
||||
// An output stream writing to a character buffer.
|
||||
class OStringStream: public OStream {
|
||||
public:
|
||||
OStringStream() : size_(0), capacity_(32), data_(allocate(capacity_)) {
|
||||
data_[0] = '\0';
|
||||
}
|
||||
~OStringStream() { deallocate(data_, capacity_); }
|
||||
|
||||
size_t size() const { return size_; }
|
||||
size_t capacity() const { return capacity_; }
|
||||
const char* data() const { return data_; }
|
||||
|
||||
// Internally, our character data is always 0-terminated.
|
||||
const char* c_str() const { return data(); }
|
||||
|
||||
virtual OStringStream& write(const char* s, size_t n) V8_OVERRIDE;
|
||||
virtual OStringStream& flush() V8_OVERRIDE;
|
||||
|
||||
private:
|
||||
// Primitive allocator interface, can be extracted if needed.
|
||||
static char* allocate (size_t n) { return new char[n]; }
|
||||
static void deallocate (char* s, size_t n) { delete[] s; }
|
||||
|
||||
void reserve(size_t requested_capacity);
|
||||
|
||||
size_t size_;
|
||||
size_t capacity_;
|
||||
char* data_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OStringStream);
|
||||
};
|
||||
|
||||
|
||||
// An output stream writing to a file.
|
||||
class OFStream: public OStream {
|
||||
public:
|
||||
explicit OFStream(FILE* f) : f_(f) { }
|
||||
virtual ~OFStream() { }
|
||||
|
||||
virtual OFStream& write(const char* s, size_t n) V8_OVERRIDE;
|
||||
virtual OFStream& flush() V8_OVERRIDE;
|
||||
|
||||
private:
|
||||
FILE* const f_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OFStream);
|
||||
};
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_OSTREAMS_H_
|
@ -96,6 +96,7 @@
|
||||
'test-mutex.cc',
|
||||
'test-object-observe.cc',
|
||||
'test-ordered-hash-table.cc',
|
||||
'test-ostreams.cc',
|
||||
'test-parsing.cc',
|
||||
'test-platform.cc',
|
||||
'test-platform-tls.cc',
|
||||
|
147
test/cctest/test-ostreams.cc
Normal file
147
test/cctest/test-ostreams.cc
Normal file
@ -0,0 +1,147 @@
|
||||
// Copyright 2014 the V8 project 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 <string.h>
|
||||
#include <limits>
|
||||
|
||||
#include "include/v8stdint.h"
|
||||
#include "src/ostreams.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
TEST(OStringStreamConstructor) {
|
||||
OStringStream oss;
|
||||
CHECK_EQ(0, oss.size());
|
||||
CHECK_GT(oss.capacity(), 0);
|
||||
CHECK_NE(NULL, oss.data());
|
||||
CHECK_EQ("", oss.c_str());
|
||||
}
|
||||
|
||||
|
||||
#define TEST_STRING \
|
||||
"Ash nazg durbatuluk, " \
|
||||
"ash nazg gimbatul, " \
|
||||
"ash nazg thrakatuluk, " \
|
||||
"agh burzum-ishi krimpatul."
|
||||
|
||||
TEST(OStringStreamGrow) {
|
||||
OStringStream oss;
|
||||
const int repeat = 30;
|
||||
size_t len = strlen(TEST_STRING);
|
||||
for (int i = 0; i < repeat; ++i) {
|
||||
oss.write(TEST_STRING, len);
|
||||
}
|
||||
const char* expected =
|
||||
TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
|
||||
TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
|
||||
TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
|
||||
TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
|
||||
TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
|
||||
TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING;
|
||||
const size_t expected_len = len * repeat;
|
||||
CHECK_EQ(static_cast<int>(expected_len), oss.size());
|
||||
CHECK_GT(oss.capacity(), 0);
|
||||
CHECK_EQ(0, strncmp(expected, oss.data(), expected_len));
|
||||
CHECK_EQ(expected, oss.c_str());
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
static void check(const char* expected, T value) {
|
||||
OStringStream oss;
|
||||
oss << value << " " << hex << value;
|
||||
CHECK_EQ(expected, oss.c_str());
|
||||
}
|
||||
|
||||
|
||||
TEST(NumericFormatting) {
|
||||
check<bool>("0 0", false);
|
||||
check<bool>("1 1", true);
|
||||
|
||||
check<int16_t>("-12345 cfc7", -12345);
|
||||
check<int16_t>("-32768 8000", std::numeric_limits<int16_t>::min());
|
||||
check<int16_t>("32767 7fff", std::numeric_limits<int16_t>::max());
|
||||
|
||||
check<uint16_t>("34567 8707", 34567);
|
||||
check<uint16_t>("0 0", std::numeric_limits<uint16_t>::min());
|
||||
check<uint16_t>("65535 ffff", std::numeric_limits<uint16_t>::max());
|
||||
|
||||
check<int32_t>("-1234567 ffed2979", -1234567);
|
||||
check<int32_t>("-2147483648 80000000", std::numeric_limits<int32_t>::min());
|
||||
check<int32_t>("2147483647 7fffffff", std::numeric_limits<int32_t>::max());
|
||||
|
||||
check<uint32_t>("3456789 34bf15", 3456789);
|
||||
check<uint32_t>("0 0", std::numeric_limits<uint32_t>::min());
|
||||
check<uint32_t>("4294967295 ffffffff", std::numeric_limits<uint32_t>::max());
|
||||
|
||||
check<int64_t>("-1234567 ffffffffffed2979", -1234567);
|
||||
check<int64_t>("-9223372036854775808 8000000000000000",
|
||||
std::numeric_limits<int64_t>::min());
|
||||
check<int64_t>("9223372036854775807 7fffffffffffffff",
|
||||
std::numeric_limits<int64_t>::max());
|
||||
|
||||
check<uint64_t>("3456789 34bf15", 3456789);
|
||||
check<uint64_t>("0 0", std::numeric_limits<uint64_t>::min());
|
||||
check<uint64_t>("18446744073709551615 ffffffffffffffff",
|
||||
std::numeric_limits<uint64_t>::max());
|
||||
|
||||
check<float>("0 0", 0.0f);
|
||||
check<float>("123 123", 123.0f);
|
||||
check<float>("-0.5 -0.5", -0.5f);
|
||||
check<float>("1.25 1.25", 1.25f);
|
||||
check<float>("0.0625 0.0625", 6.25e-2f);
|
||||
|
||||
check<double>("0 0", 0.0);
|
||||
check<double>("123 123", 123.0);
|
||||
check<double>("-0.5 -0.5", -0.5);
|
||||
check<double>("1.25 1.25", 1.25);
|
||||
check<double>("0.0625 0.0625", 6.25e-2);
|
||||
}
|
||||
|
||||
|
||||
TEST(CharacterOutput) {
|
||||
check<char>("a a", 'a');
|
||||
check<signed char>("B B", 'B');
|
||||
check<unsigned char>("9 9", '9');
|
||||
check<const char*>("bye bye", "bye");
|
||||
|
||||
OStringStream os;
|
||||
os.put('H').write("ello", 4);
|
||||
CHECK_EQ("Hello", os.c_str());
|
||||
}
|
||||
|
||||
|
||||
TEST(Manipulators) {
|
||||
OStringStream os;
|
||||
os << 123 << hex << 123 << endl << 123 << dec << 123 << 123;
|
||||
CHECK_EQ("1237b\n7b123123", os.c_str());
|
||||
}
|
||||
|
||||
|
||||
class MiscStuff {
|
||||
public:
|
||||
MiscStuff(int i, double d, const char* s) : i_(i), d_(d), s_(s) { }
|
||||
|
||||
private:
|
||||
friend OStream& operator<<(OStream& os, const MiscStuff& m);
|
||||
|
||||
int i_;
|
||||
double d_;
|
||||
const char* s_;
|
||||
};
|
||||
|
||||
|
||||
OStream& operator<<(OStream& os, const MiscStuff& m) {
|
||||
return os << "{i:" << m.i_ << ", d:" << m.d_ << ", s:'" << m.s_ << "'}";
|
||||
}
|
||||
|
||||
|
||||
TEST(CustomOutput) {
|
||||
OStringStream os;
|
||||
MiscStuff m(123, 4.5, "Hurz!");
|
||||
os << m;
|
||||
CHECK_EQ("{i:123, d:4.5, s:'Hurz!'}", os.c_str());
|
||||
}
|
@ -570,8 +570,10 @@
|
||||
'../../src/objects-visiting.h',
|
||||
'../../src/objects.cc',
|
||||
'../../src/objects.h',
|
||||
'../../src/optimizing-compiler-thread.h',
|
||||
'../../src/optimizing-compiler-thread.cc',
|
||||
'../../src/optimizing-compiler-thread.h',
|
||||
'../../src/ostreams.cc',
|
||||
'../../src/ostreams.h',
|
||||
'../../src/parser.cc',
|
||||
'../../src/parser.h',
|
||||
'../../src/platform/elapsed-timer.h',
|
||||
|
Loading…
Reference in New Issue
Block a user