一个类似windows

源代码在线查看: object.c

软件大小: 26417 K
上传用户: hudun2006
关键词: windows
下载地址: 免注册下载 普通下载 VIP

相关代码

				/*
				 * User object handling.
				 * Copyright (c) 1998 New Generation Software (NGS) Oy
				 *
				 * Author: Markku Rossi 
				 */
				
				/*
				 * 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/ksrc/object.c,v $
				 * $Id: object.c 21681 2006-04-21 15:00:24Z peterw $
				 */
				
				#include "ntddk.h"
				#include "jsint.h"
				#include "jsconfig.h"
				
				/*
				 * Types and definitions.
				 */
				
				#define HASH_SIZE 128
				
				/*
				 * Prototypes for static functions.
				 */
				
				static void hash_create (JSVirtualMachine *vm, JSObject *obj);
				
				static void hash_insert (JSVirtualMachine *vm, JSObject *obj, const char *name,
							 unsigned int name_len, int pos);
				
				static void hash_delete (JSVirtualMachine *vm, JSObject *obj, const char *name,
							 unsigned int name_len);
				
				static int hash_lookup (JSObject *obj, char *name, unsigned int name_len);
				
				
				/*
				 * Global functions.
				 */
				
				JSObject *
				js_vm_object_new (JSVirtualMachine *vm)
				{
				  JSObject *obj;
				
				  obj = js_vm_alloc (vm, sizeof (*obj));
				  obj->hash = NULL;
				  obj->num_props = 0;
				  obj->props = NULL;
				
				  return obj;
				}
				
				
				void
				js_vm_object_mark (JSObject *obj)
				{
				  int i;
				  unsigned int num_objects;
				
				  if (obj == NULL)
				    return;
				
				 tail_recursive:
				
				  if (!js_vm_mark_ptr (obj))
				    /* This object has already been marked.  Nothing to do here. */
				    return;
				
				  js_vm_mark_ptr (obj->props);
				
				  /* Mark property hash. */
				  if (obj->hash)
				    {
				      JSObjectPropHashBucket *b;
				      int i;
				
				      js_vm_mark_ptr (obj->hash);
				      js_vm_mark_ptr (obj->hash_lengths);
				
				      for (i = 0; i < HASH_SIZE; i++)
					for (b = obj->hash[i]; b; b = b->next)
					  {
					    js_vm_mark_ptr (b);
					    js_vm_mark_ptr (b->data);
					  }
				    }
				
				  /* Mark all non-object properties. */
				  num_objects = 0;
				  for (i = 0; i < obj->num_props; i++)
				    {
				      if (obj->props[i].value.type == JS_OBJECT)
					{
					  if (!js_vm_is_marked_ptr (obj->props[i].value.u.vobject))
					    num_objects++;
					}
				      else
					js_vm_mark (&obj->props[i].value);
				    }
				
				  /* And finally, mark all objects we have left. */
				  if (num_objects > 0)
				    {
				      /* Find the objects. */
				      for (i = 0; i < obj->num_props; i++)
					if (obj->props[i].value.type == JS_OBJECT
					    && !js_vm_is_marked_ptr (obj->props[i].value.u.vobject))
					  {
					    if (num_objects == 1)
					      {
						/*
						 * Hahaa, this is the only non-marked object.  We can
						 * do a tail-recursion optimization.
						 */
						obj = obj->props[i].value.u.vobject;
						goto tail_recursive;
					      }
				
					    /* Just mark it. */
					    js_vm_mark (&obj->props[i].value);
					  }
				    }
				}
				
				
				int
				js_vm_object_load_property (JSVirtualMachine *vm, JSObject *obj,
							    JSSymbol prop, JSNode *value_return)
				{
				  unsigned int ui;
				  JSSymbol link_sym = vm->syms.s___proto__;
				  JSObject *link_obj = NULL;
				
				follow_link:
				
				  /* Check if we know this property. */
				  for (ui = 0; ui < obj->num_props; ui++)
				    if (obj->props[ui].name == prop)
				      {
					JS_COPY (value_return, &obj->props[ui].value);
					return JS_PROPERTY_FOUND;
				      }
				    else if (obj->props[ui].name == link_sym
					     && obj->props[ui].value.type == JS_OBJECT)
				      link_obj = obj->props[ui].value.u.vobject;
				
				  /* Undefined so far. */
				  if (link_obj)
				    {
				      /* Follow the link. */
				      obj = link_obj;
				
				      link_obj = NULL;
				      goto follow_link;
				    }
				
				  /* Undefined.  Make it undef. */
				  value_return->type = JS_UNDEFINED;
				  return JS_PROPERTY_UNKNOWN;
				}
				
				
				void
				js_vm_object_store_property (JSVirtualMachine *vm, JSObject *obj,
							     JSSymbol prop, JSNode *val)
				{
				  unsigned int ui;
				  JSSymbol free_slot = JS_SYMBOL_NULL;
				
				  /* Check if we already know this property. */
				  for (ui = 0; ui < obj->num_props; ui++)
				    if (obj->props[ui].name == prop)
				      {
					JS_COPY (&obj->props[ui].value, val);
					return;
				      }
				    else if (obj->props[ui].name == JS_SYMBOL_NULL)
				      free_slot = ui;
				
				  /* Must create a new property. */
				
				  if (free_slot == JS_SYMBOL_NULL)
				    {
				      /* Expand our array of properties. */
				      obj->props = js_vm_realloc (vm, obj->props,
								  (obj->num_props + 1) * sizeof (JSProperty));
				      free_slot = obj->num_props++;
				    }
				
				  obj->props[free_slot].name = prop;
				  obj->props[free_slot].attributes = 0;
				  JS_COPY (&obj->props[free_slot].value, val);
				
				  /* Insert it to the hash (if the hash has been created). */
				  if (obj->hash)
				    {
				      const char *name;
				
				      name = js_vm_symname (vm, prop);
				      hash_insert (vm, obj, name, strlen (name), free_slot);
				    }
				}
				
				
				void
				js_vm_object_delete_property (JSVirtualMachine *vm, JSObject *obj,
							      JSSymbol prop)
				{
				  unsigned int ui;
				
				  /* Check if we already know this property. */
				  for (ui = 0; ui < obj->num_props; ui++)
				    if (obj->props[ui].name == prop)
				      {
					/* Found, remove it from our list of properties. */
					obj->props[ui].name = JS_SYMBOL_NULL;
					obj->props[ui].value.type = JS_UNDEFINED;
				
					/* Remove its name from the hash (if present). */
					if (obj->hash)
					  {
					    const char *name = js_vm_symname (vm, prop);
					    hash_delete (vm, obj, name, strlen (name));
					  }
				
					/* All done here. */
					return;
				      }
				}
				
				
				void
				js_vm_object_load_array (JSVirtualMachine *vm, JSObject *obj, JSNode *sel,
							 JSNode *value_return)
				{
				  if (sel->type == JS_INTEGER)
				    {
				      if (sel->u.vinteger < 0 || sel->u.vinteger >= obj->num_props)
					value_return->type = JS_UNDEFINED;
				      else
					JS_COPY (value_return, &obj->props[sel->u.vinteger].value);
				    }
				  else if (sel->type == JS_STRING)
				    {
				      int pos;
				
				      if (obj->hash == NULL)
					hash_create (vm, obj);
				
				      pos = hash_lookup (obj, (char *) sel->u.vstring->data,
							 sel->u.vstring->len);
				      if (pos < 0)
					value_return->type = JS_UNDEFINED;
				      else
					JS_COPY (value_return, &obj->props[pos].value);
				    }
				  else
				    {
				      sprintf (vm->error, "load_property: illegal array index");
				      js_vm_error (vm);
				    }
				}
				
				
				void
				js_vm_object_store_array (JSVirtualMachine *vm, JSObject *obj, JSNode *sel,
							  JSNode *value)
				{
				  if (sel->type == JS_INTEGER)
				    {
				      if (sel->u.vinteger < 0)
					{
					  sprintf (vm->error, "store_array: array index can't be nagative");
					  js_vm_error (vm);
					}
				      if (sel->u.vinteger >= obj->num_props)
					{
					  /* Expand properties. */
					  obj->props = js_vm_realloc (vm, obj->props,
								      (sel->u.vinteger + 1)
								      * sizeof (JSProperty));
				
					  /* Init the possible gap. */
					  for (; obj->num_props u.vinteger; obj->num_props++)
					    {
					      obj->props[obj->num_props].name = 0;
					      obj->props[obj->num_props].attributes = 0;
					      obj->props[obj->num_props].value.type = JS_UNDEFINED;
					    }
					}
				
				      JS_COPY (&obj->props[sel->u.vinteger].value, value);
				    }
				  else if (sel->type == JS_STRING)
				    {
				      int pos;
				
				      if (obj->hash == NULL)
					hash_create (vm, obj);
				
				      pos = hash_lookup (obj, (char *) sel->u.vstring->data,
							 sel->u.vstring->len);
				      if (pos < 0)
					{
					  /* It is undefined, define it. */
					  obj->props = js_vm_realloc (vm, obj->props,
								      (obj->num_props + 1)
								      * sizeof (JSProperty));
				
					  /*
					   * XXX if  is a valid symbol, intern it and set symbol's
					   * name below.
					   */
					  obj->props[obj->num_props].name = JS_SYMBOL_NULL;
					  obj->props[obj->num_props].attributes = 0;
					  JS_COPY (&obj->props[obj->num_props].value, value);
				
					  hash_insert (vm, obj, (char *) sel->u.vstring->data,
						       sel->u.vstring->len, obj->num_props);
				
					  obj->num_props++;
					}
				      else
					JS_COPY (&obj->props[pos].value, value);
				    }
				}
				
				
				void
				js_vm_object_delete_array (JSVirtualMachine *vm, JSObject *obj, JSNode *sel)
				{
				  if (sel->type == JS_INTEGER)
				    {
				      if (0 u.vinteger && sel->u.vinteger < obj->num_props)
					{
					  JSSymbol sym;
				
					  sym = obj->props[sel->u.vinteger].name;
					  obj->props[sel->u.vinteger].name = JS_SYMBOL_NULL;
					  obj->props[sel->u.vinteger].value.type = JS_UNDEFINED;
				
					  /* Remove its name from the hash (if present and it is not NULL). */
					  if (sym != JS_SYMBOL_NULL && obj->hash)
					    {
					      const char *name = js_vm_symname (vm, sym);
					      hash_delete (vm, obj, name, strlen (name));
					    }
					}
				    }
				  else if (sel->type == JS_STRING)
				    {
				      int pos;
				
				      if (obj->hash == NULL)
					hash_create (vm, obj);
				
				      pos = hash_lookup (obj, (char *) sel->u.vstring->data,
							 sel->u.vstring->len);
				      if (pos >= 0)
					{
					  /* Found it. */
					  obj->props[pos].name = JS_SYMBOL_NULL;
					  obj->props[pos].value.type = JS_UNDEFINED;
				
					  /* And, delete its name from the hash. */
					  hash_delete (vm, obj, (char *) sel->u.vstring->data,
						       sel->u.vstring->len);
					}
				    }
				  else
				    {
				      sprintf (vm->error, "delete_array: illegal array index");
				      js_vm_error (vm);
				    }
				}
				
				
				int
				js_vm_object_nth (JSVirtualMachine *vm, JSObject *obj, int nth,
						  JSNode *value_return)
				{
				  int i;
				  JSObjectPropHashBucket *b;
				
				  value_return->type = JS_UNDEFINED;
				
				  if (nth < 0)
				    return 0;
				
				  if (obj->hash == NULL)
				    hash_create (vm, obj);
				
				  for (i = 0; i < HASH_SIZE && nth >= obj->hash_lengths[i]; i++)
				    nth -= obj->hash_lengths[i];
				
				  if (i >= HASH_SIZE)
				    return 0;
				
				  /* The chain  is the correct one. */
				  for (b = obj->hash[i]; b && nth > 0; b = b->next, nth--)
				    ;
				  if (b == NULL)
				    {
				      char buf[512];
				
				      sprintf (buf,
					       "js_vm_object_nth(): chain didn't contain that many items%s",
					       JS_HOST_LINE_BREAK);
				      js_iostream_write (vm->s_stderr, buf, strlen (buf));
				      js_iostream_flush (vm->s_stderr);
				
				      abort ();
				    }
				
				  js_vm_make_string (vm, value_return, (char*)b->data, b->len);
				
				  return 1;
				}
				
				
				/*
				 * Static functions.
				 */
				
				static void
				hash_create (JSVirtualMachine *vm, JSObject *obj)
				{
				  int i;
				
				  obj->hash = js_vm_alloc (vm, HASH_SIZE * sizeof (JSObjectPropHashBucket *));
				  memset (obj->hash, 0, HASH_SIZE * sizeof (JSObjectPropHashBucket *));
				
				  obj->hash_lengths = js_vm_alloc (vm, HASH_SIZE * sizeof (unsigned int));
				  memset (obj->hash_lengths, 0, HASH_SIZE * sizeof (unsigned int));
				
				  /* Insert all known properties to the hash. */
				  for (i = 0; i < obj->num_props; i++)
				    if (obj->props[i].name != JS_SYMBOL_NULL)
				      {
					const char *name;
				
					name = js_vm_symname (vm, obj->props[i].name);
					hash_insert (vm, obj, name, strlen (name), i);
				      }
				}
				
				
				static void
				hash_insert (JSVirtualMachine *vm, JSObject *obj, const char *name,
					     unsigned int name_len, int pos)
				{
				  unsigned int hash;
				  JSObjectPropHashBucket *b;
				
				  hash = js_count_hash (name, name_len) % HASH_SIZE;
				  for (b = obj->hash[hash]; b; b = b->next)
				    if (b->len == name_len
					&& memcmp (b->data, name, name_len) == 0)
				      {
					/* Ok, we already have a bucket */
					b->value = pos;
					return;
				      }
				
				  /* Create a new bucket. */
				  b = js_vm_alloc (vm, sizeof (*b));
				  b->len = name_len;
				  b->data = js_vm_alloc (vm, b->len);
				  memcpy (b->data, name, b->len);
				
				  b->value = pos;
				
				  b->next = obj->hash[hash];
				  obj->hash[hash] = b;
				
				  obj->hash_lengths[hash]++;
				}
				
				
				static void
				hash_delete (JSVirtualMachine *vm, JSObject *obj, const char *name,
					     unsigned int name_len)
				{
				  unsigned int hash;
				  JSObjectPropHashBucket *b, *prev;
				
				  hash = js_count_hash (name, name_len) % HASH_SIZE;
				  for (prev = NULL, b = obj->hash[hash]; b; prev = b, b = b->next)
				    if (b->len == name_len
					&& memcmp (b->data, name, name_len) == 0)
				      {
					/* Ok, found it. */
					if (prev)
					  prev->next = b->next;
					else
					  obj->hash[hash] = b->next;
				
					obj->hash_lengths[hash]--;
				
					break;
				      }
				}
				
				
				static int
				hash_lookup (JSObject *obj, char *name, unsigned int name_len)
				{
				  unsigned int hash;
				  JSObjectPropHashBucket *b;
				
				  hash = js_count_hash (name, name_len) % HASH_SIZE;
				  for (b = obj->hash[hash]; b; b = b->next)
				    if (b->len == name_len
					&& memcmp (b->data, name, name_len) == 0)
				      return b->value;
				
				  return -1;
				}
							

相关资源