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:
svenpanne@chromium.org 2014-06-27 08:42:17 +00:00
parent 1600681420
commit e25f833496
7 changed files with 438 additions and 3 deletions

View File

@ -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",

View File

@ -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
View 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
View 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_

View File

@ -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',

View 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());
}

View File

@ -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',