e576bb2002-10-11Martin Nilsson /* || 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.
2b888e2008-01-29Henrik Grubbström (Grubba) || $Id: array.h,v 1.72 2008/01/29 20:10:06 grubba Exp $
e576bb2002-10-11Martin Nilsson */
24ddc71998-03-28Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifndef ARRAY_H #define ARRAY_H
38ac332003-11-14Martin Stjernholm #include "svalue.h"
72389e2004-09-27Martin Stjernholm #include "dmalloc.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
3ca8cd2003-04-28Martin Stjernholm /* This debug tool writes out messages whenever arrays with unfinished * type fields are encountered. */
b3604d2003-04-27Martin Stjernholm /* #define TRACE_UNFINISHED_TYPE_FIELDS */
c3f3832004-10-17H. William Welliver III /** * A Pike array is represented as a 'struct array' with all the * needed svalues malloced in the same block. * * @see type_field */
5267b71995-08-09Fredrik Hübinette (Hubbe) struct array {
45637c2001-04-07Fredrik Hübinette (Hubbe)  PIKE_MEMORY_OBJECT_MEMBERS;
c3f3832004-10-17H. William Welliver III  struct array *next; /**< we need to keep track of all arrays */ struct array *prev; /**< Another pointer, so we don't have to search
5267b71995-08-09Fredrik Hübinette (Hubbe)  * when freeing arrays */
c3f3832004-10-17H. William Welliver III  INT32 size; /**< number of svalues in this array */ INT32 malloced_size; /**< number of svalues that can fit in this array */ TYPE_FIELD type_field;/**< A bitfield with one bit for each type of * data in this array. Bits can be set that don't exist in the array. type_field is
3ca8cd2003-04-28Martin Stjernholm  * initialized to BIT_MIXED|BIT_UNFINISHED for newly allocated * arrays so that they can be modified without having to update * this. It should be set accurately when that's done, though. */
c3f3832004-10-17H. William Welliver III  INT16 flags; /**< ARRAY_* flags */ struct svalue *item; /**< the array of svalues */
b99ff82001-06-07Fredrik Hübinette (Hubbe)  struct svalue real_item[1];
5267b71995-08-09Fredrik Hübinette (Hubbe) };
5f06241999-04-11Fredrik Hübinette (Hubbe) #define ARRAY_WEAK_FLAG 1 #define ARRAY_CYCLIC 2 #define ARRAY_LVALUE 4
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5272b22004-09-22Martin Stjernholm PMOD_EXPORT extern struct array empty_array, weak_empty_array;
cd451f2004-03-15Martin Stjernholm extern struct array *first_array;
e2d9e62000-06-10Martin Stjernholm extern struct array *gc_internal_array;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG)
aa366d1998-04-16Fredrik Hübinette (Hubbe) #define ITEM(X) (((struct array *)(debug_malloc_pass((X))))->item) #else
fc76951996-02-17Fredrik Hübinette (Hubbe) #define ITEM(X) ((X)->item)
aa366d1998-04-16Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  /* These are arguments for the function 'merge' which merges two sorted * set stored in arrays in the way you specify */
71f3a21998-11-22Fredrik Hübinette (Hubbe) #define PIKE_ARRAY_OP_A 1 #define PIKE_ARRAY_OP_SKIP_A 2 #define PIKE_ARRAY_OP_TAKE_A 3 #define PIKE_ARRAY_OP_B 4 #define PIKE_ARRAY_OP_SKIP_B 8 #define PIKE_ARRAY_OP_TAKE_B 12 #define PIKE_MINTERM(X,Y,Z) (((X)<<8)+((Y)<<4)+(Z))
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) 
c3f3832004-10-17H. William Welliver III /** * This macro frees one reference to the array V. If the reference * is the last reference to the array, it will free the memory used * by the array V. * @param V an array struct to be freed. */
4fab5f2004-04-18Martin Stjernholm #define free_array(V) do{ \ struct array *v_=(V); \ debug_malloc_touch(v_); \
31a8682004-09-27Martin Stjernholm  DO_IF_DEBUG ( \
dbcb292004-09-29Martin Stjernholm  DO_IF_PIKE_CLEANUP ( \ if (gc_external_refs_zapped) \ gc_check_zapped (v_, PIKE_T_ARRAY, __FILE__, __LINE__))); \
4fab5f2004-04-18Martin Stjernholm  if(!sub_ref(v_)) \ really_free_array(v_); \ }while(0)
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2a129b1996-03-24Fredrik Hübinette (Hubbe) #define allocate_array(X) low_allocate_array((X),0) #define allocate_array_no_init(X,Y) low_allocate_array((X),(Y))
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e4acf82001-04-30Martin Stjernholm typedef int (*cmpfun)(const struct svalue *, const struct svalue *);
5267b71995-08-09Fredrik Hübinette (Hubbe) typedef int (*short_cmpfun)(union anything *, union anything *); typedef short_cmpfun (*cmpfun_getter)(TYPE_T);
cde8152004-09-30Martin Stjernholm #define low_allocate_array(size, extra_space) \ dmalloc_touch (struct array *, \ real_allocate_array ((size), (extra_space)))
5267b71995-08-09Fredrik Hübinette (Hubbe) /* Prototypes begin here */
cde8152004-09-30Martin Stjernholm PMOD_EXPORT struct array *real_allocate_array(ptrdiff_t size, ptrdiff_t extra_space);
4ee9222000-12-13Fredrik Hübinette (Hubbe) PMOD_EXPORT void really_free_array(struct array *v);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void do_free_array(struct array *a);
be08a82001-06-06Martin Stjernholm PMOD_EXPORT struct array *array_set_flags(struct array *a, int flags);
6e4c642002-09-11Marcus Comstedt PMOD_EXPORT void array_index(struct svalue *s,struct array *v,INT32 ind);
bcd8012003-04-28Martin Stjernholm PMOD_EXPORT struct array *array_column (struct array *data, struct svalue *index, int destructive);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void simple_array_index_no_free(struct svalue *s,
61e9a01998-01-25Fredrik Hübinette (Hubbe)  struct array *a,struct svalue *ind);
6e4c642002-09-11Marcus Comstedt PMOD_EXPORT void array_free_index(struct array *v,INT32 ind);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void simple_set_index(struct array *a,struct svalue *ind,struct svalue *s);
6e4c642002-09-11Marcus Comstedt PMOD_EXPORT struct array *array_insert(struct array *v,struct svalue *s,INT32 ind);
b1a6582007-12-17Henrik Grubbström (Grubba) void o_append_array(INT32 args);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *resize_array(struct array *a, INT32 size);
84f8952000-08-16Henrik Grubbström (Grubba) PMOD_EXPORT struct array *array_shrink(struct array *v, ptrdiff_t size);
6e4c642002-09-11Marcus Comstedt PMOD_EXPORT struct array *array_remove(struct array *v,INT32 ind);
63540d2000-08-15Henrik Grubbström (Grubba) PMOD_EXPORT ptrdiff_t array_search(struct array *v, struct svalue *s, ptrdiff_t start);
6aa68b2000-08-15Henrik Grubbström (Grubba) PMOD_EXPORT struct array *slice_array(struct array *v, ptrdiff_t start, ptrdiff_t end); PMOD_EXPORT struct array *friendly_slice_array(struct array *v, ptrdiff_t start, ptrdiff_t end);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *copy_array(struct array *v); PMOD_EXPORT void check_array_for_destruct(struct array *v); PMOD_EXPORT INT32 array_find_destructed_object(struct array *v);
99946c1996-02-17Fredrik Hübinette (Hubbe) INT32 *get_order(struct array *v, cmpfun fun);
84387d2001-09-24Fredrik Hübinette (Hubbe) INLINE int set_svalue_cmpfun(const struct svalue *a, const struct svalue *b);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void sort_array_destructively(struct array *v);
cce18e2003-04-26Martin Stjernholm PMOD_EXPORT INT32 *stable_sort_array_destructively(struct array *v);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT INT32 *get_set_order(struct array *a); PMOD_EXPORT INT32 *get_switch_order(struct array *a); PMOD_EXPORT INT32 *get_alpha_order(struct array *a);
5267b71995-08-09Fredrik Hübinette (Hubbe) INT32 set_lookup(struct array *a, struct svalue *s); INT32 switch_lookup(struct array *a, struct svalue *s);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *order_array(struct array *v, INT32 *order); PMOD_EXPORT struct array *reorder_and_copy_array(struct array *v, INT32 *order);
f600d22004-05-14Martin Nilsson PMOD_EXPORT TYPE_FIELD array_fix_type_field(struct array *v);
d8946e2004-03-09Martin Nilsson #ifdef PIKE_DEBUG
ec0eea2006-07-05Martin Stjernholm PMOD_EXPORT void array_check_type_field(struct array *v);
d8946e2004-03-09Martin Nilsson #endif
4ee9222000-12-13Fredrik Hübinette (Hubbe) PMOD_EXPORT union anything *low_array_get_item_ptr(struct array *a,
5267b71995-08-09Fredrik Hübinette (Hubbe)  INT32 ind, TYPE_T t);
4ee9222000-12-13Fredrik Hübinette (Hubbe) PMOD_EXPORT union anything *array_get_item_ptr(struct array *a,
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct svalue *ind, TYPE_T t); INT32 * merge(struct array *a,struct array *b,INT32 opcode);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *array_zip(struct array *a, struct array *b,INT32 *zipper); PMOD_EXPORT struct array *add_arrays(struct svalue *argp, INT32 args); PMOD_EXPORT int array_equal_p(struct array *a, struct array *b, struct processing *p);
84387d2001-09-24Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array *b, INT32 op);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct array *b,INT32 op); PMOD_EXPORT struct array *merge_array_without_order(struct array *a,
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct array *b, INT32 op);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *subtract_arrays(struct array *a, struct array *b); PMOD_EXPORT struct array *and_arrays(struct array *a, struct array *b);
84387d2001-09-24Fredrik Hübinette (Hubbe) int array_is_constant(struct array *a, struct processing *p);
5267b71995-08-09Fredrik Hübinette (Hubbe) node *make_node_from_array(struct array *a);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void push_array_items(struct array *a);
5267b71995-08-09Fredrik Hübinette (Hubbe) void describe_array_low(struct array *a, struct processing *p, int indent);
d8946e2004-03-09Martin Nilsson #ifdef PIKE_DEBUG void simple_describe_array(struct array *a);
5267b71995-08-09Fredrik Hübinette (Hubbe) void describe_index(struct array *a, int e, struct processing *p, int indent);
d8946e2004-03-09Martin Nilsson #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) void describe_array(struct array *a,struct processing *p,int indent);
f31ced2000-12-16Marcus Comstedt PMOD_EXPORT struct array *aggregate_array(INT32 args);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *append_array(struct array *a, struct svalue *s); PMOD_EXPORT struct array *explode(struct pike_string *str,
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *del);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct pike_string *implode(struct array *a,struct pike_string *del);
9cc28d2004-05-28Henrik Grubbström (Grubba) PMOD_EXPORT struct array *copy_array_recursively(struct array *a, struct mapping *p);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void apply_array(struct array *a, INT32 args);
2b888e2008-01-29Henrik Grubbström (Grubba) PMOD_EXPORT struct array *reverse_array(struct array *a, int start, int end);
84387d2001-09-24Fredrik Hübinette (Hubbe) void array_replace(struct array *a,
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct svalue *from, struct svalue *to);
d8946e2004-03-09Martin Nilsson #ifdef PIKE_DEBUG
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void check_array(struct array *a);
be478c1997-08-30Henrik Grubbström (Grubba) void check_all_arrays(void);
d8946e2004-03-09Martin Nilsson #endif
c94c371996-03-28Fredrik Hübinette (Hubbe) void gc_mark_array_as_referenced(struct array *a);
1f21332000-07-28Fredrik Hübinette (Hubbe) void real_gc_cycle_check_array(struct array *a, int weak);
e2d9e62000-06-10Martin Stjernholm unsigned gc_touch_all_arrays(void);
be478c1997-08-30Henrik Grubbström (Grubba) void gc_check_all_arrays(void); void gc_mark_all_arrays(void);
e2d9e62000-06-10Martin Stjernholm void gc_cycle_check_all_arrays(void);
45d87e2000-07-18Martin Stjernholm void gc_zap_ext_weak_refs_in_arrays(void);
88cf4f2003-01-11Martin Stjernholm size_t gc_free_all_unreferenced_arrays(void);
d8946e2004-03-09Martin Nilsson #ifdef PIKE_DEBUG
c3c7031996-12-04Fredrik Hübinette (Hubbe) void debug_dump_type_field(TYPE_FIELD t); void debug_dump_array(struct array *a);
d8946e2004-03-09Martin Nilsson #endif
c3c7031996-12-04Fredrik Hübinette (Hubbe) void count_memory_in_arrays(INT32 *num_, INT32 *size_);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *explode_array(struct array *a, struct array *b); PMOD_EXPORT struct array *implode_array(struct array *a, struct array *b);
5267b71995-08-09Fredrik Hübinette (Hubbe) /* Prototypes end here */
be08a82001-06-06Martin Stjernholm #define array_get_flags(a) ((a)->flags)
45d87e2000-07-18Martin Stjernholm #define gc_cycle_check_array(X, WEAK) \ gc_cycle_enqueue((gc_cycle_check_cb *) real_gc_cycle_check_array, (X), (WEAK))
5267b71995-08-09Fredrik Hübinette (Hubbe) 
6773ec2001-02-03Martin Stjernholm 
67a0a32005-09-12H. William Welliver III /** Macros for aggregating results built on the stack into an array,
6773ec2001-02-03Martin Stjernholm  * while maintaining a bound on stack consumption. Use like this: * * check_stack(120); * BEGIN_AGGREGATE_ARRAY(estimated_size_of_final_array) { * for (...) { * ... stuff that produces a value on the stack ... * DO_AGGREGATE_ARRAY(120); * ... * } * } END_AGGREGATE_ARRAY; * * The array is left on top of the stack. */ #define BEGIN_AGGREGATE_ARRAY(estimated_size) do { \ struct svalue *base__; \ push_array(allocate_array_no_init(0, (estimated_size))); \
3f36092004-03-17Henrik Grubbström (Grubba)  base__ = Pike_sp; \
fb78842004-03-17Henrik Grubbström (Grubba)  base__[-1].u.array->type_field = (BIT_MIXED | BIT_UNFINISHED);
6773ec2001-02-03Martin Stjernholm  #define DO_AGGREGATE_ARRAY(max_keep_on_stack) \ do { \ ptrdiff_t diff__ = Pike_sp - base__; \ if (diff__ > (max_keep_on_stack)) { \ INT32 oldsize__ = base__[-1].u.array->size; \
b3604d2003-04-27Martin Stjernholm  ACCEPT_UNFINISHED_TYPE_FIELDS { \ base__[-1].u.array = \ resize_array(base__[-1].u.array, oldsize__ + diff__); \ } END_ACCEPT_UNFINISHED_TYPE_FIELDS; \
6773ec2001-02-03Martin Stjernholm  /* Unless the user does something, the type field will contain */ \ /* BIT_MIXED|BIT_UNFINISHED from the allocation above. */ \ MEMCPY((char *) (ITEM(base__[-1].u.array) + oldsize__), \ (char *) base__, diff__ * sizeof(struct svalue)); \ Pike_sp = base__; \ } \ } while (0) #define END_AGGREGATE_ARRAY \ DO_AGGREGATE_ARRAY(0); \
6284172004-03-17Henrik Grubbström (Grubba)  DO_IF_DEBUG(if (Pike_sp[-1].type != T_ARRAY) { \ Pike_fatal("Lost track of aggregated array.\n"); \ }); \ array_fix_type_field(Pike_sp[-1].u.array); \
6773ec2001-02-03Martin Stjernholm } while (0)
67a0a32005-09-12H. William Welliver III /**
caea1c2001-08-30Fredrik Hübinette (Hubbe)  * Extract an svalue from an array */ #define array_index_no_free(S,A,I) do { \ INT32 ind_=(I); \ struct array *v_=(A); \ DO_IF_DEBUG( \ if(ind_<0 || ind_>=v_->size) \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Illegal index in low level index routine.\n"); \
caea1c2001-08-30Fredrik Hübinette (Hubbe)  ) \ \ assign_svalue_no_free((S), ITEM(v_) + ind_); \ }while(0)
67a0a32005-09-12H. William Welliver III /**
c3f3832004-10-17H. William Welliver III  * Sets an index in an array. * * @param V the array to modify * @param I the index of the array to set * @param S the svalue to set
caea1c2001-08-30Fredrik Hübinette (Hubbe)  */
1ab4ac2008-01-26Martin Stjernholm #define array_set_index_no_free(V,I,S) do { \
caea1c2001-08-30Fredrik Hübinette (Hubbe)  struct array *v_=(V); \ INT32 index_=(I); \ struct svalue *s_=(S); \ \ DO_IF_DEBUG( \ if(index_<0 || index_>v_->size) \
b3604d2003-04-27Martin Stjernholm  Pike_fatal("Illegal index in low level array set routine.\n"); \
caea1c2001-08-30Fredrik Hübinette (Hubbe)  ) \ \ check_destructed(s_); \ \
b3604d2003-04-27Martin Stjernholm  v_->type_field |= 1 << s_->type; \
caea1c2001-08-30Fredrik Hübinette (Hubbe)  assign_svalue_no_free( ITEM(v_) + index_, s_); \
1ab4ac2008-01-26Martin Stjernholm }while(0) #define array_set_index(V,I,S) do { \ struct array *v_=(V); \ INT32 index_=(I); \ struct svalue *s_=(S); \ \ DO_IF_DEBUG( \ if(index_<0 || index_>v_->size) \ Pike_fatal("Illegal index in low level array set routine.\n"); \ ) \ \ check_destructed(s_); \ \ v_->type_field |= 1 << s_->type; \ assign_svalue( ITEM(v_) + index_, s_); \
caea1c2001-08-30Fredrik Hübinette (Hubbe) }while(0)
b3604d2003-04-27Martin Stjernholm #define array_fix_unfinished_type_field(A) do { \
3c759e2003-04-27Martin Stjernholm  struct array *a_ = (A); \
b3604d2003-04-27Martin Stjernholm  if (a_->type_field & BIT_UNFINISHED) { \
3c759e2003-04-27Martin Stjernholm  DO_IF_DEBUG (array_check_type_field (a_)); \ array_fix_type_field (a_); \ } \ } while (0)
caea1c2001-08-30Fredrik Hübinette (Hubbe) 
b3604d2003-04-27Martin Stjernholm #ifdef TRACE_UNFINISHED_TYPE_FIELDS /* Note: These macros don't support thread switches. */ extern PMOD_EXPORT int accept_unfinished_type_fields; PMOD_EXPORT void dont_accept_unfinished_type_fields (void *orig); #define ACCEPT_UNFINISHED_TYPE_FIELDS do { \ ONERROR autf_uwp_; \ int orig_autf_ = accept_unfinished_type_fields; \ accept_unfinished_type_fields++; \ SET_ONERROR (autf_uwp_, dont_accept_unfinished_type_fields, \ (void *) orig_autf_); \ do #define END_ACCEPT_UNFINISHED_TYPE_FIELDS \ while (0); \ accept_unfinished_type_fields = orig_autf_; \ UNSET_ONERROR (autf_uwp_); \ } while (0) #else #define ACCEPT_UNFINISHED_TYPE_FIELDS do #define END_ACCEPT_UNFINISHED_TYPE_FIELDS while (0) #endif
e2d9e62000-06-10Martin Stjernholm #endif /* ARRAY_H */