Argument_code.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 <assert.h>
00026 #include "eyedb_p.h"
00027 #include <eyedblib/rpc_be.h>
00028 
00029 #define NO_DIRECT_SET // added the 22/09/98
00030 
00031 // ---------------------------------------------------------------------------
00032 //
00033 // private functions
00034 //
00035 // ---------------------------------------------------------------------------
00036 
00037 namespace eyedb {
00038 
00039 #define UNKNOWN_TYPE(T, X) \
00040 { \
00041   fprintf(stderr, #X ": unknown argument type : %d\n", T); \
00042   abort(); \
00043 }
00044 
00045 static unsigned int
00046 getSize(const ArgArray *);
00047 
00048 static unsigned int
00049 getSize(const Argument *arg)
00050 {
00051   int type = arg->type->getType();
00052   unsigned int size = sizeof(int); // for arg type
00053 
00054   if (type == INT16_TYPE)
00055     size += sizeof(eyedblib::int16);
00056   else if (type == INT32_TYPE)
00057     size += sizeof(eyedblib::int32);
00058   else if (type == INT64_TYPE)
00059     size += sizeof(eyedblib::int64);
00060   else if (type == CHAR_TYPE)
00061     size += sizeof(char);
00062   else if (type == STRING_TYPE)
00063     size += sizeof(int) + strlen(arg->u.s)+1;
00064   else if (type == FLOAT_TYPE)
00065     size += sizeof(double);
00066   else if (type == OID_TYPE)
00067     size += sizeof(Oid);
00068   else if (type == OBJ_TYPE)
00069     size += sizeof(int) + (arg->u.o ? 2 * sizeof(Oid) +
00070                            arg->u.o->getIDRSize() : 0);
00071   else if (type == ARRAY_TYPE)
00072     size += getSize(arg->u.array);
00073   else if (type == RAW_TYPE)
00074     size += sizeof(int) + arg->u.raw.size;
00075   else if (type == (ARRAY_TYPE|INT16_TYPE))
00076     {
00077       size += sizeof(int); // cnt
00078       size += sizeof(eyedblib::int16) * arg->u.arr_i16.cnt;
00079     }
00080   else if (type == (ARRAY_TYPE|INT32_TYPE))
00081     {
00082       size += sizeof(int); // cnt
00083       size += sizeof(eyedblib::int32) * arg->u.arr_i32.cnt;
00084     }
00085   else if (type == (ARRAY_TYPE|INT64_TYPE))
00086     {
00087       size += sizeof(int); // cnt
00088       size += sizeof(eyedblib::int64) * arg->u.arr_i64.cnt;
00089     }
00090   else if (type == (ARRAY_TYPE|CHAR_TYPE))
00091     {
00092       size += sizeof(int); // cnt
00093       size += sizeof(char) * arg->u.arr_c.cnt;
00094     }
00095   else if (type == (ARRAY_TYPE|FLOAT_TYPE))
00096     {
00097       size += sizeof(int); // cnt
00098       size += sizeof(double) * arg->u.arr_d.cnt;
00099     }
00100   else if (type == (ARRAY_TYPE|STRING_TYPE))
00101     {
00102       size += sizeof(int); // cnt
00103       for (int i = 0; i < arg->u.arr_s.cnt; i++)
00104         size += sizeof(int) + strlen(arg->u.arr_s.s[i]) + 1;
00105     }
00106   else if (type == (ARRAY_TYPE|OBJ_TYPE))
00107     {
00108       size += sizeof(int); // cnt
00109       for (int i = 0; i < arg->u.arr_o.cnt; i++)
00110         size += sizeof(int) + (arg->u.arr_o.o[i] ? 2 * sizeof(Oid) +
00111                                arg->u.arr_o.o[i]->getIDRSize() : 0);
00112     }
00113   else if (type == (ARRAY_TYPE|OID_TYPE))
00114     {
00115       size += sizeof(int); // cnt
00116       size += sizeof(Oid) * arg->u.arr_oid.cnt;
00117     }
00118   else if (type == VOID_TYPE)
00119     ;
00120   else
00121     UNKNOWN_TYPE(type, getSize())
00122 
00123   return size;
00124 }
00125 
00126 static unsigned int
00127 getSize(const ArgArray *array)
00128 {
00129   int size = sizeof(int); // n
00130   int cnt = array->getCount();
00131   for (int i = 0; i < cnt; i++)
00132     size += getSize((*array)[i]);
00133 
00134   return size;
00135 }
00136 
00137 static void
00138 code_arg(const ArgArray *array, char * &);
00139 
00140 static void
00141 code_arg(const char *s, char *&p)
00142 {
00143   int len = strlen(s)+1;
00144   mcp(p, &len, sizeof(int));
00145   p += sizeof(int);
00146   mcp(p, s, len);
00147   p += len;
00148 }
00149 
00150 static void
00151 code_arg(const Object *o, char *&p)
00152 {
00153   int len = (o ? o->getIDRSize() : 0);
00154   mcp(p, &len, sizeof(int));
00155   p += sizeof(int);
00156   if (o)
00157     {
00158       Oid oid = o->getOid();
00159       mcp(p, &oid, sizeof(Oid));
00160       p += sizeof(Oid);
00161       oid = o->getClass()->getOid();
00162       mcp(p, &oid, sizeof(Oid));
00163       p += sizeof(Oid);
00164       mcp(p, o->getIDR(), o->getIDRSize());
00165       p += o->getIDRSize();
00166     }
00167 }
00168 
00169 #define CODE_SIMPLE_ARRAY(PTR, F, TYPE, P) \
00170 { \
00171   int len = sizeof(TYPE) * PTR.cnt; \
00172   mcp(P, &PTR.cnt, sizeof(int)); \
00173   P += sizeof(int); \
00174   mcp(P, PTR.F, len); \
00175   P += len; \
00176 }
00177 
00178 #define DECODE_SIMPLE_ARRAY(ARG, TYPE, P) \
00179 { \
00180   int cnt; \
00181   mcp(&cnt, P, sizeof(int)); \
00182   P += sizeof(int); \
00183  \
00184   TYPE *x = (TYPE *)malloc(sizeof(TYPE) * cnt); \
00185   for (int i = 0; i < cnt; i++) \
00186     { \
00187       mcp(&x[i], P, sizeof(TYPE)); \
00188       P += sizeof(TYPE); \
00189     } \
00190   ARG->set(x, cnt, Argument::AutoFullGarbage); \
00191 }
00192 
00193 static void
00194 code_arg(const Argument *arg, char * &p)
00195 {
00196   int type = arg->type->getType();
00197   mcp(p, &type, sizeof(int));
00198 
00199   p += sizeof(int);
00200 
00201   if (type == INT16_TYPE)
00202     {
00203       mcp(p, &arg->u.i16, sizeof(eyedblib::int16));
00204       p += sizeof(eyedblib::int16);
00205     }
00206   else if (type == INT32_TYPE)
00207     {
00208       mcp(p, &arg->u.i32, sizeof(eyedblib::int32));
00209       p += sizeof(eyedblib::int32);
00210     }
00211   else if (type == INT64_TYPE)
00212     {
00213       mcp(p, &arg->u.i64, sizeof(eyedblib::int64));
00214       p += sizeof(eyedblib::int64);
00215     }
00216   else if (type == CHAR_TYPE)
00217     {
00218       mcp(p, &arg->u.c, sizeof(char));
00219       p += sizeof(char);
00220     }
00221   else if (type == STRING_TYPE)
00222     code_arg(arg->u.s, p);
00223   else if (type == RAW_TYPE)
00224     {
00225       mcp(p, &arg->u.raw.size, sizeof(int));
00226       p += sizeof(int);
00227       mcp(p, arg->u.raw.data, arg->u.raw.size);
00228       p += arg->u.raw.size;
00229     }
00230   else if (type == FLOAT_TYPE)
00231     {
00232       mcp(p, &arg->u.d, sizeof(double));
00233       p += sizeof(double);
00234     }
00235   else if (type == OID_TYPE)
00236     {
00237       mcp(p, arg->u.oid, sizeof(Oid));
00238       p += sizeof(Oid);
00239     }
00240   else if (type == OBJ_TYPE)
00241     code_arg(arg->u.o, p);
00242   else if (type == ARRAY_TYPE)
00243     code_arg(arg->u.array, p);
00244   else if (type == (ARRAY_TYPE|INT16_TYPE))
00245     {
00246       CODE_SIMPLE_ARRAY(arg->u.arr_i16, i, eyedblib::int16, p);
00247     }
00248   else if (type == (ARRAY_TYPE|INT32_TYPE))
00249     {
00250       CODE_SIMPLE_ARRAY(arg->u.arr_i32, i, eyedblib::int32, p);
00251     }
00252   else if (type == (ARRAY_TYPE|INT64_TYPE))
00253     {
00254       CODE_SIMPLE_ARRAY(arg->u.arr_i64, i, eyedblib::int64, p);
00255     }
00256   else if (type == (ARRAY_TYPE|CHAR_TYPE))
00257     {
00258       CODE_SIMPLE_ARRAY(arg->u.arr_c, c, char, p);
00259     }
00260   else if (type == (ARRAY_TYPE|FLOAT_TYPE))
00261     {
00262       CODE_SIMPLE_ARRAY(arg->u.arr_d, d, double, p);
00263     }
00264   else if (type == (ARRAY_TYPE|OID_TYPE))
00265     {
00266       CODE_SIMPLE_ARRAY(arg->u.arr_oid, oid, Oid, p);
00267     }
00268   else if (type == (ARRAY_TYPE|STRING_TYPE))
00269     {
00270       mcp(p, &arg->u.arr_s.cnt, sizeof(int));
00271       p += sizeof(int);
00272 
00273       for (int i = 0; i < arg->u.arr_s.cnt; i++)
00274         code_arg(arg->u.arr_s.s[i], p);
00275     }
00276   else if (type == (ARRAY_TYPE|OBJ_TYPE))
00277     {
00278       mcp(p, &arg->u.arr_o.cnt, sizeof(int));
00279       p += sizeof(int);
00280 
00281       for (int i = 0; i < arg->u.arr_o.cnt; i++)
00282         code_arg(arg->u.arr_o.o[i], p);
00283     }
00284   else if (type == VOID_TYPE)
00285     ;
00286   else
00287     UNKNOWN_TYPE(type, code_arg)
00288 }
00289 
00290 static void
00291 code_arg(const ArgArray *array, char * &p)
00292 {
00293   int n = array->getCount();
00294   mcp(p, &n, sizeof(int));
00295   p += sizeof(int);
00296 
00297   for (int i = 0; i < n; i++)
00298     code_arg((*array)[i], p);
00299 }
00300 
00301 static void
00302 decode_arg(Database *, ArgArray *array, const char * &);
00303 
00304 static void
00305 decode_arg(Database *db, Object *&o, const Class *&cls,
00306            const char *&p)
00307 {
00308   int len;
00309   mcp(&len, p, sizeof(int));
00310   p += sizeof(int);
00311 
00312   if (!len)
00313     {
00314       o = NULL;
00315       return;
00316     }
00317 
00318   Oid o_oid, cl_oid;
00319   mcp(&o_oid, p, sizeof(Oid));
00320   p += sizeof(Oid);
00321   mcp(&cl_oid, p, sizeof(Oid));
00322   p += sizeof(Oid);
00323 
00324   p += len;
00325 
00326   cls = db->getSchema()->getClass(cl_oid);
00327 
00328   if (!cls)
00329     {
00330       o = NULL;
00331       return;
00332     }
00333 
00334   o = cls->newObj((Data)p + IDB_OBJ_HEAD_SIZE);
00335 
00336   if (o)
00337     ObjectPeer::setOid(o, o_oid);
00338 }
00339 
00340 static void
00341 decode_arg(Database *db, Argument *arg, const char * &p)
00342 {
00343   int type;
00344   
00345   mcp(&type, p, sizeof(int));
00346   p += sizeof(int);
00347   
00348   //  arg->type->setType(type);
00349   
00350   if (type == INT16_TYPE)
00351     {
00352       eyedblib::int16 i;
00353       mcp(&i, p, sizeof(eyedblib::int16));
00354       arg->set(i);
00355       p += sizeof(eyedblib::int16);
00356     }
00357   else if (type == INT32_TYPE)
00358     {
00359       eyedblib::int32 i;
00360       mcp(&i, p, sizeof(eyedblib::int32));
00361       arg->set(i);
00362       p += sizeof(eyedblib::int32);
00363     }
00364   else if (type == INT64_TYPE)
00365     {
00366       eyedblib::int64 i;
00367       mcp(&i, p, sizeof(eyedblib::int64));
00368       arg->set(i);
00369       p += sizeof(eyedblib::int64);
00370     }
00371   else if (type == CHAR_TYPE)
00372     {
00373       char c;
00374       mcp(&c, p, sizeof(char));
00375       arg->set(c);
00376       p += sizeof(char);
00377     }
00378   else if (type == STRING_TYPE)
00379     {
00380       int len;
00381       mcp(&len, p, sizeof(int));
00382       p += sizeof(int);
00383       //arg->set((char *)p);
00384       //changed the 15/01/99: added strdup
00385       arg->set(strdup((char *)p), Argument::AutoFullGarbage);
00386       p += len;
00387     }
00388   else if (type == FLOAT_TYPE)
00389     {
00390       double d;
00391       mcp(&d, p, sizeof(double));
00392       arg->set(d);
00393       p += sizeof(double);
00394     }
00395   else if (type == OID_TYPE)
00396     {
00397       Oid oid;
00398       mcp(&oid, p, sizeof(Oid));
00399       arg->set(oid, db);
00400       p += sizeof(Oid);
00401     }
00402   else if (type == RAW_TYPE)
00403     {
00404       int size;
00405       mcp(&size, p, sizeof(int));
00406       p += sizeof(int);
00407       // see changed 15/01/99: should do the same thing, i.e. copy
00408       // of the raw buffer!
00409       arg->set(Argument::dup((const unsigned char *)p, size), size,
00410                Argument::AutoFullGarbage);
00411       p += size;
00412     }
00413   else if (type == OBJ_TYPE)
00414     {
00415       Object *o = NULL;
00416       const Class *cls = NULL;
00417       decode_arg(db, o, cls, p);
00418       arg->set(o, Argument::AutoFullGarbage);
00419       if (cls)
00420         arg->type->setClname(cls->getName());
00421     }
00422   else if (type == (OBJ_TYPE|ARRAY_TYPE))
00423     {
00424       int cnt;
00425       mcp(&cnt, p, sizeof(int));
00426       p += sizeof(int);
00427       Object **o = (Object **)malloc(sizeof(Object *) * cnt);
00428 
00429       const Class *cls = NULL;
00430       for (int i = 0; i < cnt; i++)
00431         decode_arg(db, o[i], cls, p);
00432 
00433       arg->set(o, cnt, Argument::AutoFullGarbage);
00434     }
00435   else if (type == (INT16_TYPE|ARRAY_TYPE))
00436     {
00437       DECODE_SIMPLE_ARRAY(arg, eyedblib::int16, p);
00438     }
00439   else if (type == (INT32_TYPE|ARRAY_TYPE))
00440     {
00441       DECODE_SIMPLE_ARRAY(arg, eyedblib::int32, p);
00442     }
00443   else if (type == (INT64_TYPE|ARRAY_TYPE))
00444     {
00445       DECODE_SIMPLE_ARRAY(arg, eyedblib::int64, p);
00446     }
00447   else if (type == (CHAR_TYPE|ARRAY_TYPE))
00448     {
00449       DECODE_SIMPLE_ARRAY(arg, char, p);
00450     }
00451   else if (type == (STRING_TYPE|ARRAY_TYPE))
00452     {
00453       int cnt;
00454       mcp(&cnt, p, sizeof(int));
00455       p += sizeof(int);
00456 
00457       char **s = (char **)malloc(sizeof(char *) * cnt);
00458       for (int i = 0; i < cnt; i++)
00459         {
00460           int len;
00461           mcp(&len, p, sizeof(int));
00462           p += sizeof(int);
00463           s[i] = strdup((char *)p);
00464           p += len;
00465         }
00466       arg->set(s, cnt, Argument::AutoFullGarbage);
00467     }
00468   else if (type == (FLOAT_TYPE|ARRAY_TYPE))
00469     {
00470       DECODE_SIMPLE_ARRAY(arg, double, p);
00471     }
00472   else if (type == (OID_TYPE|ARRAY_TYPE))
00473     {
00474       DECODE_SIMPLE_ARRAY(arg, Oid, p);
00475     }
00476   else if (type == ARRAY_TYPE)
00477     {
00478       int n;
00479       mcp(&n, p, sizeof(int));
00480       p += sizeof(int);
00481       ArgArray *array = new ArgArray(n, Argument::AutoFullGarbage);
00482       arg->set(array, Argument::AutoFullGarbage);
00483       decode_arg(db, (ArgArray *)array, p);
00484     }
00485   else if (type == VOID_TYPE)
00486     ;
00487   else
00488     UNKNOWN_TYPE(type, decode_arg)
00489 }
00490 
00491 static void
00492 decode_arg(Database *db, ArgArray *array, const char * &p)
00493 {
00494   int cnt = array->getCount();
00495   for (int i = 0; i < cnt; i++)
00496     decode_arg(db, (Argument *)(*array)[i], p);
00497 }
00498 
00499 // ---------------------------------------------------------------------------
00500 //
00501 // exported functions
00502 //
00503 // ---------------------------------------------------------------------------
00504 
00505 // ---------------------------------------------------------------------------
00506 //
00507 // argument array coding
00508 //
00509 // ---------------------------------------------------------------------------
00510 
00511 void
00512 code_arg_array(void *xdata, const void *xargarray)
00513 {
00514   rpc_Data *data = (rpc_Data *)xdata;
00515   const ArgArray *argarray = (const ArgArray *)xargarray;
00516   unsigned int size = sizeof(int);
00517 
00518   int cnt = argarray->getCount();
00519   int i;
00520   for (i = 0; i < cnt; i++)
00521     {
00522       const Argument *arg = (*argarray)[i];
00523       size += getSize(arg);
00524     }
00525 
00526   data->size = size;
00527   data->data = malloc(data->size);
00528   data->status = rpc_TempDataUsed;
00529 
00530   char *p = (char *)data->data;
00531   mcp(p, &cnt, sizeof(int));
00532 
00533   p += sizeof(int);
00534 
00535   for (i = 0; i < cnt; i++)
00536     {
00537       const Argument *arg = (*argarray)[i];
00538       code_arg(arg, p);
00539     }
00540 }
00541 
00542 int
00543 decode_arg_array(void *xdb, const void *xdata, void **pargarray,
00544                      Bool allocate)
00545 {
00546   Database *db = (Database *)xdb;
00547   rpc_Data *data = (rpc_Data *)xdata;
00548   const char *p = (const char *)data->data;
00549   int cnt;
00550   mcp(&cnt, p, sizeof(int));
00551   p += sizeof(int);
00552 
00553   ArgArray *argarray;
00554   if (allocate)
00555     {
00556 /*
00557       Argument *args = new Argument[cnt];
00558       argarray = new ArgArray(args, cnt, Argument::FullGarbage);
00559 */
00560       argarray = new ArgArray(cnt, Argument::AutoFullGarbage);
00561       *(ArgArray **)pargarray = argarray;
00562     }
00563   else
00564     argarray = (ArgArray *)pargarray;
00565 
00566   for (int i = 0; i < cnt; i++)
00567     {
00568       Argument *arg = (*argarray)[i];
00569       decode_arg(db, arg, p);
00570     }
00571 
00572   //  return (data->size - (int)(p - (char *)data->data));
00573   return (int)(p - (char *)data->data);
00574 }
00575 
00576 // ---------------------------------------------------------------------------
00577 //
00578 // argument coding
00579 //
00580 // ---------------------------------------------------------------------------
00581 
00582 void
00583 code_argument(void *xdata, const void *xarg)
00584 {
00585   rpc_Data *data = (rpc_Data *)xdata;
00586   const Argument *arg = (const Argument *)xarg;
00587   int osize = data->size;
00588 
00589   data->size += getSize(arg);
00590   data->data = realloc(data->data, data->size);
00591   data->status = rpc_TempDataUsed;
00592   char *p = ((char *)data->data) + osize;
00593 
00594   code_arg(arg, p);
00595 }
00596 
00597 void
00598 decode_argument(void *xdb, const void *xdata, void *xarg, int offset)
00599 {
00600   Database *db = (Database *)xdb;
00601   rpc_Data *data = (rpc_Data *)xdata;
00602 
00603   Argument *arg = (Argument *)xarg;
00604   const char *p = ((const char *)data->data) + offset;
00605 
00606   decode_arg(db, arg, p);
00607 }
00608 
00609 
00610 // ---------------------------------------------------------------------------
00611 //
00612 // signature coding
00613 //
00614 // ---------------------------------------------------------------------------
00615 
00616 void
00617 code_signature(void *xdata, const void *xsign)
00618 {
00619   rpc_Data *data = (rpc_Data *)xdata;
00620   const Signature *sign = (const Signature *)xsign;
00621   int cnt = sign->getNargs();
00622 
00623   data->size = sizeof(int) * (cnt + 2);
00624   data->data = malloc(data->size);
00625 
00626   char *p = (char *)data->data;
00627   int type = sign->getRettype()->getType();
00628 
00629   mcp(p, &type, sizeof(int));
00630   p += sizeof(int);
00631   mcp(p, &cnt, sizeof(int));
00632   p += sizeof(int);
00633 
00634   for (int i = 0; i < cnt; i++)
00635     {
00636       type = sign->getTypes(i)->getType();
00637       mcp(p, &type, sizeof(int));
00638       p += sizeof(int);
00639       if (type == OBJ_TYPE)
00640         {
00641           const char *s = sign->getTypes(i)->getClname().c_str();
00642           int len = strlen(sign->getTypes(i)->getClname().c_str());
00643           mcp(p, &len, sizeof(int));
00644           p += sizeof(int);
00645           mcp(p, s, len);
00646           p += len;
00647         }
00648     }
00649 
00650   assert(data->size == (int)(p - (char *)data->data));
00651 }
00652 
00653 void
00654 decode_signature(const void *xdata, void *xsign)
00655 {
00656   rpc_Data *data = (rpc_Data *)xdata;
00657   const char *p = (const char *)data->data;
00658   Signature *sign = (Signature *)xsign;
00659   ArgType *type;
00660 
00661   int _type;
00662   mcp(&_type, p, sizeof(int));
00663   p += sizeof(int);
00664 #ifdef NO_DIRECT_SET
00665   type = sign->getRettype();
00666 #else
00667   type = new ArgType();
00668 #endif
00669 
00670   type->setType((ArgType_Type)_type, False);
00671 
00672 #ifndef NO_DIRECT_SET
00673   sign->setRettype(type);
00674 #endif
00675 
00676   int cnt;
00677   mcp(&cnt, p, sizeof(int));
00678   p += sizeof(int);
00679   sign->setNargs(cnt);
00680 
00681 #ifdef NO_DIRECT_SET
00682   sign->setTypesCount(cnt);
00683 #endif
00684 
00685   for (int i = 0; i < cnt; i++)
00686     {
00687       mcp(&_type, p, sizeof(int));
00688       p += sizeof(int);
00689 #ifdef NO_DIRECT_SET
00690       type = sign->getTypes(i);
00691 #else
00692       type = new ArgType();
00693 #endif
00694       type->setType((ArgType_Type)_type, False);
00695       if (_type == OBJ_TYPE)
00696         {
00697           int len;
00698           mcp(&len, p, sizeof(int));
00699           p += sizeof(int);
00700           char *s = (char *)malloc(len+1);
00701           mcp(s, p, len);
00702           p += len;
00703           type->setClname(s);
00704           free(s);
00705         }
00706 
00707 #ifndef NO_DIRECT_SET
00708       sign->setTypes(i, type);
00709 #endif
00710     }
00711 
00712   assert(data->size == (int)(p - (char *)data->data));
00713 }
00714 }

Generated on Mon Dec 22 18:15:47 2008 for eyedb by  doxygen 1.5.3