4c0f559d23
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@15 260f80e4-7a28-3924-810f-c04153c831b5
151 lines
4.7 KiB
C++
151 lines
4.7 KiB
C++
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "vm/bootstrap_natives.h"
|
|
|
|
#include "vm/exceptions.h"
|
|
#include "vm/native_entry.h"
|
|
#include "vm/object.h"
|
|
|
|
namespace dart {
|
|
|
|
DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 1) {
|
|
const Array& a = Array::CheckedHandle(arguments->At(0));
|
|
// TODO(srdjan): Check that parameterized type is an int.
|
|
Zone* zone = Isolate::Current()->current_zone();
|
|
intptr_t len = a.Length();
|
|
|
|
// Unbox the array and determine the maximum element width.
|
|
bool is_one_byte_string = true;
|
|
bool is_two_byte_string = true;
|
|
uint32_t* temp = reinterpret_cast<uint32_t*>(
|
|
zone->Allocate(len * sizeof(uint32_t))); // NOLINT
|
|
Smi& element = Smi::Handle();
|
|
for (intptr_t i = 0; i < len; i++) {
|
|
const Object& index_object = Object::Handle(a.At(i));
|
|
if (!index_object.IsSmi()) {
|
|
GrowableArray<const Object*> args;
|
|
args.Add(&index_object);
|
|
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
|
|
}
|
|
element ^= index_object.raw();
|
|
intptr_t value = element.Value();
|
|
if (value < 0) {
|
|
GrowableArray<const Object*> args;
|
|
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
|
|
} else if (value > 0xFFFF) {
|
|
is_one_byte_string = false;
|
|
is_two_byte_string = false;
|
|
} else if (value > 0xFF) {
|
|
is_one_byte_string = false;
|
|
}
|
|
temp[i] = value;
|
|
}
|
|
String& result = String::Handle();
|
|
if (is_one_byte_string) {
|
|
result ^= OneByteString::New(temp, len, Heap::kNew);
|
|
} else if (is_two_byte_string) {
|
|
result ^= TwoByteString::New(temp, len, Heap::kNew);
|
|
} else {
|
|
result ^= FourByteString::New(temp, len, Heap::kNew);
|
|
}
|
|
arguments->SetReturn(result);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(String_hashCode, 1) {
|
|
const String& str = String::CheckedHandle(arguments->At(0));
|
|
intptr_t hash_val = 0;
|
|
if (!str.IsNull()) {
|
|
hash_val = str.Hash();
|
|
}
|
|
ASSERT(Smi::IsValid(hash_val));
|
|
ASSERT(hash_val > 0);
|
|
const Smi& hash_smi = Smi::Handle(Smi::New(hash_val));
|
|
arguments->SetReturn(hash_smi);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(String_getLength, 1) {
|
|
const String& str = String::CheckedHandle(arguments->At(0));
|
|
arguments->SetReturn(Smi::Handle(Smi::New(str.Length())));
|
|
}
|
|
|
|
|
|
static int32_t StringValueAt(const String& str, const Integer& index) {
|
|
if (index.IsSmi()) {
|
|
Smi& smi = Smi::Handle();
|
|
smi ^= index.raw();
|
|
int32_t index = smi.Value();
|
|
if ((index < 0) || (index >= str.Length())) {
|
|
GrowableArray<const Object*> arguments;
|
|
arguments.Add(&smi);
|
|
Exceptions::ThrowByType(Exceptions::kIndexOutOfRange, arguments);
|
|
}
|
|
return str.CharAt(index);
|
|
} else {
|
|
// TODO(srdjan): Bigint index not supported.
|
|
UNIMPLEMENTED();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(String_charAt, 2) {
|
|
const String& str = String::CheckedHandle(arguments->At(0));
|
|
const Instance& index_instance = Instance::CheckedHandle(arguments->At(1));
|
|
if (!index_instance.IsInteger()) {
|
|
GrowableArray<const Object*> args;
|
|
args.Add(&index_instance);
|
|
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
|
|
}
|
|
Integer& index = Integer::Handle();
|
|
index ^= index_instance.raw();
|
|
uint32_t value = StringValueAt(str, index);
|
|
ASSERT(value <= 0x10FFFF);
|
|
arguments->SetReturn(String::Handle(String::NewSymbol(&value, 1)));
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) {
|
|
const String& str = String::CheckedHandle(arguments->At(0));
|
|
const Integer& index_instance = Integer::CheckedHandle(arguments->At(1));
|
|
if (!index_instance.IsInteger()) {
|
|
GrowableArray<const Object*> args;
|
|
args.Add(&index_instance);
|
|
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
|
|
}
|
|
Integer& index = Integer::Handle();
|
|
index ^= index_instance.raw();
|
|
int32_t value = StringValueAt(str, index);
|
|
ASSERT(value >= 0);
|
|
ASSERT(value <= 0x10FFFF);
|
|
arguments->SetReturn(Smi::Handle(Smi::New(value)));
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(String_concat, 2) {
|
|
const String& a = String::CheckedHandle(arguments->At(0));
|
|
ASSERT(!a.IsNull()); // The receiver cannot be null.
|
|
const Instance& b_instance = Instance::CheckedHandle(arguments->At(1));
|
|
if (!b_instance.IsString()) {
|
|
GrowableArray<const Object*> args;
|
|
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
|
|
}
|
|
String& b = String::Handle();
|
|
b ^= b_instance.raw();
|
|
const String& result = String::Handle(String::Concat(a, b));
|
|
arguments->SetReturn(result);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Strings_concatAll, 1) {
|
|
const Array& strings = Array::CheckedHandle(arguments->At(0));
|
|
ASSERT(!strings.IsNull());
|
|
const String& result = String::Handle(String::ConcatAll(strings));
|
|
arguments->SetReturn(result);
|
|
}
|
|
|
|
} // namespace dart
|