Main Page | Class List | Directories | File List | Class Members | File Members

array.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: array.h,v 1.67 2004/10/18 00:42:36 bill Exp $
00006 */
00007 
00008 #ifndef ARRAY_H
00009 #define ARRAY_H
00010 
00011 #include "svalue.h"
00012 #include "dmalloc.h"
00013 
00014 /* This debug tool writes out messages whenever arrays with unfinished
00015  * type fields are encountered. */
00016 /* #define TRACE_UNFINISHED_TYPE_FIELDS */
00017 
00024 struct array
00025 {
00026   PIKE_MEMORY_OBJECT_MEMBERS;
00027 
00028   struct array *next;   
00029   struct array *prev;   
00031   INT32 size;           
00032   INT32 malloced_size;  
00033   TYPE_FIELD type_field;
00039   INT16 flags;          
00040   struct svalue *item;  
00041   struct svalue real_item[1];
00042 };
00043 
00044 #define ARRAY_WEAK_FLAG 1
00045 #define ARRAY_CYCLIC 2
00046 #define ARRAY_LVALUE 4
00047 
00048 PMOD_EXPORT extern struct array empty_array, weak_empty_array;
00049 extern struct array *first_array;
00050 extern struct array *gc_internal_array;
00051 
00052 #if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG)
00053 #define ITEM(X) (((struct array *)(debug_malloc_pass((X))))->item)
00054 #else
00055 #define ITEM(X) ((X)->item)
00056 #endif
00057 
00058 /* These are arguments for the function 'merge' which merges two sorted
00059  * set stored in arrays in the way you specify
00060  */
00061 #define PIKE_ARRAY_OP_A 1
00062 #define PIKE_ARRAY_OP_SKIP_A 2
00063 #define PIKE_ARRAY_OP_TAKE_A 3
00064 #define PIKE_ARRAY_OP_B 4
00065 #define PIKE_ARRAY_OP_SKIP_B 8
00066 #define PIKE_ARRAY_OP_TAKE_B 12
00067 #define PIKE_MINTERM(X,Y,Z) (((X)<<8)+((Y)<<4)+(Z))
00068 
00069 #define PIKE_ARRAY_OP_AND PIKE_MINTERM(PIKE_ARRAY_OP_SKIP_A,PIKE_ARRAY_OP_SKIP_A | PIKE_ARRAY_OP_TAKE_B,PIKE_ARRAY_OP_SKIP_B)
00070 #define PIKE_ARRAY_OP_AND_LEFT PIKE_MINTERM(PIKE_ARRAY_OP_SKIP_A,PIKE_ARRAY_OP_SKIP_B | PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_B)
00071 #define PIKE_ARRAY_OP_OR  PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A | PIKE_ARRAY_OP_TAKE_B,PIKE_ARRAY_OP_TAKE_B)
00072 #define PIKE_ARRAY_OP_OR_LEFT  PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_B | PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_TAKE_B)
00073 #define PIKE_ARRAY_OP_XOR PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A | PIKE_ARRAY_OP_SKIP_B,PIKE_ARRAY_OP_TAKE_B)
00074 #define PIKE_ARRAY_OP_ADD PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_TAKE_A | PIKE_ARRAY_OP_TAKE_B ,PIKE_ARRAY_OP_TAKE_B)
00075 #define PIKE_ARRAY_OP_SUB PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A ,PIKE_ARRAY_OP_SKIP_B)
00076 
00083 #define free_array(V) do{                                               \
00084     struct array *v_=(V);                                               \
00085     debug_malloc_touch(v_);                                             \
00086     DO_IF_DEBUG (                                                       \
00087       DO_IF_PIKE_CLEANUP (                                              \
00088         if (gc_external_refs_zapped)                                    \
00089           gc_check_zapped (v_, PIKE_T_ARRAY, __FILE__, __LINE__)));     \
00090     if(!sub_ref(v_))                                                    \
00091       really_free_array(v_);                                            \
00092   }while(0)
00093 
00094 #define allocate_array(X) low_allocate_array((X),0)
00095 #define allocate_array_no_init(X,Y) low_allocate_array((X),(Y))
00096 
00097 typedef int (*cmpfun)(const struct svalue *, const struct svalue *);
00098 typedef int (*short_cmpfun)(union anything *, union anything *);
00099 typedef short_cmpfun (*cmpfun_getter)(TYPE_T);
00100 
00101 
00102 #define low_allocate_array(size, extra_space)                           \
00103   dmalloc_touch (struct array *,                                        \
00104                  real_allocate_array ((size), (extra_space)))
00105 
00106 /* Prototypes begin here */
00107 PMOD_EXPORT struct array *real_allocate_array(ptrdiff_t size, ptrdiff_t extra_space);
00108 PMOD_EXPORT void really_free_array(struct array *v);
00109 PMOD_EXPORT void do_free_array(struct array *a);
00110 PMOD_EXPORT struct array *array_set_flags(struct array *a, int flags);
00111 PMOD_EXPORT void array_index(struct svalue *s,struct array *v,INT32 ind);
00112 PMOD_EXPORT struct array *array_column (struct array *data, struct svalue *index,
00113                                         int destructive);
00114 PMOD_EXPORT void simple_array_index_no_free(struct svalue *s,
00115                                 struct array *a,struct svalue *ind);
00116 PMOD_EXPORT void array_free_index(struct array *v,INT32 ind);
00117 PMOD_EXPORT void simple_set_index(struct array *a,struct svalue *ind,struct svalue *s);
00118 PMOD_EXPORT struct array *array_insert(struct array *v,struct svalue *s,INT32 ind);
00119 PMOD_EXPORT struct array *resize_array(struct array *a, INT32 size);
00120 PMOD_EXPORT struct array *array_shrink(struct array *v, ptrdiff_t size);
00121 PMOD_EXPORT struct array *array_remove(struct array *v,INT32 ind);
00122 PMOD_EXPORT ptrdiff_t array_search(struct array *v, struct svalue *s,
00123                                    ptrdiff_t start);
00124 PMOD_EXPORT struct array *slice_array(struct array *v, ptrdiff_t start,
00125                                       ptrdiff_t end);
00126 PMOD_EXPORT struct array *friendly_slice_array(struct array *v,
00127                                                ptrdiff_t start,
00128                                                ptrdiff_t end);
00129 PMOD_EXPORT struct array *copy_array(struct array *v);
00130 PMOD_EXPORT void check_array_for_destruct(struct array *v);
00131 PMOD_EXPORT INT32 array_find_destructed_object(struct array *v);
00132 INT32 *get_order(struct array *v, cmpfun fun);
00133 INLINE int set_svalue_cmpfun(const struct svalue *a, const struct svalue *b);
00134 PMOD_EXPORT void sort_array_destructively(struct array *v);
00135 PMOD_EXPORT INT32 *stable_sort_array_destructively(struct array *v);
00136 PMOD_EXPORT INT32 *get_set_order(struct array *a);
00137 PMOD_EXPORT INT32 *get_switch_order(struct array *a);
00138 PMOD_EXPORT INT32 *get_alpha_order(struct array *a);
00139 INT32 set_lookup(struct array *a, struct svalue *s);
00140 INT32 switch_lookup(struct array *a, struct svalue *s);
00141 PMOD_EXPORT struct array *order_array(struct array *v, INT32 *order);
00142 PMOD_EXPORT struct array *reorder_and_copy_array(struct array *v, INT32 *order);
00143 PMOD_EXPORT TYPE_FIELD array_fix_type_field(struct array *v);
00144 #ifdef PIKE_DEBUG
00145 void array_check_type_field(struct array *v);
00146 #endif
00147 PMOD_EXPORT union anything *low_array_get_item_ptr(struct array *a,
00148                                        INT32 ind,
00149                                        TYPE_T t);
00150 PMOD_EXPORT union anything *array_get_item_ptr(struct array *a,
00151                                    struct svalue *ind,
00152                                    TYPE_T t);
00153 INT32 * merge(struct array *a,struct array *b,INT32 opcode);
00154 PMOD_EXPORT struct array *array_zip(struct array *a, struct array *b,INT32 *zipper);
00155 PMOD_EXPORT struct array *add_arrays(struct svalue *argp, INT32 args);
00156 PMOD_EXPORT int array_equal_p(struct array *a, struct array *b, struct processing *p);
00157 PMOD_EXPORT struct array *merge_array_with_order(struct array *a,
00158                                                  struct array *b, INT32 op);
00159 PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct array *b,INT32 op);
00160 PMOD_EXPORT struct array *merge_array_without_order(struct array *a,
00161                                         struct array *b,
00162                                         INT32 op);
00163 PMOD_EXPORT struct array *subtract_arrays(struct array *a, struct array *b);
00164 PMOD_EXPORT struct array *and_arrays(struct array *a, struct array *b);
00165 int array_is_constant(struct array *a,
00166                       struct processing *p);
00167 node *make_node_from_array(struct array *a);
00168 PMOD_EXPORT void push_array_items(struct array *a);
00169 void describe_array_low(struct array *a, struct processing *p, int indent);
00170 #ifdef PIKE_DEBUG
00171 void simple_describe_array(struct array *a);
00172 void describe_index(struct array *a,
00173                     int e,
00174                     struct processing *p,
00175                     int indent);
00176 #endif
00177 void describe_array(struct array *a,struct processing *p,int indent);
00178 PMOD_EXPORT struct array *aggregate_array(INT32 args);
00179 PMOD_EXPORT struct array *append_array(struct array *a, struct svalue *s);
00180 PMOD_EXPORT struct array *explode(struct pike_string *str,
00181                        struct pike_string *del);
00182 PMOD_EXPORT struct pike_string *implode(struct array *a,struct pike_string *del);
00183 PMOD_EXPORT struct array *copy_array_recursively(struct array *a,
00184                                                  struct mapping *p);
00185 PMOD_EXPORT void apply_array(struct array *a, INT32 args);
00186 PMOD_EXPORT struct array *reverse_array(struct array *a);
00187 void array_replace(struct array *a,
00188                    struct svalue *from,
00189                    struct svalue *to);
00190 #ifdef PIKE_DEBUG
00191 PMOD_EXPORT void check_array(struct array *a);
00192 void check_all_arrays(void);
00193 #endif
00194 void gc_mark_array_as_referenced(struct array *a);
00195 void real_gc_cycle_check_array(struct array *a, int weak);
00196 unsigned gc_touch_all_arrays(void);
00197 void gc_check_all_arrays(void);
00198 void gc_mark_all_arrays(void);
00199 void gc_cycle_check_all_arrays(void);
00200 void gc_zap_ext_weak_refs_in_arrays(void);
00201 size_t gc_free_all_unreferenced_arrays(void);
00202 #ifdef PIKE_DEBUG
00203 void debug_dump_type_field(TYPE_FIELD t);
00204 void debug_dump_array(struct array *a);
00205 #endif
00206 void count_memory_in_arrays(INT32 *num_, INT32 *size_);
00207 PMOD_EXPORT struct array *explode_array(struct array *a, struct array *b);
00208 PMOD_EXPORT struct array *implode_array(struct array *a, struct array *b);
00209 /* Prototypes end here */
00210 
00211 #define array_get_flags(a) ((a)->flags)
00212 
00213 #define gc_cycle_check_array(X, WEAK) \
00214   gc_cycle_enqueue((gc_cycle_check_cb *) real_gc_cycle_check_array, (X), (WEAK))
00215 
00216 
00217 /* Macros for aggregating results built on the stack into an array,
00218  * while maintaining a bound on stack consumption. Use like this:
00219  *
00220  * check_stack(120);
00221  * BEGIN_AGGREGATE_ARRAY(estimated_size_of_final_array) {
00222  *   for (...) {
00223  *     ... stuff that produces a value on the stack ...
00224  *     DO_AGGREGATE_ARRAY(120);
00225  *     ...
00226  *   }
00227  * } END_AGGREGATE_ARRAY;
00228  *
00229  * The array is left on top of the stack.
00230  */
00231 
00232 #define BEGIN_AGGREGATE_ARRAY(estimated_size) do {                      \
00233   struct svalue *base__;                                                \
00234   push_array(allocate_array_no_init(0, (estimated_size)));              \
00235   base__ = Pike_sp;                                                     \
00236   base__[-1].u.array->type_field = (BIT_MIXED | BIT_UNFINISHED);
00237 
00238 #define DO_AGGREGATE_ARRAY(max_keep_on_stack)                           \
00239   do {                                                                  \
00240     ptrdiff_t diff__ = Pike_sp - base__;                                \
00241     if (diff__ > (max_keep_on_stack)) {                                 \
00242       INT32 oldsize__ = base__[-1].u.array->size;                       \
00243       ACCEPT_UNFINISHED_TYPE_FIELDS {                                   \
00244         base__[-1].u.array =                                            \
00245           resize_array(base__[-1].u.array, oldsize__ + diff__);         \
00246       } END_ACCEPT_UNFINISHED_TYPE_FIELDS;                              \
00247       /* Unless the user does something, the type field will contain */ \
00248       /* BIT_MIXED|BIT_UNFINISHED from the allocation above. */         \
00249       MEMCPY((char *) (ITEM(base__[-1].u.array) + oldsize__),           \
00250              (char *) base__, diff__ * sizeof(struct svalue));          \
00251       Pike_sp = base__;                                                 \
00252     }                                                                   \
00253   } while (0)
00254 
00255 #define END_AGGREGATE_ARRAY                                             \
00256   DO_AGGREGATE_ARRAY(0);                                                \
00257   DO_IF_DEBUG(if (Pike_sp[-1].type != T_ARRAY) {                        \
00258                 Pike_fatal("Lost track of aggregated array.\n");        \
00259               });                                                       \
00260   array_fix_type_field(Pike_sp[-1].u.array);                            \
00261 } while (0)
00262 
00263 
00264 /*
00265  * Extract an svalue from an array
00266  */
00267 #define array_index_no_free(S,A,I) do {                         \
00268   INT32 ind_=(I);                                               \
00269   struct array *v_=(A);                                         \
00270   DO_IF_DEBUG(                                                  \
00271     if(ind_<0 || ind_>=v_->size)                                \
00272     Pike_fatal("Illegal index in low level index routine.\n");  \
00273     )                                                           \
00274                                                                 \
00275   assign_svalue_no_free((S), ITEM(v_) + ind_);                  \
00276 }while(0)
00277 
00278 
00279 /*
00280  * Sets an index in an array. 
00281  * 
00282  * @param V the array to modify
00283  * @param I the index of the array to set
00284  * @param S the svalue to set
00285  */
00286 #define array_set_index(V,I,S) do {                                      \
00287   struct array *v_=(V);                                                  \
00288   INT32 index_=(I);                                                      \
00289   struct svalue *s_=(S);                                                 \
00290   struct svalue tmp_;                                                    \
00291                                                                          \
00292   DO_IF_DEBUG(                                                           \
00293   if(index_<0 || index_>v_->size)                                        \
00294     Pike_fatal("Illegal index in low level array set routine.\n");       \
00295     )                                                                    \
00296                                                                          \
00297   check_destructed(s_);                                                  \
00298   tmp_=ITEM(v_)[index_];                                                 \
00299                                                                          \
00300   v_->type_field |= 1 << s_->type;                                       \
00301   assign_svalue_no_free( ITEM(v_) + index_, s_);                         \
00302   free_svalue(&tmp_);                                                    \
00303 }while(0)
00304 
00305 #define array_fix_unfinished_type_field(A) do {                         \
00306     struct array *a_ = (A);                                             \
00307     if (a_->type_field & BIT_UNFINISHED) {                              \
00308       DO_IF_DEBUG (array_check_type_field (a_));                        \
00309       array_fix_type_field (a_);                                        \
00310     }                                                                   \
00311   } while (0)
00312 
00313 #ifdef TRACE_UNFINISHED_TYPE_FIELDS
00314 /* Note: These macros don't support thread switches. */
00315 
00316 extern PMOD_EXPORT int accept_unfinished_type_fields;
00317 PMOD_EXPORT void dont_accept_unfinished_type_fields (void *orig);
00318 
00319 #define ACCEPT_UNFINISHED_TYPE_FIELDS do {                              \
00320     ONERROR autf_uwp_;                                                  \
00321     int orig_autf_ = accept_unfinished_type_fields;                     \
00322     accept_unfinished_type_fields++;                                    \
00323     SET_ONERROR (autf_uwp_, dont_accept_unfinished_type_fields,         \
00324                  (void *) orig_autf_);                                  \
00325     do
00326 
00327 #define END_ACCEPT_UNFINISHED_TYPE_FIELDS                               \
00328     while (0);                                                          \
00329     accept_unfinished_type_fields = orig_autf_;                         \
00330     UNSET_ONERROR (autf_uwp_);                                          \
00331   } while (0)
00332 
00333 #else
00334 
00335 #define ACCEPT_UNFINISHED_TYPE_FIELDS do
00336 #define END_ACCEPT_UNFINISHED_TYPE_FIELDS while (0)
00337 
00338 #endif
00339 
00340 #endif /* ARRAY_H */

Generated on Fri Jul 22 23:44:24 2005 for Pike by  doxygen 1.3.9.1