Value.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 #include <eyedb/eyedb_p.h>
00026 #include <sstream>
00027 
00028 using namespace std;
00029 //using std::ostringstream;
00030 
00031 #define TRY_GETELEMS_GC
00032 
00033 namespace eyedb {
00034 
00035   int
00036   Value::Struct::operator==(const Struct &stru)
00037   {
00038     if (attr_cnt != stru.attr_cnt)
00039       return 0;
00040 
00041     for (int i = 0; i < attr_cnt; i++)
00042       {
00043         if (strcmp(attrs[i]->name, stru.attrs[i]->name))
00044           return 0;
00045         if (*attrs[i]->value != *stru.attrs[i]->value)
00046           return 0;
00047       }
00048 
00049     return 1;
00050   }
00051 
00052   void
00053   Value::Struct::print(FILE *fd) const
00054   {
00055     fprintf(fd, "struct(");
00056     for (int ii = 0; ii < attr_cnt; ii++)
00057       {
00058         if (ii) fprintf(fd, ", ");
00059         fprintf(fd, "%s: ", attrs[ii]->name);
00060         attrs[ii]->value->print(fd);
00061       }
00062     fprintf(fd, ")");
00063   }
00064 
00065   std::string
00066   Value::Struct::toString() const
00067   {
00068     std::string s = "struct(";
00069     for (int ii = 0; ii < attr_cnt; ii++)
00070       {
00071         if (ii) s += ", ";
00072         s += std::string(attrs[ii]->name) + ": " + attrs[ii]->value->getString();
00073       }
00074     return s + ")";
00075   }
00076 
00077   int Value::operator==(const Value &val) const
00078   {
00079     if (type != val.type)
00080       return 0;
00081 
00082     switch(type)
00083       {
00084       case tNil:
00085         return 1;
00086 
00087       case tNull:
00088         return 1;
00089 
00090       case tBool:
00091         return val.b == b;
00092 
00093       case tByte:
00094         return val.by == by;
00095 
00096       case tChar:
00097         return val.c == c;
00098 
00099       case tShort:
00100         return val.s == s;
00101 
00102       case tInt:
00103         return val.i == i;
00104 
00105       case tLong:
00106         return val.l == l;
00107 
00108       case tDouble:
00109         return val.d == d;
00110 
00111       case tIdent:
00112       case tString:
00113         return !strcmp(val.str, str);
00114 
00115       case tData:
00116         return val.data.data == data.data &&
00117           val.data.size == data.size;
00118 
00119       case tOid:
00120         return *val.oid == *oid;
00121 
00122       case tObject:
00123         return val.o == o;
00124 
00125       case tObjectPtr:
00126         return val.o_ptr->getObject() == o_ptr->getObject();
00127 
00128       case tList:
00129       case tBag:
00130       case tSet:
00131       case tArray:
00132         if (list->getCount() != val.list->getCount())
00133           return 0;
00134         return val.list == list;
00135 
00136       case tPobj:
00137         return val.idx == idx;
00138 
00139       case tStruct:
00140         return *val.stru == *stru;
00141 
00142       default:
00143         abort();
00144       }
00145 
00146     return 0;
00147   }
00148 
00149   int cmp_objects(const Object *o, const Object *val_o)
00150   {
00151     if (o->getOid().isValid() && val_o->getOid().isValid())
00152       return o->getOid().getNX() < val_o->getOid().getNX();
00153 
00154     Size o_size;
00155     Data o_idr = o->getIDR(o_size);
00156 
00157     Size val_o_size;
00158     Data val_o_idr = val_o->getIDR(val_o_size);
00159 
00160     Size size = (o_size < val_o_size ? o_size : val_o_size);
00161 
00162     int r = memcmp(o_idr, val_o_idr, size);
00163     if (r < 0)
00164       return 1;
00165     if (r > 0)
00166       return 0;
00167     return o < val_o;
00168   }
00169 
00170   int Value::operator<(const Value &val) const
00171   {
00172     if (type != val.type)
00173       return (int)type < (int)val.type;
00174 
00175     switch(type) {
00176 
00177     case tNil:
00178     case tNull:
00179       return 0;
00180 
00181     case tBool:
00182       return b < val.b;
00183 
00184     case tByte:
00185       return by < val.by;
00186 
00187     case tChar:
00188       return c < val.c;
00189 
00190     case tShort:
00191       return s < val.s;
00192 
00193     case tInt:
00194       return i < val.i;
00195 
00196     case tLong:
00197       return l < val.l;
00198 
00199     case tDouble:
00200       return d < val.d;
00201 
00202     case tIdent:
00203     case tString:
00204       return strcmp(str, val.str) < 0 ? 1 : 0;
00205 
00206     case tData: {
00207       Size size = data.size;
00208       if (val.data.size < size)
00209         size = val.data.size;
00210       return memcmp(data.data, val.data.data, size) < 0 ? 1 : 0;
00211     }
00212 
00213     case tOid:
00214       return oid->getNX() < val.oid->getNX();
00215 
00216 #if 1
00217     case tObject:
00218       return cmp_objects(o, val.o);
00219 
00220     case tObjectPtr:
00221       return cmp_objects(o_ptr->getObject(), val.o_ptr->getObject());
00222 #else
00223     case tObject: {
00224       if (o->getOid().isValid() && val.o->getOid().isValid())
00225         return o->getOid().getNX() < val.o->getOid().getNX();
00226 
00227       Size o_size;
00228       Data o_idr = o->getIDR(o_size);
00229 
00230       Size val_o_size;
00231       Data val_o_idr = val.o->getIDR(val_o_size);
00232 
00233       Size size = (o_size < val_o_size ? o_size : val_o_size);
00234 
00235       int r = memcmp(o_idr, val_o_idr, size);
00236       if (r < 0)
00237         return 1;
00238       if (r > 0)
00239         return 0;
00240       return o < val.o;
00241     }
00242 #endif
00243 
00244     default:
00245       return !(*this == val);
00246     }
00247   }
00248 
00249   int Value::operator!=(const Value &val) const
00250   {
00251     return !(*this == val);
00252   }
00253 
00254   Value::Value(const Value &val)
00255   {
00256     bufstr = NULL;
00257     type = tNil;
00258     auto_obj_garb = false;
00259     *this = val;
00260   }
00261 
00262   void Value::set(Object *_o)
00263   {
00264     type = tObject;
00265 #ifdef TRY_GETELEMS_GC
00266     if (auto_obj_garb) {
00267       if (o)
00268         o->release();
00269       o = _o;
00270       if (o)
00271         o->incrRefCount();
00272 
00273       unvalid();
00274       return;
00275     }
00276 #endif
00277     o = _o;
00278     unvalid();
00279   }
00280 
00281   Status
00282   Value::toOidObjectArray(Database *db, LinkedList &ll, Bool isobj,
00283                           const RecMode *rcm)
00284   {
00285     if (type == tOid) {
00286       if (isobj) {
00287         if (db) {
00288           Object *x;
00289           Status status = db->loadObject(*oid, x, rcm);
00290           if (status)
00291             return status;
00292           ll.insertObjectLast(x);
00293         }
00294       }
00295       else
00296         ll.insertObjectLast(new Oid(*oid));
00297     }
00298     else if (type == tObject) {
00299       if (isobj) {
00300 #ifdef TRY_GETELEMS_GC
00301         if (o)
00302           o->incrRefCount();
00303 #endif
00304         ll.insertObjectLast(o);
00305       }
00306       else if (o) {
00307         Oid *xoid = new Oid(o->getOid());
00308         ll.insertObjectLast(new Oid(*xoid));
00309       }
00310     }
00311 
00312     else if (type == tObjectPtr) {
00313       if (isobj) {
00314         if (o_ptr->getObject())
00315           o_ptr->getObject()->incrRefCount();
00316         ll.insertObjectLast(o_ptr->getObject());
00317       }
00318       else if (o_ptr->getObject()) {
00319         Oid *xoid = new Oid(o_ptr->getObject()->getOid());
00320         ll.insertObjectLast(new Oid(*xoid));
00321       }
00322     }
00323     
00324     else if (type == tList || type == tBag || type == tSet || type == tArray) {
00325       LinkedListCursor cc(list);
00326       Value *v;
00327       Status status;
00328       while (cc.getNext((void *&)v))
00329         if (status = v->toOidObjectArray(db, ll, isobj, rcm))
00330           return status;
00331     }
00332     else if (type == tStruct) {
00333       Status status;
00334       for (int ii = 0; ii < stru->attr_cnt; ii++)
00335         if (status = stru->attrs[ii]->value->toOidObjectArray(db, ll, isobj, rcm))
00336           return status;
00337     }
00338     
00339     return Success;
00340   }
00341 
00342   Status
00343   Value::toValueArray(LinkedList &ll)
00344   {
00345     if (type == tList || type == tBag || type == tSet || type == tArray) {
00346       LinkedListCursor cc(list);
00347       Value *v;
00348       Status status;
00349       while (cc.getNext((void *&)v))
00350         if (status = v->toValueArray(ll))
00351           return status;
00352     }
00353     else if (type == tStruct) {
00354       Status status;
00355       for (int ii = 0; ii < stru->attr_cnt; ii++)
00356         if (status = stru->attrs[ii]->value->toValueArray(ll))
00357           return status;
00358     }
00359     else
00360       ll.insertObjectLast(new Value(*this));
00361 
00362     return Success;
00363   }
00364 
00365   Status
00366   Value::toArray(Database *db, ObjectPtrVector &obj_vect, const RecMode *rcm)
00367   {
00368     ObjectArray obj_array; // true or false ?
00369     Status s = toArray(db, obj_array, rcm);
00370     if (s)
00371       return s;
00372     obj_array.makeObjectPtrVector(obj_vect);
00373     return Success;
00374   }
00375 
00376   Status
00377   Value::toArray(Database *db, ObjectArray &objarr, const RecMode *rcm)
00378   {
00379     LinkedList ll;
00380     Status status = toOidObjectArray(db, ll, True, rcm);
00381     if (status)
00382       return status;
00383 
00384 #ifdef TRY_GETELEMS_GC
00385     Object **o_arr = new Object*[ll.getCount()];
00386     LinkedListCursor cc(ll);
00387     Object *o;
00388     for (int ii = 0; cc.getNext((void *&)o); ii++)
00389       o_arr[ii] = o;
00390 
00391     objarr.set(o_arr, ll.getCount());
00392     delete [] o_arr;
00393 
00394     if (objarr.isAutoGarbage()) {
00395       // should release objects because auto garb objectarray has
00396       // increase refcnt
00397       LinkedListCursor cc2(ll);
00398       for (int ii = 0; cc2.getNext((void *&)o); ii++) {
00399         if (o)
00400           o->release();
00401       }
00402     }
00403 #else
00404     objarr.set(0, ll.getCount());
00405 
00406     LinkedListCursor cc(ll);
00407     Object *x;
00408     for (int ii = 0; cc.getNext((void *&)x); ii++)
00409       objarr.setObjectAt(ii, x);//objarr[ii] = x;
00410 
00411 #endif
00412     return Success;
00413   }
00414 
00415   Status
00416   Value::toArray(OidArray &oidarr)
00417   {
00418     LinkedList ll;
00419     Status status = toOidObjectArray(0, ll, False, 0);
00420     if (status) return status;
00421 
00422     oidarr.set(0, ll.getCount());
00423 
00424     LinkedListCursor cc(ll);
00425     Oid *x;
00426     for (int ii = 0; cc.getNext((void *&)x); ii++) {
00427       oidarr[ii] = *x;
00428       delete x;
00429     }
00430 
00431     return Success;
00432   }
00433 
00434   Status
00435   Value::toArray(ValueArray &valarr)
00436   {
00437     LinkedList ll;
00438     Status status = toValueArray(ll);
00439     if (status)
00440       return status;
00441 
00442     valarr.set(0, ll.getCount());
00443 
00444     LinkedListCursor cc(ll);
00445 
00446     Value *x;
00447     for (int ii = 0; cc.getNext((void *&)x); ii++) {
00448       valarr.setValueAt(ii, *x); // valarr[ii] = *x;
00449       delete x;
00450     }
00451 
00452     return Success;
00453   }
00454 
00455   Value &Value::operator=(const Value &val)
00456   {
00457     if (this == &val)
00458       return *this;
00459 
00460     garbage();
00461 
00462     type = val.type;
00463 
00464     if (type == tString || type == tIdent)
00465       str = strdup(val.str);
00466     else if (type == tOid)
00467       oid = new Oid(*val.oid);
00468     else if (type == tList || type == tBag || type == tArray || type == tSet) {
00469       list = new LinkedList();
00470       LinkedListCursor cursor(val.list);
00471       Value *value;
00472       for (int ii = 0; cursor.getNext((void *&)value); ii++)
00473         if (value) list->insertObjectLast(new Value(*value));
00474     }
00475     else if (type == tStruct) {
00476       stru = new Struct(val.stru->attr_cnt);
00477       for (int ii = 0; ii < stru->attr_cnt; ii++)
00478         stru->attrs[ii] = new Attr(val.stru->attrs[ii]->name,
00479                                    val.stru->attrs[ii]->value);
00480     }
00481 #ifdef TRY_GETELEMS_GC
00482     else if (type == tObject) {
00483       o = val.o;
00484       if (auto_obj_garb && o) {
00485         o->incrRefCount();
00486       }
00487     }
00488 #endif
00489     else if (type == tObjectPtr) {
00490       o_ptr = new ObjectPtr(*val.o_ptr);
00491     }
00492     else
00493       memcpy(this, &val, sizeof(*this));
00494 
00495     bufstr = NULL;
00496 
00497     return *this;
00498   }
00499 
00500   static void
00501   append(char *& buf, const char *s)
00502   {
00503     buf = (char *)realloc(buf, strlen(buf)+strlen(s)+1);
00504     strcat(buf, s);
00505   }
00506 
00507   //#define OPTIM_STRLIST
00508 
00509   static std::string
00510   getStringList(LinkedList *list, const char *head)
00511   {
00512 #ifdef OPTIM_STRLIST
00513     int len = 16;
00514     char *s = (char *)malloc(len);
00515     *s = 0;
00516 
00517     LinkedListCursor cursor(list);
00518     Value *value;
00519     for (int i = 0; cursor.getNext((void *&)value); i++)
00520       {
00521         if (isBackendInterrupted())
00522           {
00523             set_backendInterrupt(False);
00524             return "<interrupted>";
00525           }
00526 
00527         char *x = value->getString();
00528         int l = strlen(x);
00529         if (l + strlen(s) + 4 >= len)
00530           {
00531             len += l + 200;
00532             s = (char *)realloc(s, len);
00533           }
00534 
00535         if (i) strcat(s, ", ");
00536         strcat(s, x);
00537       }
00538 
00539     if (strlen(s) + 4 >= len)
00540       {
00541         len += 4;
00542         s = (char *)realloc(s, len);
00543       }
00544 
00545     strcat(s, ")");
00546     return std::string(s);
00547 #else
00548     std::string s = std::string(head) + "(";
00549 
00550     LinkedListCursor cursor(list);
00551     Value *value;
00552     for (int i = 0; cursor.getNext((void *&)value); i++)
00553       {
00554         if (i) s += ", ";
00555         s += value->getString();
00556       }
00557 
00558     s += ")";
00559     return s;
00560 #endif
00561   }
00562 
00563   static void
00564   print_list(FILE *fd, LinkedList *list, const char *head)
00565   {
00566     fprintf(fd, "%s(", head);
00567 
00568     LinkedListCursor cursor(list);
00569     Value *value;
00570     for (int i = 0; cursor.getNext((void *&)value); i++)
00571       {
00572         if (i) fprintf(fd, ", ");
00573         value->print(fd);
00574       }
00575 
00576     fprintf(fd, ")");
00577   }
00578 
00579   const char *Value::getString() const
00580   {
00581     if (bufstr)
00582       return bufstr;
00583 
00584     char tok[32];
00585 
00586     *tok = 0;
00587 
00588     switch(type)
00589       {
00590       case tNil:
00591         ((Value *)this)->bufstr = strdup(NilString);
00592         break;
00593 
00594       case tNull:
00595         ((Value *)this)->bufstr = strdup(NullString);
00596         break;
00597 
00598       case tBool:
00599         sprintf(tok, "%s", (b ? "true" : "false"));
00600         break;
00601 
00602       case tByte:
00603         sprintf(tok, "\\0%d", b);
00604         break;
00605 
00606       case tChar:
00607         sprintf(tok, "'%c'", c);
00608         break;
00609 
00610       case tShort:
00611         sprintf(tok, "%d", s);
00612         break;
00613 
00614       case tInt:
00615         sprintf(tok, "%d", i);
00616         break;
00617 
00618       case tLong:
00619         sprintf(tok, "%lld", l);
00620         break;
00621 
00622       case tDouble:
00623         sprintf(tok, "%f", d);
00624         break;
00625 
00626       case tIdent:
00627         ((Value *)this)->bufstr = strdup(str);
00628         break;
00629 
00630       case tString:
00631         ((Value *)this)->bufstr = (char *)malloc(strlen(str)+3);
00632         sprintf(((Value *)this)->bufstr, "\"%s\"", str);
00633         break;
00634 
00635       case tData:
00636         sprintf(tok, "[0x%x, %u]", data.data, data.size);
00637         break;
00638 
00639       case tOid:
00640         ((Value *)this)->bufstr = strdup(oid->getString());
00641         break;
00642 
00643       case tObject:
00644         {
00645           ostringstream ostr;
00646           ostr << o;
00647           ((Value *)this)->bufstr = strdup(ostr.str().c_str());
00648         }
00649         break;
00650 
00651       case tObjectPtr:
00652         {
00653           ostringstream ostr;
00654           ostr << o_ptr->getObject();
00655           ((Value *)this)->bufstr = strdup(ostr.str().c_str());
00656         }
00657         break;
00658 
00659       case tList:
00660         ((Value *)this)->bufstr = strdup(getStringList(list, "list").c_str());
00661         break;
00662 
00663       case tSet:
00664         ((Value *)this)->bufstr = strdup(getStringList(list, "set").c_str());
00665         break;
00666 
00667       case tBag:
00668         ((Value *)this)->bufstr = strdup(getStringList(list, "bag").c_str());
00669         break;
00670 
00671       case tArray:
00672         ((Value *)this)->bufstr = strdup(getStringList(list, "array").c_str());
00673         break;
00674 
00675       case tPobj:
00676         {
00677           std::string x = str_convert((long)idx, "%x:obj");
00678           ((Value *)this)->bufstr = strdup(x.c_str());
00679         }
00680         break;
00681 
00682       case tStruct:
00683         ((Value *)this)->bufstr = strdup(stru->toString().c_str());
00684         break;
00685 
00686       default:
00687         abort();
00688       }
00689 
00690     if (*tok)
00691       ((Value *)this)->bufstr = strdup(tok);
00692 
00693     return bufstr;
00694   }
00695 
00696   void
00697   Value::print(FILE *fd) const
00698   {
00699     switch(type)
00700       {
00701       case tNil:
00702         fprintf(fd, NilString);
00703         break;
00704 
00705       case tNull:
00706         fprintf(fd, NullString);
00707         break;
00708 
00709       case tBool:
00710         fprintf(fd, "%s", (b ? "true" : "false"));
00711         break;
00712 
00713       case tByte:
00714         fprintf(fd, "\\0%d", b);
00715         break;
00716 
00717       case tChar:
00718         fprintf(fd, "'%c'", c);
00719         break;
00720 
00721       case tShort:
00722         fprintf(fd, "%d", s);
00723         break;
00724 
00725       case tInt:
00726         fprintf(fd, "%d", i);
00727         break;
00728 
00729       case tLong:
00730         fprintf(fd, "%lld", l);
00731         break;
00732 
00733       case tDouble:
00734         fprintf(fd, "%f", d);
00735         break;
00736 
00737       case tIdent:
00738         fprintf(fd, "%s", str);
00739         break;
00740 
00741       case tString:
00742         fprintf(fd, "\"%s\"", str);
00743         break;
00744 
00745       case tData:
00746         fprintf(fd, "0x%x", data);
00747         break;
00748 
00749       case tOid:
00750         fprintf(fd, oid->getString());
00751         break;
00752 
00753       case tObject:
00754         o->trace(fd);
00755         break;
00756 
00757       case tObjectPtr:
00758         o_ptr->getObject()->trace(fd);
00759         break;
00760 
00761       case tList:
00762         print_list(fd, list, "list");
00763         break;
00764 
00765       case tSet:
00766         print_list(fd, list, "set");
00767         break;
00768 
00769       case tBag:
00770         print_list(fd, list, "bag");
00771         break;
00772 
00773       case tArray:
00774         print_list(fd, list, "array");
00775         break;
00776 
00777       case tPobj:
00778         fprintf(fd, "%x:obj", idx);
00779         break;
00780 
00781       case tStruct:
00782         fprintf(fd, "%s", stru->toString().c_str());
00783         break;
00784 
00785       default:
00786         abort();
00787       }
00788   }
00789 
00790   const char *
00791   Value::getAttributeName(const Class *cl, Bool isIndirect)
00792   {
00793     if (cl->asCharClass())
00794       {
00795         if (isIndirect)
00796           return "str";
00797         return "c";
00798       }
00799 
00800     if (isIndirect || (!cl->asBasicClass() && !cl->asEnumClass()))
00801       return "o";
00802 
00803     if (cl->asInt16Class())
00804       return "s";
00805 
00806     if (cl->asInt32Class())
00807       return "i";
00808 
00809     if (cl->asInt64Class())
00810       return "l";
00811 
00812     if (cl->asFloatClass())
00813       return "d";
00814 
00815     if (cl->asOidClass())
00816       return "oid";
00817 
00818     if (cl->asByteClass())
00819       return "by";
00820 
00821     return "<unknown class>";
00822   }
00823 
00824   ostream& operator<<(ostream& os, const Value &value)
00825   {
00826     os << value.getString();
00827     return os;
00828   }
00829 
00830   ostream& operator<<(ostream& os, const Value *value)
00831   {
00832     os << value->getString();
00833     return os;
00834   }
00835 
00836   void
00837   Value::garbage()
00838   {
00839     if (type == tString || type == tIdent)
00840       free(str);
00841     else if (type == tOid)
00842       delete oid;
00843     else if (type == tList || type == tBag || type == tSet || type == tArray) {
00844       LinkedListCursor cursor(list);
00845       Value *value;
00846       while (cursor.getNext((void *&)value))
00847         delete value;
00848       delete list;
00849     }
00850     else if (type == tStruct)
00851       delete stru;
00852 #ifdef TRY_GETELEMS_GC
00853     else if (type == tObject) {
00854       if (auto_obj_garb && o) {
00855         o->release();
00856       }
00857     }
00858 #endif
00859     else if (type == tObjectPtr)
00860       delete o_ptr;
00861 
00862     free(bufstr);
00863   }
00864 
00865   const char *
00866   Value::getStringType() const
00867   {
00868     return getStringType(type);
00869   }
00870 
00871   const char *
00872   Value::getStringType(Value::Type type)
00873   {
00874     switch(type)
00875       {
00876       case tNil:
00877         return "nil";
00878 
00879       case tNull:
00880         return "null";
00881 
00882       case tBool:
00883         return "bool";
00884 
00885       case tByte:
00886         return "byte";
00887 
00888       case tChar:
00889         return "char";
00890 
00891       case tShort:
00892         return "int16";
00893 
00894       case tInt:
00895         return "int32";
00896 
00897       case tLong:
00898         return "int64";
00899 
00900       case tDouble:
00901         return "double";
00902 
00903       case tIdent:
00904         return "ident";
00905 
00906       case tString:
00907         return "string";
00908 
00909       case tData:
00910         return "data";
00911 
00912       case tOid:
00913         return "oid";
00914 
00915       case tObject:
00916         return "object";
00917 
00918       case tObjectPtr:
00919         return "object_ptr";
00920 
00921       case tList:
00922         return "list";
00923 
00924       case tSet:
00925         return "set";
00926 
00927       case tBag:
00928         return "bag";
00929 
00930       case tArray:
00931         return "array";
00932 
00933       case tPobj:
00934         return "pobject";
00935 
00936       case tStruct:
00937         return "struct";
00938 
00939       default:
00940         return "<unknown>";
00941       }
00942   }
00943 
00944   Data
00945   Value::getData(Size *psize) const
00946   {
00947     switch(type)
00948       {
00949       case tNil:
00950       case tNull:
00951         if (psize)
00952           *psize = 0;
00953         return 0;
00954 
00955       case tByte:
00956         if (psize)
00957           *psize = sizeof(by);
00958         return (Data)&by;;
00959 
00960       case tChar:
00961         if (psize)
00962           *psize = sizeof(c);
00963         return (Data)&c;;
00964 
00965       case tShort:
00966         if (psize)
00967           *psize = sizeof(s);
00968         return (Data)&s;;
00969 
00970       case tInt:
00971         if (psize)
00972           *psize = sizeof(i);
00973         return (Data)&i;
00974 
00975       case tLong:
00976         if (psize)
00977           *psize = sizeof(l);
00978         return (Data)&l;;
00979 
00980       case tDouble:
00981         if (psize)
00982           *psize = sizeof(d);
00983         return (Data)&d;;
00984 
00985       case tString:
00986         if (psize)
00987           *psize = strlen(str)+1;
00988         return (Data)str;
00989 
00990       case tData:
00991         if (psize)
00992           *psize = data.size;
00993         return data.data;
00994 
00995       case tOid:
00996         if (psize)
00997           *psize = sizeof(oid);
00998         return (Data)&oid;;
00999 
01000       default:
01001         assert(0);
01002         if (psize)
01003           *psize = 0;
01004         return (Data)0;;
01005       }
01006   }
01007 
01008   void
01009   Value::code(Data &idr, Offset &offset, Size &alloc_size) const
01010   {
01011     char x = type;
01012     char_code(&idr, &offset, &alloc_size, &x);
01013 
01014     switch(type)
01015       {
01016       case tNil:
01017       case tNull:
01018         break;
01019 
01020       case tBool:
01021         x = b;
01022         char_code(&idr, &offset, &alloc_size, &x);
01023         break;
01024 
01025       case tByte:
01026         char_code(&idr, &offset, &alloc_size, (char *)&by);
01027         break;
01028 
01029       case tChar:
01030         char_code(&idr, &offset, &alloc_size, &c);
01031         break;
01032 
01033       case tShort:
01034         int16_code(&idr, &offset, &alloc_size, &s);
01035         break;
01036 
01037       case tInt:
01038         int32_code(&idr, &offset, &alloc_size, &i);
01039         break;
01040 
01041       case tLong:
01042         int64_code(&idr, &offset, &alloc_size, &l);
01043         break;
01044 
01045       case tDouble:
01046         double_code(&idr, &offset, &alloc_size, &d);
01047         break;
01048 
01049       case tIdent:
01050       case tString:
01051         string_code(&idr, &offset, &alloc_size, str);
01052         break;
01053 
01054       case tData:
01055         throw *eyedb::Exception::make(eyedb::IDB_UNSERIALIZABLE_TYPE_ERROR, "tData");
01056         break;
01057 
01058       case tOid:
01059         oid_code(&idr, &offset, &alloc_size, oid->getOid());
01060         break;
01061 
01062       case tObject:
01063         throw *eyedb::Exception::make(eyedb::IDB_UNSERIALIZABLE_TYPE_ERROR, "tObject");
01064         break;
01065 
01066       case tObjectPtr:
01067         throw *eyedb::Exception::make(eyedb::IDB_UNSERIALIZABLE_TYPE_ERROR, "tObjectPtr");
01068         break;
01069 
01070       case tList:
01071       case tSet:
01072       case tBag:
01073       case tArray:
01074         {
01075           int cnt = list->getCount();
01076           int32_code(&idr, &offset, &alloc_size, &cnt);
01077           LinkedListCursor cc(list);
01078           Value *v;
01079           while (cc.getNext((void *&)v))
01080             v->code(idr, offset, alloc_size);
01081         }
01082         break;
01083 
01084       case tPobj:
01085         int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&idx);
01086         break;
01087 
01088       case tStruct:
01089         {
01090           int32_code(&idr, &offset, &alloc_size, &stru->attr_cnt);
01091           for (int ii = 0; ii < stru->attr_cnt; ii++)
01092             {
01093               string_code(&idr, &offset, &alloc_size, stru->attrs[ii]->name);
01094               stru->attrs[ii]->value->code(idr, offset, alloc_size);
01095             }
01096 
01097         }
01098         break;
01099 
01100       default:
01101         throw *eyedb::Exception::make(eyedb::IDB_INTERNAL_ERROR, "Unknown type in Value code()");
01102         break;
01103       }
01104   }
01105 
01106   void Value::setMustRelease(bool must_release)
01107   {
01108     if (type == tObject && o)
01109       o->setMustRelease(must_release);
01110   }
01111 
01112   Value::~Value()
01113   {
01114     garbage();
01115   }
01116 
01117   ValueArray::ValueArray(const Collection *coll)
01118   {
01119     values = NULL;
01120     value_cnt = 0;
01121     coll->getElements(*this);
01122   }
01123 
01124   ValueArray::ValueArray(const ValueArray &valarr)
01125   {
01126     value_cnt = 0;
01127     values = NULL;
01128     *this = valarr;
01129   }
01130  
01131   ValueArray::ValueArray(const ValueList &list)
01132   {
01133     value_cnt = 0;
01134     int cnt = list.getCount();
01135     if (!cnt) {
01136       values = 0;
01137       return;
01138     }
01139 
01140     values = (Value *)malloc(sizeof(Value) * cnt);
01141     memset(values, 0, sizeof(Value) * cnt);
01142 
01143     ValueListCursor c(list);
01144     Value value;
01145 
01146     for (; c.getNext(value); value_cnt++)
01147       values[value_cnt] = value;
01148   }
01149 
01150   ValueArray &ValueArray::operator=(const ValueArray &valarr)
01151   {
01152     set(valarr.values, valarr.value_cnt, True);
01153     return *this;
01154   }
01155 
01156   void ValueArray::set(Value *_values, unsigned int _value_cnt, Bool copy)
01157   {
01158     if (values)
01159       delete[] values;
01160 
01161     value_cnt = _value_cnt;
01162 
01163     if (copy) {
01164       values = new Value[value_cnt];
01165       
01166 #ifdef TRY_GETELEMS_GC
01167       for (int i = 0; i < value_cnt; i++)
01168         values[i].setAutoObjGarbage(auto_obj_garb);
01169 #endif
01170 
01171       if (_values) {
01172         for (int i = 0; i < value_cnt; i++) {
01173           values[i] = _values[i];
01174         }
01175       }
01176 
01177       return;
01178     }
01179     
01180     values = _values;
01181   }
01182 
01183   void ValueArray::setMustRelease(bool must_release)
01184   {
01185     for (int i = 0; i < value_cnt; i++)
01186       values[i].setMustRelease(must_release);
01187   }
01188 
01189   void ValueArray::setAutoObjGarbage(bool _auto_obj_garb)
01190   {
01191     auto_obj_garb = _auto_obj_garb;
01192 #ifdef TRY_GETELEMS_GC
01193     for (int i = 0; i < value_cnt; i++)
01194       values[i].setAutoObjGarbage(auto_obj_garb);
01195 #endif
01196   }
01197 
01198   Status ValueArray::setValueAt(unsigned int ind, const Value &value)
01199   {
01200     if (ind >= value_cnt)
01201       return Exception::make(IDB_ERROR, "invalid range %d (maximun is %d)",
01202                              ind, value_cnt);
01203 
01204     values[ind] = value;
01205     return Success;
01206   }
01207 
01208   ValueList *
01209   ValueArray::toList() const
01210   {
01211     return new ValueList(*this);
01212   }
01213 
01214   ValueArray::~ValueArray()
01215   {
01216     if (values)
01217       delete [] values;
01218   }
01219 
01220   void
01221   Value::decode(Data idr, Offset &offset)
01222   {
01223     garbage();
01224 
01225     char x;
01226     char_decode(idr, &offset, &x);
01227     type = (Type)x;
01228 
01229     switch(type)
01230       {
01231       case tNil:
01232       case tNull:
01233         break;
01234 
01235       case tBool:
01236         char_decode(idr, &offset, &x);
01237         b = (Bool)x;
01238         break;
01239 
01240       case tByte:
01241         char_decode(idr, &offset, (char *)&by);
01242         break;
01243 
01244       case tChar:
01245         char_decode(idr, &offset, &c);
01246         break;
01247 
01248       case tShort:
01249         int16_decode(idr, &offset, &s);
01250         break;
01251 
01252       case tInt:
01253         int32_decode(idr, &offset, &i);
01254         break;
01255 
01256       case tLong:
01257         int64_decode(idr, &offset, &l);
01258         break;
01259 
01260       case tDouble:
01261         double_decode(idr, &offset, &d);
01262         break;
01263 
01264       case tIdent:
01265       case tString:
01266         {
01267           char *y;
01268           string_decode(idr, &offset, &y);
01269           str = strdup(y);
01270         }
01271         break;
01272 
01273       case tData:
01274         break;
01275 
01276       case tOid:
01277         {
01278           eyedbsm::Oid xoid;
01279           oid_decode(idr, &offset, &xoid);
01280           oid = new Oid(xoid);
01281         }
01282         break;
01283 
01284       case tObject:
01285         break;
01286 
01287       case tObjectPtr:
01288         break;
01289 
01290       case tList:
01291       case tSet:
01292       case tBag:
01293       case tArray:
01294         {
01295           int cnt;
01296           int32_decode(idr, &offset, &cnt);
01297           list = new LinkedList();
01298           for (int ii = 0; ii < cnt; ii++)
01299             {
01300               Value *v = new Value();
01301               v->decode(idr, offset);
01302               list->insertObjectLast(v);
01303             }
01304         }
01305         break;
01306 
01307       case tPobj:
01308         int32_decode(idr, &offset, (eyedblib::int32 *)&idx);
01309         break;
01310 
01311       case tStruct:
01312         {
01313           int cnt;
01314           int32_decode(idr, &offset, &cnt);
01315           stru = new Struct(cnt);
01316           for (int ii = 0; ii < stru->attr_cnt; ii++)
01317             {
01318               char *y;
01319               string_decode(idr, &offset, &y);
01320               Value *v = new Value();
01321               v->decode(idr, offset);
01322               stru->attrs[ii] = new Attr(y, v);
01323             }
01324 
01325         }
01326         break;
01327 
01328       default:
01329         abort();
01330         break;
01331       }
01332   }
01333 
01334   void decode_value(void *xdata, void *xvalue)
01335   {
01336     Offset offset = 0;
01337     ((Value *)xvalue)->decode((Data)((rpc_Data *)xdata)->data, offset);
01338   }
01339 
01340   ValueList::ValueList()
01341   {
01342     list = new LinkedList();
01343   }
01344 
01345   ValueList::ValueList(const ValueArray &value_array)
01346   {
01347     list = new LinkedList();
01348     for (int i = 0; i < value_array.getCount(); i++)
01349       insertValueLast(value_array[i]);
01350   }
01351 
01352   int ValueList::getCount() const
01353   {
01354     return list->getCount();
01355   }
01356 
01357   void
01358   ValueList::insertValue(const Value &value)
01359   {
01360     list->insertObject(new Value(value));
01361   }
01362 
01363   void
01364   ValueList::insertValueFirst(const Value &value)
01365   {
01366     list->insertObjectFirst(new Value(value));
01367   }
01368 
01369   void
01370   ValueList::insertValueLast(const Value &value)
01371   {
01372     list->insertObjectLast(new Value(value));
01373   }
01374 
01375   Bool
01376   ValueList::suppressValue(const Value &value)
01377   {
01378     LinkedListCursor c(list);
01379     Value *xvalue;
01380     while (c.getNext((void *&)xvalue))
01381       if (*xvalue == value) {
01382         list->deleteObject(xvalue);
01383         return True;
01384       }
01385 
01386     return False;
01387   }
01388 
01389   Bool
01390   ValueList::suppressPairValues(const Value &value1, const Value &value2)
01391   {
01392     LinkedListCursor c(list);
01393     int cnt = list->getCount();
01394 
01395     for (int n = 0; n < cnt; n += 2) {
01396       Value *xvalue1, *xvalue2;
01397       assert(c.getNext((void *&)xvalue1));
01398       assert(c.getNext((void *&)xvalue2));
01399 
01400       if (value1 == *xvalue1 && value2 == *xvalue2) {
01401         list->deleteObject(xvalue1);
01402         list->deleteObject(xvalue2);
01403         return True;
01404       }
01405     }
01406 
01407     return False;
01408   }
01409 
01410   Bool
01411   ValueList::exists(const Value &value) const
01412   {
01413     LinkedListCursor c(list);
01414     Value *xvalue;
01415     while (c.getNext((void *&)xvalue))
01416       if (*xvalue == value)
01417         return True;
01418     return False;
01419   }
01420 
01421   void
01422   ValueList::empty()
01423   {
01424     list->empty();
01425   }
01426 
01427   ValueArray *
01428   ValueList::toArray() const
01429   {
01430     int cnt = list->getCount();
01431     if (!cnt)
01432       return new ValueArray();
01433     Value *arr = (Value *)malloc(sizeof(Value) * cnt);
01434     memset(arr, 0, sizeof(Value) * cnt);
01435 
01436     LinkedListCursor c(list);
01437     Value *xvalue;
01438     for (int i = 0; c.getNext((void *&)xvalue); i++)
01439       arr[i] = *xvalue;
01440   
01441     ValueArray *value_arr = new ValueArray(arr, cnt);
01442     free(arr);
01443     return value_arr;
01444   }
01445 
01446   ValueList::~ValueList()
01447   {
01448     LinkedListCursor c(list);
01449     Value *xvalue;
01450     while (c.getNext((void *&)xvalue))
01451       delete xvalue;
01452     delete list;
01453   }
01454 
01455   ValueListCursor::ValueListCursor(const ValueList &valuelist)
01456   {
01457     c = new LinkedListCursor(valuelist.list);
01458   }
01459 
01460   ValueListCursor::ValueListCursor(const ValueList *valuelist)
01461   {
01462     c = new LinkedListCursor(valuelist->list);
01463   }
01464 
01465   Bool
01466   ValueListCursor::getNext(Value &value)
01467   {
01468     Value *xvalue;
01469     if (c->getNext((void *&)xvalue))
01470       {
01471         value = *xvalue;
01472         return True;
01473       }
01474 
01475     return False;
01476   }
01477 
01478   ValueListCursor::~ValueListCursor()
01479   {
01480     delete c;
01481   }
01482 }

Generated on Mon Dec 22 18:16:14 2008 for eyedb by  doxygen 1.5.3