/*************************************************************************** (C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International Business Machines Corporation and Siemens Rolm Communications Inc. For purposes of this license notice, the term Licensors shall mean, collectively, Apple Computer, Inc., AT&T Corp., International Business Machines Corporation and Siemens Rolm Communications Inc. The term Licensor shall mean any of the Licensors. Subject to acceptance of the following conditions, permission is hereby granted by Licensors without the need for written agreement and without license or royalty fees, to use, copy, modify and distribute this software for any purpose. The above copyright notice and the following four paragraphs must be reproduced in all copies of this software and any software including this software. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS. IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. The software is provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the government are subject to restrictions set forth in DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. ***************************************************************************/ /* * src: vobject.c * doc: vobject and APIs to construct vobject, APIs pretty print * vobject, and convert a vobject into its textual representation. */ #ifndef MWERKS #include #endif #include "vobject.h" #include #include #include #define NAME_OF(o) o->id #define VALUE_TYPE(o) o->valType #define STRINGZ_VALUE_OF(o) o->val.strs #define USTRINGZ_VALUE_OF(o) o->val.ustrs #define INTEGER_VALUE_OF(o) o->val.i #define LONG_VALUE_OF(o) o->val.l #define ANY_VALUE_OF(o) o->val.any #define VOBJECT_VALUE_OF(o) o->val.vobj typedef union ValueItem { const char *strs; const wchar_t *ustrs; unsigned int i; unsigned long l; void *any; VObject *vobj; } ValueItem; struct VObject { VObject *next; const char *id; VObject *prop; unsigned short valType; ValueItem val; }; typedef struct StrItem StrItem; struct StrItem { StrItem *next; const char *s; unsigned int refCnt; }; const char** fieldedProp; /*---------------------------------------------------------------------- The following functions involve with memory allocation: newVObject deleteVObject dupStr deleteStr newStrItem deleteStrItem ----------------------------------------------------------------------*/ DLLEXPORT(VObject*) newVObject_(const char *id) { VObject *p = (VObject*)malloc(sizeof(VObject)); p->next = 0; p->id = id; p->prop = 0; VALUE_TYPE(p) = 0; ANY_VALUE_OF(p) = 0; return p; } DLLEXPORT(VObject*) newVObject(const char *id) { return newVObject_(lookupStr(id)); } DLLEXPORT(void) deleteVObject(VObject *p) { unUseStr(p->id); free(p); } DLLEXPORT(char*) dupStr(const char *s, unsigned int size) { char *t; if (size == 0) { size = strlen(s); } t = (char*)malloc(size+1); if (t) { memcpy(t,s,size); t[size] = 0; return t; } else { return (char*)0; } } DLLEXPORT(void) deleteStr(const char *p) { if (p) free((void*)p); } static StrItem* newStrItem(const char *s, StrItem *next) { StrItem *p = (StrItem*)malloc(sizeof(StrItem)); p->next = next; p->s = s; p->refCnt = 1; return p; } static void deleteStrItem(StrItem *p) { free((void*)p); } /*---------------------------------------------------------------------- The following function provide accesses to VObject's value. ----------------------------------------------------------------------*/ DLLEXPORT(const char*) vObjectName(VObject *o) { return NAME_OF(o); } DLLEXPORT(void) setVObjectName(VObject *o, const char* id) { NAME_OF(o) = id; } DLLEXPORT(const char*) vObjectStringZValue(VObject *o) { return STRINGZ_VALUE_OF(o); } DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s) { STRINGZ_VALUE_OF(o) = dupStr(s,0); VALUE_TYPE(o) = VCVT_STRINGZ; } DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s) { STRINGZ_VALUE_OF(o) = s; VALUE_TYPE(o) = VCVT_STRINGZ; } DLLEXPORT(const wchar_t*) vObjectUStringZValue(VObject *o) { return USTRINGZ_VALUE_OF(o); } DLLEXPORT(void) setVObjectUStringZValue(VObject *o, const wchar_t *s) { USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2); VALUE_TYPE(o) = VCVT_USTRINGZ; } DLLEXPORT(void) setVObjectUStringZValue_(VObject *o, const wchar_t *s) { USTRINGZ_VALUE_OF(o) = s; VALUE_TYPE(o) = VCVT_USTRINGZ; } DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o) { return INTEGER_VALUE_OF(o); } DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i) { INTEGER_VALUE_OF(o) = i; VALUE_TYPE(o) = VCVT_UINT; } DLLEXPORT(unsigned long) vObjectLongValue(VObject *o) { return LONG_VALUE_OF(o); } DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l) { LONG_VALUE_OF(o) = l; VALUE_TYPE(o) = VCVT_ULONG; } DLLEXPORT(void*) vObjectAnyValue(VObject *o) { return ANY_VALUE_OF(o); } DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t) { ANY_VALUE_OF(o) = t; VALUE_TYPE(o) = VCVT_RAW; } DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o) { return VOBJECT_VALUE_OF(o); } DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p) { VOBJECT_VALUE_OF(o) = p; VALUE_TYPE(o) = VCVT_VOBJECT; } DLLEXPORT(int) vObjectValueType(VObject *o) { return VALUE_TYPE(o); } /*---------------------------------------------------------------------- The following functions can be used to build VObject. ----------------------------------------------------------------------*/ DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p) { /* circular link list pointed to tail */ /* o {next,id,prop,val} V pn {next,id,prop,val} V ... p1 {next,id,prop,val} V pn --> o {next,id,prop,val} V pn {next,id,prop,val} V p {next,id,prop,val} ... p1 {next,id,prop,val} V pn */ VObject *tail = o->prop; if (tail) { p->next = tail->next; o->prop = tail->next = p; } else { o->prop = p->next = p; } return p; } DLLEXPORT(VObject*) addProp(VObject *o, const char *id) { return addVObjectProp(o,newVObject(id)); } DLLEXPORT(VObject*) addProp_(VObject *o, const char *id) { return addVObjectProp(o,newVObject_(id)); } DLLEXPORT(void) addList(VObject **o, VObject *p) { p->next = 0; if (*o == 0) { *o = p; } else { VObject *t = *o; while (t->next) { t = t->next; } t->next = p; } } DLLEXPORT(VObject*) nextVObjectInList(VObject *o) { return o->next; } DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size) { VObject *sizeProp; setVObjectAnyValue(prop, val); sizeProp = addProp(prop,VCDataSizeProp); setVObjectLongValue(sizeProp, size); return prop; } DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size) { void *p = dupStr((const char *)val,size); return setValueWithSize_(prop,p,p?size:0); } DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o) { i->start = o->prop; i->next = 0; } DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o) { i->start = o->next; i->next = 0; } DLLEXPORT(int) moreIteration(VObjectIterator *i) { return (i->start && (i->next==0 || i->next!=i->start)); } DLLEXPORT(VObject*) nextVObject(VObjectIterator *i) { if (i->start && i->next != i->start) { if (i->next == 0) { i->next = i->start->next; return i->next; } else { i->next = i->next->next; return i->next; } } else return (VObject*)0; } DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id) { VObjectIterator i; initPropIterator(&i,o); while (moreIteration(&i)) { VObject *each = nextVObject(&i); if (!stricmp(id,each->id)) return each; } return (VObject*)0; } DLLEXPORT(VObject*) addGroup(VObject *o, const char *g) { /* a.b.c --> prop(c) prop(VCGrouping=b) prop(VCGrouping=a) */ char *dot = strrchr(g,'.'); if (dot) { VObject *p, *t; char *gs, *n = dot+1; gs = dupStr(g,0); /* so we can write to it. */ /* used to be * t = p = addProp_(o,lookupProp_(n)); */ t = p = addProp_(o,lookupProp(n)); dot = strrchr(gs,'.'); *dot = 0; do { dot = strrchr(gs,'.'); if (dot) { n = dot+1; *dot=0; } else n = gs; /* property(VCGroupingProp=n); * and the value may have VCGrouping property */ t = addProp(t,VCGroupingProp); setVObjectStringZValue(t,lookupProp_(n)); } while (n != gs); deleteStr(gs); return p; } else return addProp_(o,lookupProp(g)); } DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v) { VObject *prop; prop = addProp(o,p); setVObjectUStringZValue_(prop, fakeUnicode(v,0)); return prop; } DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size) { VObject *prop; prop = addProp(o,p); setValueWithSize_(prop, (void*)v, size); return prop; } DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size) { return addPropSizedValue_(o,p,dupStr(v,size),size); } /*---------------------------------------------------------------------- The following pretty print a VObject ----------------------------------------------------------------------*/ static void printVObject_(FILE *fp, VObject *o, int level); static void indent(FILE *fp, int level) { int i; for (i=0;i */ appendcOFile_(fp,0xd); appendcOFile_(fp,0xa); } else appendcOFile_(fp,c); } static void appendsOFile(OFile *fp, const char *s) { int i, slen; slen = strlen(s); for (i=0; ifp = ofp; fp->s = 0; fp->len = 0; fp->limit = 0; fp->alloc = 0; fp->fail = 0; } static void initMemOFile(OFile *fp, char *s, int len) { fp->fp = 0; fp->s = s; fp->len = 0; fp->limit = s?len:0; fp->alloc = s?0:1; fp->fail = 0; } static int writeBase64(OFile *fp, unsigned char *s, long len) { long cur = 0; int i, numQuads = 0; unsigned long trip; unsigned char b; char quad[5]; #define MAXQUADS 16 quad[4] = 0; while (cur < len) { // collect the triplet of bytes into 'trip' trip = 0; for (i = 0; i < 3; i++) { b = (cur < len) ? *(s + cur) : 0; cur++; trip = trip << 8 | b; } // fill in 'quad' with the appropriate four characters for (i = 3; i >= 0; i--) { b = (unsigned char)(trip & 0x3F); trip = trip >> 6; if ((3 - i) < (cur - len)) quad[i] = '='; // pad char else if (b < 26) quad[i] = (char)b + 'A'; else if (b < 52) quad[i] = (char)(b - 26) + 'a'; else if (b < 62) quad[i] = (char)(b - 52) + '0'; else if (b == 62) quad[i] = '+'; else quad[i] = '/'; } // now output 'quad' with appropriate whitespace and line ending appendsOFile(fp, (numQuads == 0 ? " " : "")); appendsOFile(fp, quad); appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); numQuads = (numQuads + 1) % MAXQUADS; } appendcOFile(fp,'\n'); return 1; } static void writeQPString(OFile *fp, const char *s) { const char *p = s; while (*p) { if (*p == '\n') { if (p[1]) appendsOFile(fp,"=0A="); } appendcOFile(fp,*p); p++; } } static void writeVObject_(OFile *fp, VObject *o); static void writeValue(OFile *fp, VObject *o, unsigned long size) { if (o == 0) return; switch (VALUE_TYPE(o)) { case VCVT_USTRINGZ: { char *s = fakeCString(USTRINGZ_VALUE_OF(o)); writeQPString(fp, s); deleteStr(s); break; } case VCVT_STRINGZ: { writeQPString(fp, STRINGZ_VALUE_OF(o)); break; } case VCVT_UINT: { char buf[16]; sprintf(buf,"%u", INTEGER_VALUE_OF(o)); appendsOFile(fp,buf); break; } case VCVT_ULONG: { char buf[16]; sprintf(buf,"%lu", LONG_VALUE_OF(o)); appendsOFile(fp,buf); break; } case VCVT_RAW: { appendcOFile(fp,'\n'); writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size); break; } case VCVT_VOBJECT: appendcOFile(fp,'\n'); writeVObject_(fp,VOBJECT_VALUE_OF(o)); break; } } static void writeAttrValue(OFile *fp, VObject *o) { if (NAME_OF(o)) { struct PreDefProp *pi; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; appendcOFile(fp,';'); appendsOFile(fp,NAME_OF(o)); } else appendcOFile(fp,';'); if (VALUE_TYPE(o)) { appendcOFile(fp,'='); writeValue(fp,o,0); } } static void writeGroup(OFile *fp, VObject *o) { char buf1[256]; char buf2[256]; strcpy(buf1,NAME_OF(o)); while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { strcpy(buf2,STRINGZ_VALUE_OF(o)); strcat(buf2,"."); strcat(buf2,buf1); strcpy(buf1,buf2); } appendsOFile(fp,buf1); } static int inList(const char **list, const char *s) { if (list == 0) return 0; while (*list) { if (stricmp(*list,s) == 0) return 1; list++; } return 0; } static void writeProp(OFile *fp, VObject *o) { if (NAME_OF(o)) { struct PreDefProp *pi; VObjectIterator t; const char **fields_ = 0; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_BEGIN) != 0)) { writeVObject_(fp,o); return; } if (isAPropertyOf(o,VCGroupingProp)) writeGroup(fp,o); else appendsOFile(fp,NAME_OF(o)); if (pi) fields_ = pi->fields; initPropIterator(&t,o); while (moreIteration(&t)) { const char *s; VObject *eachProp = nextVObject(&t); s = NAME_OF(eachProp); if (stricmp(VCGroupingProp,s) && !inList(fields_,s)) writeAttrValue(fp,eachProp); } if (fields_) { int i = 0, n = 0; const char** fields = fields_; /* output prop as fields */ appendcOFile(fp,':'); while (*fields) { VObject *t = isAPropertyOf(o,*fields); i++; if (t) n = i; fields++; } fields = fields_; for (i=0;iflags & PD_BEGIN) != 0)) { VObjectIterator t; const char *begin = NAME_OF(o); appendsOFile(fp,"BEGIN:"); appendsOFile(fp,begin); appendcOFile(fp,'\n'); initPropIterator(&t,o); while (moreIteration(&t)) { VObject *eachProp = nextVObject(&t); writeProp(fp, eachProp); } appendsOFile(fp,"END:"); appendsOFile(fp,begin); appendsOFile(fp,"\n\n"); } } } void writeVObject(FILE *fp, VObject *o) { OFile ofp; initOFile(&ofp,fp); writeVObject_(&ofp,o); } DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o) { FILE *fp = fopen(fname,"w"); if (fp) { writeVObject(fp,o); fclose(fp); } } DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list) { FILE *fp = fopen(fname,"w"); if (fp) { while (list) { writeVObject(fp,list); list = nextVObjectInList(list); } fclose(fp); } } DLLEXPORT(char*) writeMemVObject(char *s, int *len, VObject *o) { OFile ofp; initMemOFile(&ofp,s,len?*len:0); writeVObject_(&ofp,o); if (len) *len = ofp.len; appendcOFile(&ofp,0); return ofp.s; } DLLEXPORT(char*) writeMemVObjects(char *s, int *len, VObject *list) { OFile ofp; initMemOFile(&ofp,s,len?*len:0); while (list) { writeVObject_(&ofp,list); list = nextVObjectInList(list); } if (len) *len = ofp.len; appendcOFile(&ofp,0); return ofp.s; } /*---------------------------------------------------------------------- APIs to do fake Unicode stuff. ----------------------------------------------------------------------*/ DLLEXPORT(wchar_t*) fakeUnicode(const char *ps, int *bytes) { wchar_t *r, *pw; int len = strlen(ps)+1; pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len); if (bytes) *bytes = len * sizeof(wchar_t); while (*ps) { if (*ps == '\n') *pw = (wchar_t)0x2028; else if (*ps == '\r') *pw = (wchar_t)0x2029; else *pw = (wchar_t)(unsigned char)*ps; ps++; pw++; } *pw = (wchar_t)0; return r; } DLLEXPORT(int) uStrLen(const wchar_t *u) { int i = 0; while (*u != (wchar_t)0) { u++; i++; } return i; } DLLEXPORT(char*) fakeCString(const wchar_t *u) { char *s, *t; int len = uStrLen(u) + 1; t = s = (char*)malloc(len); while (*u) { if (*u == (wchar_t)0x2028) *t = '\n'; else if (*u == (wchar_t)0x2029) *t = '\r'; else *t = (char)*u; u++; t++; } *t = 0; return s; } // end of source file vobject.c /tr> * With portmgr hat on, reset inactive maintainer.linimon2004-11-201-1/+1 * - Distfiles change every few days, so drop md5 checking on thempav2004-11-182-4/+5 * Add blast, a powerful software package for gene and protein identification,pav2004-11-126-0/+324 * Bump PORTREVISIONS for all ports that depend on atk or pango to ease in themarcus2004-11-084-4/+4 * - Fix build on amd64 (crude hack to pass -fPIC to c++ compiles)pav2004-11-071-0/+11 * Update to 3.14kevlo2004-11-063-5/+4 * Correct a typo: s/linux-opera/linux-openmotif/g.mezz2004-11-021-1/+1 * - Update to 2004.06.16pav2004-11-024-167/+276 * Chase the linux-openmotif shared library version and mark biology/spdbv asmezz2004-11-021-1/+4 * Now installs on FreeBSD 5.x.kris2004-10-291-7/+1 * - Update to 1.30pav2004-10-283-128/+209 * Avoid the use of != statements in ports Makefilemaho2004-10-241-1/+5 * - Update to 3.62pav2004-10-123-6/+16 * BROKEN on 5.x: Does not compilekris2004-09-291-1/+7 * Upgrade to latest revision to make fetchable again.thierry2004-09-252-3/+3 * Update config.h and unbreak.thierry2004-09-241-2/+2 * The build should be fixed now, so remove BROKEN mark.danfe2004-09-231-7/+1 * BROKEN on 5.x: Does not compilekris2004-09-191-1/+7 * BROKEN on 5.x: Does not installkris2004-09-191-0/+4 * BROKEN on 5.x: Does not installkris2004-09-191-0/+4 * Unbreak the build on 5.X and -CURRENT.danfe2004-09-181-0/+44 * BROKEN on 5.x: Does not compilekris2004-09-181-1/+7 * - add missing MAN1 and MAN3leeym2004-09-042-357/+537 * - Unbreak by upgrading to 4.2;thierry2004-08-204-444/+387 * biology/lsysexp is not brokenedwin2004-08-181-3/+5 * This is now buildable on 5.x, remove BROKEN.kris2004-08-171-7/+1 * After devel/p5-File-Temp has gained an IGNORE for PERL_LEVEL > 500800, allmat2004-08-121-1/+3 * - Update to 5.2pav2004-07-312-3/+13 * Use X_IMAKE_PORT instead of dist-specific imake dependencies. While here,anholt2004-07-241-6/+3 * Update to version 2.7.2.1.1krion2004-07-105-42/+35 * Apply a big libtool patch to allow porters to use the libtool installed bymarcus2004-07-101-1/+1 * Fix distsitevs2004-07-061-2/+1 * BROKEN: Checksum mismatchkris2004-07-031-0/+2 * Update to 4.6vs2004-07-027-51/+58 * BROKEN: Does not buildkris2004-07-021-0/+2 * Update to fix fetch. Rework PORTVERSION to be more like biology/fasta3linimon2004-07-014-9/+11 * Chase mastersite and fix checksum to unbreak. (Changes are inclusion of alinimon2004-07-012-8/+4 * Update to 1.7.6.1.linimon2004-06-304-11/+43 * Drop maintainershiplioux2004-06-241-1/+1 * Fix MASTER_SITES:vs2004-06-231-2/+2 * Add ariadne 1.3, programs to compare protein sequences andkrion2004-06-225-0/+60 * Set an expiry date of 2004-08-20 for these BROKEN/IGNORE/FORBIDDENkris2004-06-222-1/+5 * BROKEN: Checksum mismatchkris2004-06-201-0/+2 * Replace explicit imake dependency with USE_IMAKE=yesanholt2004-06-181-5/+1 * Update to 20040613 releaselioux2004-06-132-3/+3 * - Remove obsolete MASTER_SITESkrion2004-06-081-2/+1 * - Update MASTER_SITESpav2004-06-021-3/+3 * [PATCH] biology/mopac patchsite fixedwin2004-06-011-1/+1 * [PATCH] biology/mopac distsite fixedwin2004-06-011-1/+1 * [PATCH] biology/gff2ps distsite fixedwin2004-06-011-3/+3 * - Update WWWpav2004-05-301-1/+1 * - Fix MASTER_SITESkrion2004-05-231-4/+1 * - Remove long time unresponsive MASTER_SITEpav2004-05-221-1/+0 * - Update MASTER_SITES and WWW: linekrion2004-05-222-2/+2 * Add forgotten patches...thierry2004-05-214-2/+62 * BROKEN: Broken pkg-plistkris2004-05-211-0/+2 * unbreak, only minor changes in the distfiles (see PR)eik2004-05-182-8/+7 * Add a missing BUILD_DEPENDS.thierry2004-05-111-0/+1 * Upgrade to 2.0b7 and unbreak.thierry2004-05-117-113/+128 * Fix MASTER_SITESmarkus2004-05-091-1/+1 * Make portlint happy by replacing space to tabmaho2004-05-072-4/+4 * - update to 4.5.3petef2004-05-02