lib/xap.c

Go to the documentation of this file.
00001 /* xap - XML Automatic Parser - together with autoXml this helps automatically
00002  * read in automatically generated data structures.  Calls lower level routine
00003  * in xp module, which originally was just a thin shell around expat. 
00004  *
00005  * This file is copyright 2002 Jim Kent, but license is hereby
00006  * granted for all use - public, private or commercial. */
00007 
00008 #include "common.h"
00009 #include "xap.h"
00010 #include "errabort.h"
00011 #include "xp.h"
00012 
00013 static char const rcsid[] = "$Id: xap.c,v 1.11 2005/12/19 05:18:26 kent Exp $";
00014 
00015 void xapError(struct xap *xap, char *format, ...)
00016 /* Issue an error message and abort*/
00017 {
00018 va_list args;
00019 va_start(args, format);
00020 vaWarn(format, args);
00021 errAbort("line %d of %s", xpLineIx(xap->xp), xap->fileName);
00022 va_end(args);
00023 }
00024 
00025 static void xapStartTag(void *userData, char *name, char **atts)
00026 /* Handle beginning of a tag. */
00027 {
00028 struct xap *xap = userData;
00029 struct xapStack *stack;
00030 
00031 stack = --xap->stack;
00032 if (stack < xap->stackBuf)
00033     xapError(xap, "xap stack overflow");
00034 ++xap->stackDepth;
00035 if (stack->text == NULL)
00036     stack->text = newDyString(256);
00037 stack->elName = (char*)name;
00038 if (xap->skipDepth == 0)
00039     stack->object = xap->startHandler(xap, (char*)name, (char**)atts);
00040 if (xap->stackDepth == 1)
00041     {
00042     freeMem(xap->topType);
00043     xap->topType = cloneString(stack->elName);
00044     xap->topObject = stack->object;
00045     }
00046 }
00047 
00048 static void xapEndTag(void *userData, char *name, char *text)
00049 /* Handle end of tag. */
00050 {
00051 struct xap *xap = userData;
00052 struct xapStack *stack;
00053 
00054 dyStringAppend(xap->stack->text, text);
00055 if (xap->skipDepth == 0 || xap->skipDepth <= xap->stackDepth)
00056     {
00057     xap->skipDepth = 0;
00058     if (xap->endHandler)
00059         xap->endHandler(xap, (char*)name);
00060     }
00061 stack = xap->stack++;
00062 if (xap->stack > xap->endStack)
00063     xapError(xap, "xap stack underflow");
00064 --xap->stackDepth;
00065 dyStringClear(stack->text);
00066 }
00067 
00068 #ifdef EXPAT
00069 static void xapText(void *userData, char *s, int len)
00070 /* Handle some text. */
00071 {
00072 struct xap *xap = userData;
00073 if (xap->skipDepth == 0)
00074     dyStringAppendN(xap->stack->text, (char *)s, len);
00075 }
00076 #endif /* EXPAT */
00077 
00078 static int xapRead(void *userData, char *buf, int bufSize)
00079 /* Read some text. */
00080 {
00081 struct xap *xap = userData;
00082 return fread(buf, 1, bufSize, xap->f);
00083 }
00084 
00085 struct xap *xapNew(void *(*startHandler)(struct xap *xap, char *name, char **atts),
00086         void (*endHandler)(struct xap *xap, char *name) , char *fileName)
00087 /* Create a new parse stack. */
00088 {
00089 struct xap *xap;
00090 AllocVar(xap);
00091 xap->endStack = xap->stack = xap->stackBuf + ArraySize(xap->stackBuf) - 1;
00092 xap->startHandler = startHandler;
00093 xap->endHandler = endHandler;
00094 xap->xp = xpNew(xap, xapStartTag, xapEndTag, xapRead, fileName);
00095 xap->fileName = cloneString(fileName);
00096 return xap;
00097 }
00098 
00099 void xapFree(struct xap **pXp)
00100 /* Free up a parse stack. */
00101 {
00102 struct xap *xap = *pXp;
00103 if (xap != NULL)
00104     {
00105     struct xapStack *stack;
00106     for (stack = xap->stackBuf; stack < xap->endStack; ++stack)
00107         {
00108         if (stack->text != NULL)
00109            freeDyString(&stack->text);
00110         }
00111     xpFree(&xap->xp);
00112     freeMem(xap->fileName);
00113     freeMem(xap->topType);
00114     freez(pXp);
00115     }
00116 }
00117 
00118 void xapParseFile(struct xap *xap, char *fileName)
00119 /* Open up file and parse it all. */
00120 {
00121 xap->f = mustOpen(fileName, "r");
00122 xpParse(xap->xp);
00123 carefulClose(&xap->f);
00124 }
00125 
00126 void xapIndent(int count, FILE *f)
00127 /* Write out some spaces. */
00128 {
00129 int i;
00130 for (i=0; i<count; ++i)
00131     {
00132     fputc(' ', f);
00133     }
00134 }
00135 
00136 void xapSkip(struct xap *xap)
00137 /* Skip current tag and any children.  Called from startHandler. */
00138 {
00139 xap->skipDepth = xap->stackDepth;
00140 }
00141 
00142 void xapParseAny(char *fileName, char *type, 
00143         void *(*startHandler)(struct xap *xap, char *name, char **atts),
00144         void (*endHandler)(struct xap *xap, char *name),
00145         char **retType, void *retObj)
00146 /* Parse any object out of an XML file. 
00147  * If type parameter is non-NULL, force type.
00148  * example:
00149  *     xapParseAny("file.xml", "das", dasStartHandler, dasEndHandler, &type, &obj); */
00150 {
00151 struct xap *xap = xapNew(startHandler, endHandler, fileName);
00152 void **pObj = retObj;
00153 xapParseFile(xap, fileName);
00154 if (type != NULL && !sameString(xap->topType, type))
00155     xapError(xap, "Got %s, expected %s\n", xap->topType, type);
00156 if (retType != NULL)
00157     *retType = cloneString(xap->topType);
00158 *pObj = xap->topObject;
00159 xapFree(&xap);
00160 }
00161 
00162 struct xap *xapOpen(char *fileName, 
00163         void *(*startHandler)(struct xap *xap, char *name, char **atts),
00164         void (*endHandler)(struct xap *xap, char *name))
00165 /* Open up an xml file, but don't start parsing it yet.
00166  * Instead call xapNext to get the elements you want out of
00167  * the file.  When all done call xapFree. */
00168 {
00169 struct xap *xap = xapNew(startHandler, endHandler, fileName);
00170 xap->f =  mustOpen(fileName, "r");
00171 return xap;
00172 }
00173 
00174 void *xapNext(struct xap *xap, char *tag)
00175 /* Return next item matching tag (and all of it's children). */
00176 {
00177 if (!xpParseNext(xap->xp, tag))
00178     return NULL;
00179 if (!sameString(xap->topType, tag))
00180     errAbort("Expecting %s tag, got %s tag", tag, xap->topType);
00181 return xap->topObject;
00182 }
00183 

Generated on Tue Dec 25 18:39:32 2007 for blat by  doxygen 1.5.2