pike.git / src / builtin.cmod

version» Context lines:

pike.git/src/builtin.cmod:1:   /* -*- c -*-   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: builtin.cmod,v 1.169 2004/09/15 08:08:42 grubba Exp $ + || $Id: builtin.cmod,v 1.170 2004/09/17 15:07:43 grubba Exp $   */      #include "global.h"   #include "interpret.h"   #include "svalue.h"   #include "pike_macros.h"   #include "object.h"   #include "program.h"   #include "array.h"   #include "pike_error.h"
pike.git/src/builtin.cmod:3065:    *!    *! Linked list of values.    */   PIKECLASS List   {    CVAR struct list_node *head;    CVAR INT32 head_sentinel_refs;    CVAR struct list_node *tail; /* Always NULL. */    CVAR INT32 tail_sentinel_refs;    CVAR struct list_node *tail_pred; +  CVAR INT32 num_elems;      #define HEAD_SENTINEL(this) ((struct list_node *)(&this->head))   #define TAIL_SENTINEL(this) ((struct list_node *)(&this->tail))       /* Sentinel overlap description:    *    * List Head sentinel Tail sentinel    * head next    * head_sentinel_refs refs    * tail prev next
pike.git/src/builtin.cmod:3099:    * o Support for reverse(), filter() and map().    * o Initialization from array.    */       INIT    {    THIS->tail = NULL;    THIS->head = TAIL_SENTINEL(THIS);    THIS->tail_pred = HEAD_SENTINEL(THIS);    THIS->head_sentinel_refs = THIS->tail_sentinel_refs = 2; +  THIS->num_elems = 0;    }       EXIT    {    struct list_node *node = THIS->head;    struct list_node *next;    while ((next = node->next)) {   #ifdef PIKE_DEBUG    if (node->refs != 2) {    Pike_fatal("Unexpected number of references for node: %d\n",
pike.git/src/builtin.cmod:3175:    *!    *! @returns    *! Returns @expr{1@} if the list is empty,    *! and @expr{0@} (zero) if there are elements in the list.    */    PIKEFUN int(0..1) is_empty()    {    push_int(!THIS->head->next);    }    +  /*! @decl int(0..) _sizeof() +  *! +  *! Returns the number of elements in the list. +  */ +  PIKEFUN int(0..) _sizeof() +  flags ID_STATIC; +  { +  push_int(THIS->num_elems); +  } +     /*! @decl mixed head()    *!    *! Get the element at the head of the list.    *!    *! @throws    *! Throws an error if the list is empty.    *!    *! @seealso    *! @[is_empty()], @[tail()], @[pop()]    */
pike.git/src/builtin.cmod:3232:    */    PIKEFUN mixed pop()    {    if (THIS->head->next) {    push_svalue(&THIS->head->val);    if (THIS->head->refs == 2) {    unlink_list_node(THIS->head);    } else {    detach_list_node(THIS->head);    } +  THIS->num_elems--;    } else {    Pike_error("Empty list.\n");    }    }       /*! @decl void append(mixed ... values)    *!    *! Append @[values] to the end of the list.    *!    *! @seealso    *! @[insert()]    */    PIKEFUN void append(mixed ... values)    {    struct list_node *node = TAIL_SENTINEL(THIS);    while (args--) {    struct list_node *new = alloc_list_node();    new->val = *(--Pike_sp);    prepend_list_node(node, new);    free_list_node(node = new); -  +  THIS->num_elems++;    }    push_int(0);    }       /*! @decl void insert(mixed ... values)    *!    *! Insert @[values] at the front of the list.    *!    *! @seealso    *! @[append()]    */    PIKEFUN void insert(mixed ... values)    {    struct list_node *node = THIS->head;    while (args--) {    struct list_node *new = alloc_list_node();    new->val = *(--Pike_sp);    prepend_list_node(node, new);    free_list_node(node = new); -  +  THIS->num_elems++;    }    push_int(0);    }       /*! @decl void create(mixed ... values)    *!    *! Create a new @[List], and initialize it with @[values].    *!    *! @fixme    *! Ought to reset the @[List] if called multiple times.
pike.git/src/builtin.cmod:3304:    program_flags PROGRAM_USES_PARENT;    flags ID_STATIC;    {    CVAR struct list_node *cur;    CVAR INT32 ind; /* Not meaningful, but requred by the API. */       /* NOTE: cur may never refer to an unlinked node.    * cur may however refer to a detached node, or to sentinels.    */    -  INIT +  static struct List_struct *List__get_iterator_find_parent()    {    struct external_variable_context loc; -  struct List_struct *parent; +     -  /* Find our parent. */ +     loc.o = Pike_fp->current_object;    loc.parent_identifier = Pike_fp->fun;    loc.inherit = INHERIT_FROM_INT(loc.o->prog, loc.parent_identifier);    find_external_context(&loc, 1); -  parent = (struct List_struct *)(loc.o->storage + +  return (struct List_struct *)(loc.o->storage +    loc.inherit->storage_offset); -  add_ref(THIS->cur = parent->head); +  } +  +  INIT +  { +  add_ref(THIS->cur = List__get_iterator_find_parent()->head);    THIS->ind = 0;    }       EXIT    {    if (THIS->cur) {    free_list_node(THIS->cur);    THIS->cur = NULL;    }    }
pike.git/src/builtin.cmod:3607:    {    struct list_node *new;    if (!THIS->cur->prev) {    Pike_error("Attempt to insert before the start sentinel.\n");    }    new = alloc_list_node();    assign_svalue_no_free(&new->val, val);    prepend_list_node(THIS->cur, new);    free_list_node(THIS->cur);    THIS->cur = new; +  List__get_iterator_find_parent()->num_elems++;    pop_n_elems(args);    push_int(0);    }       /*! @decl void append(mixed val)    *!    *! Append @[val] after the current position.    *!    *! @seealso    *! @[insert()], @[delete()], @[set()]
pike.git/src/builtin.cmod:3628:    PIKEFUN void append(mixed val)    {    struct list_node *new;    if (!THIS->cur->next) {    Pike_error("Attempt to append after the end sentinel.\n");    }    new = alloc_list_node();    assign_svalue_no_free(&new->val, val);    append_list_node(THIS->cur, new);    free_list_node(new); +  List__get_iterator_find_parent()->num_elems++;    pop_n_elems(args);    push_int(0);    }       /*! @decl void delete()    *!    *! Delete the current node.    *!    *! The current position will advance to the next node.    *! This function thus performes the reverse operation
pike.git/src/builtin.cmod:3650:    *! @seealso    *! @[insert()], @[append()], @[set()]    */    PIKEFUN void delete()    {    struct list_node *next;    if (!(next = THIS->cur->next) || !THIS->cur->prev) {    Pike_error("Attempt to delete a sentinel.\n");    }    add_ref(next); +  if (next->prev == THIS->cur) {    if (THIS->cur->refs == 3) {    unlink_list_node(THIS->cur);    } else {    /* There's some other iterator holding references to this node. */    detach_list_node(THIS->cur);    } -  +  List__get_iterator_find_parent()->num_elems--; +  }    free_list_node(THIS->cur);    THIS->cur = next;    pop_n_elems(args);    push_int(0);    }       /*! @decl void set(mixed val)    *!    *! Set the value of the current position to @[val].    *!