00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022
00023 #include "analy_register.h"
00024
00025 #include "htatom.h"
00026 #include "stddata.h"
00027 #include "stream.h"
00028 #include "tools.h"
00029
00030
00031
00032
00033 void Area::init()
00034 {
00035 a = NULL;
00036 }
00037
00038 static void areaload(ht_object_stream *st, area_s *&p, int level, int &left)
00039 {
00040 if (left<=0) {
00041 p = NULL;
00042 return;
00043 }
00044 p = (area_s *) smalloc0(sizeof(area_s));
00045 if ((level<=1) || (left<=1)) {
00046 st->getObject(p->start, "start");
00047 st->getObject(p->end, "end");
00048 p->left = p->right = NULL;
00049 left--;
00050 } else {
00051 areaload(st, p->left, level / 2, left);
00052 st->getObject(p->start, "start");
00053 st->getObject(p->end, "end");
00054 left--;
00055 areaload(st, p->right, level / 2 -1, left);
00056 }
00057 }
00058
00059 int Area::load(ht_object_stream *st)
00060 {
00061 int count;
00062 GET_INT_DEC(st, count);
00063 areaload(st, a, count, count);
00064 return st->get_error();
00065 }
00066
00067 void Area::done()
00068 {
00069 freeRecursive(a);
00070 }
00071
00072 OBJECT_ID Area::object_id() const
00073 {
00074 return ATOM_AREA;
00075 }
00076
00077 static area_s *areaget(area_s *p, Object *V)
00078 {
00079 if (p) {
00080 if (V->compareTo(p->start) < 0) return areaget(p->left, V);
00081 if (V->compareTo(p->end) >= 0) return areaget(p->right, V);
00082 return p;
00083 } else return NULL;
00084 }
00085
00086 area_s *Area::getArea(Object *at)
00087 {
00088 return areaget(a, at);
00089 }
00090
00091 static void areaadd(area_s *&p, Object *Start, Object *End)
00092 {
00093 if (p) {
00094 if ((Start->compareTo(p->start) >= 0) && (Start->compareTo(p->end)<=0)) {
00095 if (p->end->compareTo(End) < 0) {
00096 delete p->end;
00097 p->end = End->duplicate();
00098 }
00099 if ((End->compareTo(p->start) >= 0) && (End->compareTo(p->end)<=0)) {
00100 if (p->start->compareTo(Start) > 0) {
00101 delete p->start;
00102 p->start = Start->duplicate();
00103 }
00104 }
00105 return;
00106 }
00107 if ((End->compareTo(p->start) >= 0) && (End->compareTo(p->end) <= 0)) {
00108 if (p->start->compareTo(Start) > 0) {
00109 delete p->start;
00110 p->start = Start->duplicate();
00111 }
00112 return;
00113 }
00114 if (Start->compareTo(p->end) > 0) areaadd(p->right, Start, End);
00115 else areaadd(p->left, Start, End);
00116 } else {
00117
00118 area_s *tmp = (area_s *) smalloc(sizeof(area_s));
00119 p = tmp;
00120 p->start = Start->duplicate();
00121 p->end = End->duplicate();
00122 p->left = NULL;
00123 p->right = NULL;
00124 }
00125 }
00126
00127 void Area::add(Object *Start, Object *End)
00128 {
00129 areaadd(a, Start, End);
00130 }
00131
00132 static bool areacontains(area_s *p, Object *V)
00133 {
00134 if (p) {
00135 if (V->compareTo(p->start) < 0) return areacontains(p->left, V);
00136 if (V->compareTo(p->end) >= 0) return areacontains(p->right, V);
00137 return true;
00138 } else return false;
00139 }
00140
00141 bool Area::contains(Object *v)
00142 {
00143 if (v->instanceOf(ATOM_ADDRESS_INVALID)) return false;
00144 return areacontains(a, v);
00145 }
00146
00147 static void areafindnext(area_s *p, Object *from, Object **res)
00148 {
00149 if (!from || from->compareTo(p->start) < 0) {
00150 *res = p->start;
00151 if (p->left) areafindnext(p->left, from, res);
00152 } else if (from->compareTo(p->end) >= 0) {
00153 if (p->right) areafindnext(p->right, from, res);
00154 } else *res = from;
00155 }
00156
00157 Object *Area::findNext(Object *from)
00158 {
00159 Object *res = NULL;
00160 if (a) areafindnext(a, from, &res);
00161 return res;
00162 }
00163
00164 static void areafindprev(area_s *p, Object *from, Object **res)
00165 {
00166
00167 if (p) {
00168 if (!from || from->compareTo(p->end) >= 0) {
00169 *res = p->end;
00170 areafindprev(p->right, from, res);
00171 } else if (from->compareTo(p->start) < 0) {
00172 areafindprev(p->left, from, res);
00173 } else *res = from;
00174 };
00175 }
00176
00177 Object *Area::findPrev(Object *from)
00178 {
00179 Object *res = NULL;
00180 areafindprev(a, from, &res);
00181 return res;
00182 }
00183
00184 void Area::freeRecursive(area_s *p)
00185 {
00186 if (p) {
00187 freeRecursive(p->left);
00188 freeRecursive(p->right);
00189 delete p->start;
00190 delete p->end;
00191 free(p);
00192 }
00193 }
00194
00195 static void areacount(area_s *p, int &c, Object **startend)
00196 {
00197 if (p) {
00198 areacount(p->left, c, startend);
00199 if (!*startend || p->start->compareTo(*startend) != 0) c++;
00200 *startend = p->end;
00201 areacount(p->right, c, startend);
00202 }
00203 }
00204
00205 static void areastore(ht_object_stream *f, area_s *p, Object **startend)
00206 {
00207 if (p) {
00208 areastore(f, p->left, startend);
00209 if (!*startend) {
00210 f->putObject(p->start, "start");
00211 } else {
00212 if ((*startend)->compareTo(p->start) != 0) {
00213 f->putObject(*startend, "end");
00214 f->putObject(p->start, "start");
00215 }
00216 }
00217 *startend = p->end;
00218 areastore(f, p->right, startend);
00219 }
00220 }
00221
00222 void Area::store(ht_object_stream *f)
00223 {
00224 int count = 0;
00225 Object *start = NULL;
00226 areacount(a, count, &start);
00227 PUT_INT_DEC(f, count);
00228 start = NULL;
00229 areastore(f, a, &start);
00230 if (start!=NULL) f->putObject(start, "end");
00231 }
00232
00233 #ifdef DEBUG_FIXNEW
00234 static void areadump(int sp, area_s *A)
00235 {
00236 if (A) {
00237 for (int i=0; i<sp; i++) printf(" ");
00238 char buf[1024];
00239 ht_snprintf(buf, sizeof buf, "%y %y\n", A->start, A->end);
00240 printf(buf);
00241 ++sp;++sp;
00242 areadump(sp, A->left);
00243 areadump(sp, A->right);
00244 }
00245 }
00246
00247 void Area::dump()
00248 {
00249 areadump(1, a);
00250 }
00251 #endif
00252
00253
00254
00255
00256
00257 BUILDER(ATOM_AREA, Area)
00258
00259 bool init_stddata()
00260 {
00261 REGISTER(ATOM_AREA, Area)
00262 return true;
00263 }
00264
00265 void done_stddata()
00266 {
00267 UNREGISTER(ATOM_AREA, Area)
00268 }