Commit 877d6198 authored by lrn@chromium.org's avatar lrn@chromium.org

Extract string->double and double->string conversions for use in the preparser.

Review URL: http://codereview.chromium.org/7308004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8534 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e3b1fe2c
...@@ -126,7 +126,9 @@ SOURCES = { ...@@ -126,7 +126,9 @@ SOURCES = {
utils.cc utils.cc
v8-counters.cc v8-counters.cc
v8.cc v8.cc
v8conversions.cc
v8threads.cc v8threads.cc
v8utils.cc
variables.cc variables.cc
version.cc version.cc
zone.cc zone.cc
...@@ -229,13 +231,18 @@ SOURCES = { ...@@ -229,13 +231,18 @@ SOURCES = {
PREPARSER_SOURCES = { PREPARSER_SOURCES = {
'all': Split(""" 'all': Split("""
allocation.cc allocation.cc
bignum.cc
cached-powers.cc
conversions.cc
hashmap.cc hashmap.cc
preparse-data.cc preparse-data.cc
preparser.cc preparser.cc
preparser-api.cc preparser-api.cc
scanner-base.cc scanner-base.cc
strtod.cc
token.cc token.cc
unicode.cc unicode.cc
utils.cc
""") """)
} }
......
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -25,10 +25,9 @@ ...@@ -25,10 +25,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h" #include "../include/v8stdint.h"
#include "bignum.h"
#include "utils.h" #include "utils.h"
#include "bignum.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
......
// Copyright 2006-2008 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -26,10 +26,12 @@ ...@@ -26,10 +26,12 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h> #include <stdarg.h>
#include <math.h>
#include <limits.h> #include <limits.h>
#include "v8.h" #include "../include/v8stdint.h"
#include "globals.h"
#include "checks.h"
#include "cached-powers.h" #include "cached-powers.h"
namespace v8 { namespace v8 {
...@@ -147,7 +149,9 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( ...@@ -147,7 +149,9 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
DiyFp* power, DiyFp* power,
int* decimal_exponent) { int* decimal_exponent) {
int kQ = DiyFp::kSignificandSize; int kQ = DiyFp::kSignificandSize;
double k = ceiling((min_exponent + kQ - 1) * kD_1_LOG2_10); // Some platforms return incorrect sign on 0 result. We can ignore that here,
// which means we can avoid depending on platform.h.
double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);
int foo = kCachedPowersOffset; int foo = kCachedPowersOffset;
int index = int index =
(foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1; (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
......
This diff is collapsed.
This diff is collapsed.
...@@ -28,11 +28,36 @@ ...@@ -28,11 +28,36 @@
#ifndef V8_CONVERSIONS_H_ #ifndef V8_CONVERSIONS_H_
#define V8_CONVERSIONS_H_ #define V8_CONVERSIONS_H_
#include <limits>
#include "scanner-base.h" #include "scanner-base.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// Maximum number of significant digits in decimal representation.
// The longest possible double in decimal representation is
// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
// (768 digits). If we parse a number whose first digits are equal to a
// mean of 2 adjacent doubles (that could have up to 769 digits) the result
// must be rounded to the bigger one unless the tail consists of zeros, so
// we don't need to preserve all the digits.
const int kMaxSignificantDigits = 772;
static const double JUNK_STRING_VALUE =
std::numeric_limits<double>::quiet_NaN();
static bool isDigit(int x, int radix) {
return (x >= '0' && x <= '9' && x < '0' + radix)
|| (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
|| (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
}
static double SignedZero(bool negative) {
return negative ? -0.0 : 0.0;
}
// The fast double-to-(unsigned-)int conversion routine does not guarantee // The fast double-to-(unsigned-)int conversion routine does not guarantee
// rounding towards zero. // rounding towards zero.
...@@ -87,16 +112,7 @@ enum ConversionFlags { ...@@ -87,16 +112,7 @@ enum ConversionFlags {
}; };
// Convert from Number object to C integer.
static inline int32_t NumberToInt32(Object* number);
static inline uint32_t NumberToUint32(Object* number);
// Converts a string into a double value according to ECMA-262 9.3.1 // Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(UnicodeCache* unicode_cache,
String* str,
int flags,
double empty_string_val = 0);
double StringToDouble(UnicodeCache* unicode_cache, double StringToDouble(UnicodeCache* unicode_cache,
Vector<const char> str, Vector<const char> str,
int flags, int flags,
...@@ -111,9 +127,6 @@ double StringToDouble(UnicodeCache* unicode_cache, ...@@ -111,9 +127,6 @@ double StringToDouble(UnicodeCache* unicode_cache,
int flags, int flags,
double empty_string_val = 0); double empty_string_val = 0);
// Converts a string into an integer.
double StringToInt(UnicodeCache* unicode_cache, String* str, int radix);
// Converts a double to a string value according to ECMA-262 9.8.1. // Converts a double to a string value according to ECMA-262 9.8.1.
// The buffer should be large enough for any floating point number. // The buffer should be large enough for any floating point number.
// 100 characters is enough. // 100 characters is enough.
......
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -25,8 +25,9 @@ ...@@ -25,8 +25,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h" #include "../include/v8stdint.h"
#include "globals.h"
#include "checks.h"
#include "diy-fp.h" #include "diy-fp.h"
namespace v8 { namespace v8 {
......
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -80,7 +80,7 @@ class DiyFp { ...@@ -80,7 +80,7 @@ class DiyFp {
// This method is mainly called for normalizing boundaries. In general // This method is mainly called for normalizing boundaries. In general
// boundaries need to be shifted by 10 bits. We thus optimize for this case. // boundaries need to be shifted by 10 bits. We thus optimize for this case.
const uint64_t k10MSBits = V8_2PART_UINT64_C(0xFFC00000, 00000000); const uint64_t k10MSBits = static_cast<uint64_t>(0x3FF) << 54;
while ((f & k10MSBits) == 0) { while ((f & k10MSBits) == 0) {
f <<= 10; f <<= 10;
e -= 10; e -= 10;
...@@ -106,7 +106,7 @@ class DiyFp { ...@@ -106,7 +106,7 @@ class DiyFp {
void set_e(int new_value) { e_ = new_value; } void set_e(int new_value) { e_ = new_value; }
private: private:
static const uint64_t kUint64MSB = V8_2PART_UINT64_C(0x80000000, 00000000); static const uint64_t kUint64MSB = static_cast<uint64_t>(1) << 63;
uint64_t f_; uint64_t f_;
int e_; int e_;
......
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
#include "data-flow.h" #include "data-flow.h"
#include "small-pointer-list.h" #include "small-pointer-list.h"
#include "string-stream.h" #include "string-stream.h"
#include "utils.h" #include "v8conversions.h"
#include "v8utils.h"
#include "zone.h" #include "zone.h"
namespace v8 { namespace v8 {
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include "v8.h" #include "v8.h"
#include "char-predicates-inl.h" #include "char-predicates-inl.h"
#include "conversions.h" #include "v8conversions.h"
#include "messages.h" #include "messages.h"
#include "spaces-inl.h" #include "spaces-inl.h"
#include "token.h" #include "token.h"
......
...@@ -2585,4 +2585,3 @@ void LiveObjectList::VerifyNotInFromSpace() { ...@@ -2585,4 +2585,3 @@ void LiveObjectList::VerifyNotInFromSpace() {
} } // namespace v8::internal } } // namespace v8::internal
#endif // LIVE_OBJECT_LIST #endif // LIVE_OBJECT_LIST
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include "preparse-data.h" #include "preparse-data.h"
#include "preparser.h" #include "preparser.h"
#include "conversions-inl.h"
namespace v8 { namespace v8 {
namespace preparser { namespace preparser {
......
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -26,9 +26,13 @@ ...@@ -26,9 +26,13 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h> #include <stdarg.h>
#include <limits.h> #include <limits>
#include "v8.h" #ifndef V8_INFINITY
#define V8_INFINITY std::numeric_limits<double>::infinity()
#endif
#include "utils.h"
#include "strtod.h" #include "strtod.h"
#include "bignum.h" #include "bignum.h"
......
This diff is collapsed.
...@@ -822,6 +822,69 @@ class EmbeddedContainer<ElementType, 0> { ...@@ -822,6 +822,69 @@ class EmbeddedContainer<ElementType, 0> {
}; };
// Helper class for building result strings in a character buffer. The
// purpose of the class is to use safe operations that checks the
// buffer bounds on all operations in debug mode.
// This simple base class does not allow formatted output.
class SimpleStringBuilder {
public:
// Create a string builder with a buffer of the given size. The
// buffer is allocated through NewArray<char> and must be
// deallocated by the caller of Finalize().
explicit SimpleStringBuilder(int size);
SimpleStringBuilder(char* buffer, int size)
: buffer_(buffer, size), position_(0) { }
~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
int size() const { return buffer_.length(); }
// Get the current position in the builder.
int position() const {
ASSERT(!is_finalized());
return position_;
}
// Reset the position.
void Reset() { position_ = 0; }
// Add a single character to the builder. It is not allowed to add
// 0-characters; use the Finalize() method to terminate the string
// instead.
void AddCharacter(char c) {
ASSERT(c != '\0');
ASSERT(!is_finalized() && position_ < buffer_.length());
buffer_[position_++] = c;
}
// Add an entire string to the builder. Uses strlen() internally to
// compute the length of the input string.
void AddString(const char* s);
// Add the first 'n' characters of the given string 's' to the
// builder. The input string must have enough characters.
void AddSubstring(const char* s, int n);
// Add character padding to the builder. If count is non-positive,
// nothing is added to the builder.
void AddPadding(char c, int count);
// Add the decimal representation of the value.
void AddDecimalInteger(int value);
// Finalize the string by 0-terminating it and returning the buffer.
char* Finalize();
protected:
Vector<char> buffer_;
int position_;
bool is_finalized() const { return position_ < 0; }
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
};
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_UTILS_H_ #endif // V8_UTILS_H_
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <limits.h>
#include "v8.h"
#include "conversions-inl.h"
#include "v8conversions.h"
#include "dtoa.h"
#include "factory.h"
#include "scanner-base.h"
#include "strtod.h"
namespace v8 {
namespace internal {
namespace {
// C++-style iterator adaptor for StringInputBuffer
// (unlike C++ iterators the end-marker has different type).
class StringInputBufferIterator {
public:
class EndMarker {};
explicit StringInputBufferIterator(StringInputBuffer* buffer);
int operator*() const;
void operator++();
bool operator==(EndMarker const&) const { return end_; }
bool operator!=(EndMarker const& m) const { return !end_; }
private:
StringInputBuffer* const buffer_;
int current_;
bool end_;
};
StringInputBufferIterator::StringInputBufferIterator(
StringInputBuffer* buffer) : buffer_(buffer) {
++(*this);
}
int StringInputBufferIterator::operator*() const {
return current_;
}
void StringInputBufferIterator::operator++() {
end_ = !buffer_->has_more();
if (!end_) {
current_ = buffer_->GetNext();
}
}
} // End anonymous namespace.
double StringToDouble(UnicodeCache* unicode_cache,
String* str, int flags, double empty_string_val) {
StringShape shape(str);
if (shape.IsSequentialAscii()) {
const char* begin = SeqAsciiString::cast(str)->GetChars();
const char* end = begin + str->length();
return InternalStringToDouble(unicode_cache, begin, end, flags,
empty_string_val);
} else if (shape.IsSequentialTwoByte()) {
const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
const uc16* end = begin + str->length();
return InternalStringToDouble(unicode_cache, begin, end, flags,
empty_string_val);
} else {
StringInputBuffer buffer(str);
return InternalStringToDouble(unicode_cache,
StringInputBufferIterator(&buffer),
StringInputBufferIterator::EndMarker(),
flags,
empty_string_val);
}
}
double StringToInt(UnicodeCache* unicode_cache,
String* str,
int radix) {
StringShape shape(str);
if (shape.IsSequentialAscii()) {
const char* begin = SeqAsciiString::cast(str)->GetChars();
const char* end = begin + str->length();
return InternalStringToInt(unicode_cache, begin, end, radix);
} else if (shape.IsSequentialTwoByte()) {
const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
const uc16* end = begin + str->length();
return InternalStringToInt(unicode_cache, begin, end, radix);
} else {
StringInputBuffer buffer(str);
return InternalStringToInt(unicode_cache,
StringInputBufferIterator(&buffer),
StringInputBufferIterator::EndMarker(),
radix);
}
}
} } // namespace v8::internal
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_V8CONVERSIONS_H_
#define V8_V8CONVERSIONS_H_
#include "conversions.h"
namespace v8 {
namespace internal {
// Convert from Number object to C integer.
static inline int32_t NumberToInt32(Object* number) {
if (number->IsSmi()) return Smi::cast(number)->value();
return DoubleToInt32(number->Number());
}
static inline uint32_t NumberToUint32(Object* number) {
if (number->IsSmi()) return Smi::cast(number)->value();
return DoubleToUint32(number->Number());
}
// Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(UnicodeCache* unicode_cache,
String* str,
int flags,
double empty_string_val = 0);
// Converts a string into an integer.
double StringToInt(UnicodeCache* unicode_cache, String* str, int radix);
} } // namespace v8::internal
#endif // V8_V8CONVERSIONS_H_
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include "v8.h"
#include "platform.h"
#include "sys/stat.h"
namespace v8 {
namespace internal {
void PrintF(const char* format, ...) {
va_list arguments;
va_start(arguments, format);
OS::VPrint(format, arguments);
va_end(arguments);
}
void PrintF(FILE* out, const char* format, ...) {
va_list arguments;
va_start(arguments, format);
OS::VFPrint(out, format, arguments);
va_end(arguments);
}
void Flush(FILE* out) {
fflush(out);
}
char* ReadLine(const char* prompt) {
char* result = NULL;
char line_buf[256];
int offset = 0;
bool keep_going = true;
fprintf(stdout, "%s", prompt);
fflush(stdout);
while (keep_going) {
if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
// fgets got an error. Just give up.
if (result != NULL) {
DeleteArray(result);
}
return NULL;
}
int len = StrLength(line_buf);
if (len > 1 &&
line_buf[len - 2] == '\\' &&
line_buf[len - 1] == '\n') {
// When we read a line that ends with a "\" we remove the escape and
// append the remainder.
line_buf[len - 2] = '\n';
line_buf[len - 1] = 0;
len -= 1;
} else if ((len > 0) && (line_buf[len - 1] == '\n')) {
// Since we read a new line we are done reading the line. This
// will exit the loop after copying this buffer into the result.
keep_going = false;
}
if (result == NULL) {
// Allocate the initial result and make room for the terminating '\0'
result = NewArray<char>(len + 1);
} else {
// Allocate a new result with enough room for the new addition.
int new_len = offset + len + 1;
char* new_result = NewArray<char>(new_len);
// Copy the existing input into the new array and set the new
// array as the result.
memcpy(new_result, result, offset * kCharSize);
DeleteArray(result);
result = new_result;
}
// Copy the newly read line into the result.
memcpy(result + offset, line_buf, len * kCharSize);
offset += len;
}
ASSERT(result != NULL);
result[offset] = '\0';
return result;
}
char* ReadCharsFromFile(const char* filename,
int* size,
int extra_space,
bool verbose) {
FILE* file = OS::FOpen(filename, "rb");
if (file == NULL || fseek(file, 0, SEEK_END) != 0) {
if (verbose) {
OS::PrintError("Cannot read from file %s.\n", filename);
}
return NULL;
}
// Get the size of the file and rewind it.
*size = ftell(file);
rewind(file);
char* result = NewArray<char>(*size + extra_space);
for (int i = 0; i < *size;) {
int read = static_cast<int>(fread(&result[i], 1, *size - i, file));
if (read <= 0) {
fclose(file);
DeleteArray(result);
return NULL;
}
i += read;
}
fclose(file);
return result;
}
byte* ReadBytes(const char* filename, int* size, bool verbose) {
char* chars = ReadCharsFromFile(filename, size, 0, verbose);
return reinterpret_cast<byte*>(chars);
}
Vector<const char> ReadFile(const char* filename,
bool* exists,
bool verbose) {
int size;
char* result = ReadCharsFromFile(filename, &size, 1, verbose);
if (!result) {
*exists = false;
return Vector<const char>::empty();
}
result[size] = '\0';
*exists = true;
return Vector<const char>(result, size);
}
int WriteCharsToFile(const char* str, int size, FILE* f) {
int total = 0;
while (total < size) {
int write = static_cast<int>(fwrite(str, 1, size - total, f));
if (write == 0) {
return total;
}
total += write;
str += write;
}
return total;
}
int AppendChars(const char* filename,
const char* str,
int size,
bool verbose) {
FILE* f = OS::FOpen(filename, "ab");
if (f == NULL) {
if (verbose) {
OS::PrintError("Cannot open file %s for writing.\n", filename);
}
return 0;
}
int written = WriteCharsToFile(str, size, f);
fclose(f);
return written;
}
int WriteChars(const char* filename,
const char* str,
int size,
bool verbose) {
FILE* f = OS::FOpen(filename, "wb");
if (f == NULL) {
if (verbose) {
OS::PrintError("Cannot open file %s for writing.\n", filename);
}
return 0;
}
int written = WriteCharsToFile(str, size, f);
fclose(f);
return written;
}
int WriteBytes(const char* filename,
const byte* bytes,
int size,
bool verbose) {
const char* str = reinterpret_cast<const char*>(bytes);
return WriteChars(filename, str, size, verbose);
}
void StringBuilder::AddFormatted(const char* format, ...) {
va_list arguments;
va_start(arguments, format);
AddFormattedList(format, arguments);
va_end(arguments);
}
void StringBuilder::AddFormattedList(const char* format, va_list list) {
ASSERT(!is_finalized() && position_ < buffer_.length());
int n = OS::VSNPrintF(buffer_ + position_, format, list);
if (n < 0 || n >= (buffer_.length() - position_)) {
position_ = buffer_.length();
} else {
position_ += n;
}
}
MemoryMappedExternalResource::MemoryMappedExternalResource(const char* filename)
: filename_(NULL),
data_(NULL),
length_(0),
remove_file_on_cleanup_(false) {
Init(filename);
}
MemoryMappedExternalResource::
MemoryMappedExternalResource(const char* filename,
bool remove_file_on_cleanup)
: filename_(NULL),
data_(NULL),
length_(0),
remove_file_on_cleanup_(remove_file_on_cleanup) {
Init(filename);
}
MemoryMappedExternalResource::~MemoryMappedExternalResource() {
// Release the resources if we had successfully acquired them:
if (file_ != NULL) {
delete file_;
if (remove_file_on_cleanup_) {
OS::Remove(filename_);
}
DeleteArray<char>(filename_);
}
}
void MemoryMappedExternalResource::Init(const char* filename) {
file_ = OS::MemoryMappedFile::open(filename);
if (file_ != NULL) {
filename_ = StrDup(filename);
data_ = reinterpret_cast<char*>(file_->memory());
length_ = file_->size();
}
}
bool MemoryMappedExternalResource::EnsureIsAscii(bool abort_if_failed) const {
bool is_ascii = true;
int line_no = 1;
const char* start_of_line = data_;
const char* end = data_ + length_;
for (const char* p = data_; p < end; p++) {
char c = *p;
if ((c & 0x80) != 0) {
// Non-ascii detected:
is_ascii = false;
// Report the error and abort if appropriate:
if (abort_if_failed) {
int char_no = static_cast<int>(p - start_of_line) - 1;
ASSERT(filename_ != NULL);
PrintF("\n\n\n"
"Abort: Non-Ascii character 0x%.2x in file %s line %d char %d",
c, filename_, line_no, char_no);
// Allow for some context up to kNumberOfLeadingContextChars chars
// before the offending non-ascii char to help the user see where
// the offending char is.
const int kNumberOfLeadingContextChars = 10;
const char* err_context = p - kNumberOfLeadingContextChars;
if (err_context < data_) {
err_context = data_;
}
// Compute the length of the error context and print it.
int err_context_length = static_cast<int>(p - err_context);
if (err_context_length != 0) {
PrintF(" after \"%.*s\"", err_context_length, err_context);
}
PrintF(".\n\n\n");
OS::Abort();
}
break; // Non-ascii detected. No need to continue scanning.
}
if (c == '\n') {
start_of_line = p;
line_no++;
}
}
return is_ascii;
}
} } // namespace v8::internal
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -190,71 +190,6 @@ Vector<const char> ReadFile(const char* filename, ...@@ -190,71 +190,6 @@ Vector<const char> ReadFile(const char* filename,
bool verbose = true); bool verbose = true);
// Helper class for building result strings in a character buffer. The
// purpose of the class is to use safe operations that checks the
// buffer bounds on all operations in debug mode.
class StringBuilder {
public:
// Create a string builder with a buffer of the given size. The
// buffer is allocated through NewArray<char> and must be
// deallocated by the caller of Finalize().
explicit StringBuilder(int size);
StringBuilder(char* buffer, int size)
: buffer_(buffer, size), position_(0) { }
~StringBuilder() { if (!is_finalized()) Finalize(); }
int size() const { return buffer_.length(); }
// Get the current position in the builder.
int position() const {
ASSERT(!is_finalized());
return position_;
}
// Reset the position.
void Reset() { position_ = 0; }
// Add a single character to the builder. It is not allowed to add
// 0-characters; use the Finalize() method to terminate the string
// instead.
void AddCharacter(char c) {
ASSERT(c != '\0');
ASSERT(!is_finalized() && position_ < buffer_.length());
buffer_[position_++] = c;
}
// Add an entire string to the builder. Uses strlen() internally to
// compute the length of the input string.
void AddString(const char* s);
// Add the first 'n' characters of the given string 's' to the
// builder. The input string must have enough characters.
void AddSubstring(const char* s, int n);
// Add formatted contents to the builder just like printf().
void AddFormatted(const char* format, ...);
// Add formatted contents like printf based on a va_list.
void AddFormattedList(const char* format, va_list list);
// Add character padding to the builder. If count is non-positive,
// nothing is added to the builder.
void AddPadding(char c, int count);
// Finalize the string by 0-terminating it and returning the buffer.
char* Finalize();
private:
Vector<char> buffer_;
int position_;
bool is_finalized() const { return position_ < 0; }
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
};
// Copy from ASCII/16bit chars to ASCII/16bit chars. // Copy from ASCII/16bit chars to ASCII/16bit chars.
template <typename sourcechar, typename sinkchar> template <typename sourcechar, typename sinkchar>
...@@ -313,6 +248,19 @@ class MemoryMappedExternalResource: public ...@@ -313,6 +248,19 @@ class MemoryMappedExternalResource: public
bool remove_file_on_cleanup_; bool remove_file_on_cleanup_;
}; };
class StringBuilder : public SimpleStringBuilder {
public:
explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
// Add formatted contents to the builder just like printf().
void AddFormatted(const char* format, ...);
// Add formatted contents like printf based on a va_list.
void AddFormattedList(const char* format, va_list list);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
};
} } // namespace v8::internal } } // namespace v8::internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment