/*
* Copyright (c) 2018-present Samsung Electronics Co., Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#include "Escargot.h"
#include "runtime/MapObject.h"
#include "runtime/ArrayObject.h"
#include "runtime/Context.h"
namespace Escargot {
MapObject::MapObject(ExecutionState& state)
: MapObject(state, state.context()->globalObject()->mapPrototype())
{
}
MapObject::MapObject(ExecutionState& state, Object* proto)
: Object(state, proto)
{
}
void* MapObject::operator new(size_t size)
{
static MAY_THREAD_LOCAL bool typeInited = false;
static MAY_THREAD_LOCAL GC_descr descr;
if (!typeInited) {
GC_word obj_bitmap[GC_BITMAP_SIZE(MapObject)] = { 0 };
Object::fillGCDescriptor(obj_bitmap);
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(MapObject, m_storage));
descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(MapObject));
typeInited = true;
}
return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
}
void MapObject::clear(ExecutionState& state)
{
for (size_t i = 0; i < m_storage.size(); i++) {
m_storage[i] = std::make_pair(Value(Value::EmptyValue), Value(Value::EmptyValue));
}
}
size_t MapObject::size(ExecutionState& state)
{
size_t siz = 0;
for (size_t i = 0; i < m_storage.size(); i++) {
Value existingKey = m_storage[i].first;
if (existingKey.isEmpty()) {
continue;
}
siz++;
}
return siz;
}
bool MapObject::deleteOperation(ExecutionState& state, const Value& key)
{
for (size_t i = 0; i < m_storage.size(); i++) {
Value existingKey = m_storage[i].first;
if (existingKey.isEmpty()) {
continue;
}
if (existingKey.equalsToByTheSameValueZeroAlgorithm(state, key)) {
m_storage[i] = std::make_pair(Value(Value::EmptyValue), Value(Value::EmptyValue));
return true;
}
}
return false;
}
Value MapObject::get(ExecutionState& state, const Value& key)
{
for (size_t i = 0; i < m_storage.size(); i++) {
Value existingKey = m_storage[i].first;
if (existingKey.isEmpty()) {
continue;
}
if (existingKey.equalsToByTheSameValueZeroAlgorithm(state, key)) {
return m_storage[i].second;
}
}
return Value();
}
bool MapObject::has(ExecutionState& state, const Value& key)
{
for (size_t i = 0; i < m_storage.size(); i++) {
Value existingKey = m_storage[i].first;
if (existingKey.isEmpty()) {
continue;
}
if (existingKey.equalsToByTheSameValueZeroAlgorithm(state, key)) {
return true;
}
}
return false;
}
void MapObject::set(ExecutionState& state, const Value& key, const Value& value)
{
for (size_t i = 0; i < m_storage.size(); i++) {
Value existingKey = m_storage[i].first;
if (existingKey.isEmpty()) {
continue;
}
if (existingKey.equalsToByTheSameValueZeroAlgorithm(state, key)) {
m_storage[i].second = value;
return;
}
}
// If key is -0, let key be +0.
if (key.isNumber() && key.asNumber() == 0 && std::signbit(key.asNumber())) {
m_storage.pushBack(std::make_pair(Value(0), value));
} else {
m_storage.pushBack(std::make_pair(key, value));
}
}
IteratorObject* MapObject::values(ExecutionState& state)
{
return new MapIteratorObject(state, this, MapIteratorObject::TypeValue);
}
IteratorObject* MapObject::keys(ExecutionState& state)
{
return new MapIteratorObject(state, this, MapIteratorObject::TypeKey);
}
IteratorObject* MapObject::entries(ExecutionState& state)
{
return new MapIteratorObject(state, this, MapIteratorObject::TypeKeyValue);
}
MapIteratorObject::MapIteratorObject(ExecutionState& state, MapObject* map, Type type)
: IteratorObject(state, state.context()->globalObject()->mapIteratorPrototype())
, m_map(map)
, m_iteratorIndex(0)
, m_type(type)
{
}
void* MapIteratorObject::operator new(size_t size)
{
static MAY_THREAD_LOCAL bool typeInited = false;
static MAY_THREAD_LOCAL GC_descr descr;
if (!typeInited) {
GC_word obj_bitmap[GC_BITMAP_SIZE(MapIteratorObject)] = { 0 };
Object::fillGCDescriptor(obj_bitmap);
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(MapIteratorObject, m_map));
descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(MapIteratorObject));
typeInited = true;
}
return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
}
std::pair