📄 b_array.c
字号:
/*
* The builtin Array object.
* Copyright (c) 1998 New Generation Software (NGS) Oy
*
* Author: Markku Rossi <mtr@ngs.fi>
*/
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
/*
* $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/src/b_array.c,v $
* $Id: b_array.c 21681 2006-04-21 15:00:24Z peterw $
*/
/*
* Mehtods:
*
* concat (array) => array
* join ([glue]) => string
* pop () => last_element
* push (any...) => last_element_added
* reverse ()
* shift () => first_element
* slice (start, end) => array
* splice (index, how_many[, any...]) => array
* sort ([sort_function])
* toString () => string
* unshift (any...) => length_of_the_array
*
* Properties:
*
* length
*/
#include "jsint.h"
#include "mrgsort.h"
/*
* Types and definitions.
*/
/* Class context. */
struct array_ctx_st
{
JSSymbol s_concat;
JSSymbol s_join;
JSSymbol s_pop;
JSSymbol s_push;
JSSymbol s_reverse;
JSSymbol s_shift;
JSSymbol s_slice;
JSSymbol s_splice;
JSSymbol s_sort;
JSSymbol s_unshift;
JSSymbol s_length;
};
typedef struct array_ctx_st ArrayCtx;
/* Context for array sorts with JavaScript functions. */
struct array_sort_ctx_st
{
JSVirtualMachine *vm;
JSNode *func;
JSNode argv[3];
};
typedef struct array_sort_ctx_st ArraySortCtx;
/*
* Prototypes for static functions.
*/
static void new_proc (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
JSNode *args, JSNode *result_return);
/*
* Static functions.
*/
static int
sort_default_cmp_func (const void *aptr, const void *bptr, void *context)
{
JSVirtualMachine *vm = context;
const JSNode *a = aptr;
const JSNode *b = bptr;
JSNode astr, bstr;
if (a->type == JS_UNDEFINED)
return 1;
if (b->type == JS_UNDEFINED)
return -1;
js_vm_to_string (vm, a, &astr);
js_vm_to_string (vm, b, &bstr);
return js_compare_strings (&astr, &bstr);
}
static int
sort_js_cmp_func (const void *aptr, const void *bptr, void *context)
{
ArraySortCtx *ctx = context;
const JSNode *a = aptr;
const JSNode *b = bptr;
/*
* Finalize the argument array. The argumnet count has already been set.
* when the context were initialized.
*/
JS_COPY (&ctx->argv[1], a);
JS_COPY (&ctx->argv[2], b);
/* Call the function. */
if (!js_vm_apply (ctx->vm, NULL, ctx->func, 3, ctx->argv))
/* Raise an error. */
js_vm_error (ctx->vm);
/* Fetch the return value. */
if (ctx->vm->exec_result.type != JS_INTEGER)
{
sprintf (ctx->vm->error,
"Array.sort(): comparison function didn't return integer");
js_vm_error (ctx->vm);
}
return ctx->vm->exec_result.u.vinteger;
}
/* Global method proc. */
static void
global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context, JSNode *result_return,
JSNode *args)
{
/* This does exactly the same as the new_proc. */
new_proc (vm, builtin_info, args, result_return);
}
/* Method proc. */
static int
method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context, JSSymbol method, JSNode *result_return,
JSNode *args)
{
ArrayCtx *ctx = builtin_info->obj_context;
JSNode *n = instance_context;
int i;
/* XXX 15.7.4.3 toSource(). */
/* Handle static methods here. */
if (instance_context == NULL)
{
if (method == vm->syms.s_toString)
js_vm_make_static_string (vm, result_return, "Array", 5);
/* ************************************************************ */
else
return JS_PROPERTY_UNKNOWN;
return JS_PROPERTY_FOUND;
}
/* Handle the instance methods. */
/* Set the default result type. */
result_return->type = JS_UNDEFINED;
if (method == ctx->s_concat)
{
int nlen;
int pos;
/* Count the new len; */
nlen = n->u.varray->length;
for (i = 0; i < args->u.vinteger; i++)
{
if (args[i + 1].type != JS_ARRAY)
goto argument_error;
nlen += args[i + 1].u.varray->length;
}
js_vm_make_array (vm, result_return, nlen);
/* Insert the items. */
memcpy (result_return->u.varray->data, n->u.varray->data,
n->u.varray->length * sizeof (JSNode));
pos = n->u.varray->length;
for (i = 0; i < args->u.vinteger; i++)
{
memcpy (&result_return->u.varray->data[pos],
args[i + 1].u.varray->data,
args[i + 1].u.varray->length * sizeof (JSNode));
pos += args[i + 1].u.varray->length;
}
}
/* ********************************************************************** */
else if (method == ctx->s_join || method == vm->syms.s_toString)
{
char *glue = NULL;
if (method == vm->syms.s_toString)
{
if (args->u.vinteger != 0)
goto argument_error;
}
else
{
if (args->u.vinteger == 0)
;
else if (args->u.vinteger == 1)
{
JSNode glue_result;
js_vm_to_string (vm, &args[1], &glue_result);
glue = js_string_to_c_string (vm, &glue_result);
}
else
goto argument_error;
}
/* Ok, ready to run. */
if (n->u.varray->length == 0)
js_vm_make_static_string (vm, result_return, "", 0);
else
{
int len;
int glue_len = glue ? strlen (glue) : 1;
/* Estimate the result length. */
len = (n->u.varray->length * 5
+ (n->u.varray->length - 1) * glue_len);
js_vm_make_string (vm, result_return, NULL, len);
result_return->u.vstring->len = 0;
/* Do the join. */
for (i = 0; i < n->u.varray->length; i++)
{
JSNode sitem;
int delta;
js_vm_to_string (vm, &n->u.varray->data[i], &sitem);
delta = sitem.u.vstring->len;
if (i + 1 < n->u.varray->length)
delta += glue_len;
result_return->u.vstring->data
= js_vm_realloc (vm, result_return->u.vstring->data,
result_return->u.vstring->len + delta);
memcpy (result_return->u.vstring->data
+ result_return->u.vstring->len,
sitem.u.vstring->data,
sitem.u.vstring->len);
result_return->u.vstring->len += sitem.u.vstring->len;
if (i + 1 < n->u.varray->length)
{
if (glue)
{
memcpy (result_return->u.vstring->data
+ result_return->u.vstring->len,
glue, glue_len);
result_return->u.vstring->len += glue_len;
}
else
result_return->u.vstring->data
[result_return->u.vstring->len++] = ',';
}
}
}
if (glue)
js_free (glue);
}
/* ********************************************************************** */
else if (method == ctx->s_pop)
{
if (args->u.vinteger != 0)
goto argument_error;
if (n->u.varray->length == 0)
result_return->type = JS_UNDEFINED;
else
{
JS_COPY (result_return, &n->u.varray->data[n->u.varray->length - 1]);
n->u.varray->length--;
}
}
/* ********************************************************************** */
else if (method == ctx->s_push)
{
int old_len;
if (args->u.vinteger == 0)
goto argument_error;
old_len = n->u.varray->length;
js_vm_expand_array (vm, n, n->u.varray->length + args->u.vinteger);
for (i = 0; i < args->u.vinteger; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -