From 4750b90ad18f4f59fa19b839550d6397f5dffbfd Mon Sep 17 00:00:00 2001 From: Arturo Espinosa Date: Thu, 2 Apr 1998 02:18:42 +0000 Subject: GnomeCalendar toplevel GnomeApp; versit code -mig svn path=/trunk/; revision=89 --- libversit/vobject.c | 1428 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1428 insertions(+) create mode 100644 libversit/vobject.c (limited to 'libversit/vobject.c') diff --git a/libversit/vobject.c b/libversit/vobject.c new file mode 100644 index 0000000000..74ac4fadfb --- /dev/null +++ b/libversit/vobject.c @@ -0,0 +1,1428 @@ +/*************************************************************************** +(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 -- cgit