jerryscript/jerry-core/rcs/rcs-iterator.cpp
Zidong Jiang dfb22c3441 refactor rcs_chunked_list and remove its c++ features
issue #806

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
2016-02-05 11:11:36 +01:00

216 lines
6.5 KiB
C++

/* Copyright 2015 Samsung Electronics Co., Ltd.
* Copyright 2015 University of Szeged
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rcs-iterator.h"
#include "rcs-allocator.h"
#include "rcs-records.h"
/**
* Represents the memory access on the literal storage.
*/
typedef enum
{
RCS_ITERATOR_ACCESS_WRITE = 0, /**< Write 'size' bytes from 'data' buffer to the record. */
RCS_ITERATOR_ACCESS_READ = 1, /**< Read 'size' bytes from the record and write to the 'data' buffer. */
RCS_ITERATOR_ACCESS_SKIP = 2 /**< Increment current position so that 'size' bytes would be skipped. */
} rcs_access_t;
/**
* Create an iterator context.
*
* @return an initialized iterator context
*/
rcs_iterator_t
rcs_iterator_create (rcs_record_set_t *recordset_p, /**< recordset */
rcs_record_t *record_p) /**< start record */
{
rcs_iterator_t ctx;
{
ctx.recordset_p = recordset_p;
ctx.record_start_p = record_p;
rcs_iterator_reset (&ctx);
}
return ctx;
} /* rcs_iterator_create */
/**
* Perform general access to the record
*
* Warning: This function is implemented in assumption that `size` is not more than `2 * node_data_space_size`.
*/
static void
rcs_iterator_access (rcs_iterator_t *ctx_p, /**< iterator context */
void *data, /**< iterator context */
size_t size, /**< iterator context */
rcs_access_t access_type) /**< access type */
{
const size_t node_data_space_size = rcs_get_node_data_space_size ();
JERRY_ASSERT (2 * node_data_space_size >= size);
const size_t record_size = rcs_record_get_size (ctx_p->record_start_p);
JERRY_ASSERT (!rcs_iterator_finished (ctx_p));
rcs_chunked_list_node_t *current_node_p =
rcs_chunked_list_get_node_from_pointer (ctx_p->recordset_p, ctx_p->current_pos_p);
uint8_t *current_node_data_space_p = rcs_get_node_data_space (ctx_p->recordset_p, current_node_p);
size_t left_in_node = node_data_space_size - (size_t) (ctx_p->current_pos_p - current_node_data_space_p);
JERRY_ASSERT (ctx_p->current_offset + size <= record_size);
/*
* Read the data and increase the current position pointer.
*/
if (left_in_node >= size)
{
/* all data is placed inside single node */
if (access_type == RCS_ITERATOR_ACCESS_READ)
{
memcpy (data, ctx_p->current_pos_p, size);
}
else if (access_type == RCS_ITERATOR_ACCESS_WRITE)
{
memcpy (ctx_p->current_pos_p, data, size);
}
else
{
JERRY_ASSERT (access_type == RCS_ITERATOR_ACCESS_SKIP);
if (left_in_node > size)
{
ctx_p->current_pos_p += size;
}
else if (ctx_p->current_offset + size < record_size)
{
current_node_p = rcs_chunked_list_get_next (current_node_p);
JERRY_ASSERT (current_node_p);
ctx_p->current_pos_p = rcs_get_node_data_space (ctx_p->recordset_p, current_node_p);
}
else
{
JERRY_ASSERT (ctx_p->current_offset + size == record_size);
}
}
}
else
{
/* Data is distributed between two nodes. */
const size_t first_chunk_size = node_data_space_size - (size_t) (ctx_p->current_pos_p - current_node_data_space_p);
if (access_type == RCS_ITERATOR_ACCESS_READ)
{
memcpy (data, ctx_p->current_pos_p, first_chunk_size);
}
else if (access_type == RCS_ITERATOR_ACCESS_WRITE)
{
memcpy (ctx_p->current_pos_p, data, first_chunk_size);
}
rcs_chunked_list_node_t *next_node_p = rcs_chunked_list_get_next (current_node_p);
JERRY_ASSERT (next_node_p != NULL);
uint8_t *next_node_data_space_p = rcs_get_node_data_space (ctx_p->recordset_p, next_node_p);
if (access_type == RCS_ITERATOR_ACCESS_READ)
{
memcpy ((uint8_t *)data + first_chunk_size, next_node_data_space_p, size - first_chunk_size);
}
else if (access_type == RCS_ITERATOR_ACCESS_WRITE)
{
memcpy (next_node_data_space_p, (uint8_t *)data + first_chunk_size, size - first_chunk_size);
}
else
{
JERRY_ASSERT (access_type == RCS_ITERATOR_ACCESS_SKIP);
ctx_p->current_pos_p = next_node_data_space_p + size - first_chunk_size;
}
}
/* Check if we reached the end. */
if (access_type == RCS_ITERATOR_ACCESS_SKIP)
{
ctx_p->current_offset += size;
JERRY_ASSERT (ctx_p->current_offset <= record_size);
if (ctx_p->current_offset == record_size)
{
ctx_p->current_pos_p = NULL;
ctx_p->current_offset = 0;
}
}
} /* rcs_iterator_access */
/**
* Read a value from the record.
* After reading iterator doesn't change its position.
*
* @return read value
*/
void
rcs_iterator_read (rcs_iterator_t *ctx_p, /**< iterator context */
void *out_data, /**< value to read */
size_t size) /**< size to read */
{
rcs_iterator_access (ctx_p, out_data, size, RCS_ITERATOR_ACCESS_READ);
} /* rcs_iterator_read */
/**
* Write a value to the record.
* After writing, iterator doesn't change its position.
*/
void
rcs_iterator_write (rcs_iterator_t *ctx_p, /**< iterator context */
void *value, /**< value to write */
size_t size) /**< size to write */
{
rcs_iterator_access (ctx_p, value, size, RCS_ITERATOR_ACCESS_WRITE);
} /* rcs_iterator_write */
/**
* Increment current position to skip 'size' bytes.
*/
void
rcs_iterator_skip (rcs_iterator_t *ctx_p, /**< iterator context */
size_t size) /**< size to skip */
{
if (size)
{
rcs_iterator_access (ctx_p, NULL, size, RCS_ITERATOR_ACCESS_SKIP);
}
} /* rcs_iterator_skip */
/**
* Reset the iterator, so that it points to the beginning of the record.
*/
void
rcs_iterator_reset (rcs_iterator_t *ctx_p) /**< iterator context */
{
ctx_p->current_pos_p = ctx_p->record_start_p;
ctx_p->current_offset = 0;
} /* rcs_iterator_reset */
/**
* Check if the end of the record was reached.
*
* @return true if the whole record was iterated
* false otherwise
*/
bool
rcs_iterator_finished (rcs_iterator_t *ctx_p) /**< iterator context */
{
return ctx_p->current_pos_p == NULL;
} /* rcs_iterator_finished */