mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
pgindent run on all C files. Java run to follow. initdb/regression
tests pass.
This commit is contained in:
@ -14,32 +14,39 @@ XML_Memory_Handling_Suite mhs;
|
||||
|
||||
/* passthrough functions (palloc is a macro) */
|
||||
|
||||
static void *pgxml_palloc(size_t size)
|
||||
static void *
|
||||
pgxml_palloc(size_t size)
|
||||
{
|
||||
return palloc(size);
|
||||
return palloc(size);
|
||||
}
|
||||
|
||||
static void *pgxml_repalloc(void *ptr, size_t size)
|
||||
static void *
|
||||
pgxml_repalloc(void *ptr, size_t size)
|
||||
{
|
||||
return repalloc(ptr,size);
|
||||
return repalloc(ptr, size);
|
||||
}
|
||||
|
||||
static void pgxml_pfree(void *ptr)
|
||||
static void
|
||||
pgxml_pfree(void *ptr)
|
||||
{
|
||||
return pfree(ptr);
|
||||
return pfree(ptr);
|
||||
}
|
||||
|
||||
static void pgxml_mhs_init()
|
||||
static void
|
||||
pgxml_mhs_init()
|
||||
{
|
||||
mhs.malloc_fcn = pgxml_palloc;
|
||||
mhs.realloc_fcn = pgxml_repalloc;
|
||||
mhs.free_fcn = pgxml_pfree;
|
||||
mhs.malloc_fcn = pgxml_palloc;
|
||||
mhs.realloc_fcn = pgxml_repalloc;
|
||||
mhs.free_fcn = pgxml_pfree;
|
||||
}
|
||||
|
||||
static void pgxml_handler_init()
|
||||
static void
|
||||
pgxml_handler_init()
|
||||
{
|
||||
/* This code should set up the relevant handlers from user-supplied
|
||||
settings. Quite how these settings are made is another matter :) */
|
||||
/*
|
||||
* This code should set up the relevant handlers from user-supplied
|
||||
* settings. Quite how these settings are made is another matter :)
|
||||
*/
|
||||
}
|
||||
|
||||
/* Returns true if document is well-formed */
|
||||
@ -49,31 +56,35 @@ PG_FUNCTION_INFO_V1(pgxml_parse);
|
||||
Datum
|
||||
pgxml_parse(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* called as pgxml_parse(document) */
|
||||
XML_Parser p;
|
||||
text *t = PG_GETARG_TEXT_P(0); /*document buffer */
|
||||
int32 docsize = VARSIZE(t) - VARHDRSZ;
|
||||
/* called as pgxml_parse(document) */
|
||||
XML_Parser p;
|
||||
text *t = PG_GETARG_TEXT_P(0); /* document buffer */
|
||||
int32 docsize = VARSIZE(t) - VARHDRSZ;
|
||||
|
||||
pgxml_mhs_init();
|
||||
pgxml_mhs_init();
|
||||
|
||||
pgxml_handler_init();
|
||||
pgxml_handler_init();
|
||||
|
||||
p = XML_ParserCreate_MM(NULL,&mhs,NULL);
|
||||
if (! p) {
|
||||
elog(ERROR, "pgxml: Could not create expat parser");
|
||||
PG_RETURN_NULL(); /* seems appropriate if we couldn't parse */
|
||||
}
|
||||
p = XML_ParserCreate_MM(NULL, &mhs, NULL);
|
||||
if (!p)
|
||||
{
|
||||
elog(ERROR, "pgxml: Could not create expat parser");
|
||||
PG_RETURN_NULL(); /* seems appropriate if we couldn't parse */
|
||||
}
|
||||
|
||||
if (! XML_Parse(p, (char *)VARDATA(t) , docsize, 1)) {
|
||||
/* elog(NOTICE, "Parse error at line %d:%s",
|
||||
XML_GetCurrentLineNumber(p),
|
||||
XML_ErrorString(XML_GetErrorCode(p))); */
|
||||
XML_ParserFree(p);
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
if (!XML_Parse(p, (char *) VARDATA(t), docsize, 1))
|
||||
{
|
||||
/*
|
||||
* elog(NOTICE, "Parse error at line %d:%s",
|
||||
* XML_GetCurrentLineNumber(p),
|
||||
* XML_ErrorString(XML_GetErrorCode(p)));
|
||||
*/
|
||||
XML_ParserFree(p);
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
XML_ParserFree(p);
|
||||
PG_RETURN_BOOL(true);
|
||||
XML_ParserFree(p);
|
||||
PG_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
/* XPath handling functions */
|
||||
@ -81,83 +92,88 @@ pgxml_parse(PG_FUNCTION_ARGS)
|
||||
/* XPath support here is for a very skeletal kind of XPath!
|
||||
It was easy to program though... */
|
||||
|
||||
/* This first is the core function that builds a result set. The
|
||||
/* This first is the core function that builds a result set. The
|
||||
actual functions called by the user manipulate that result set
|
||||
in various ways.
|
||||
*/
|
||||
|
||||
static XPath_Results *build_xpath_results(text *doc, text *pathstr)
|
||||
static XPath_Results *
|
||||
build_xpath_results(text *doc, text *pathstr)
|
||||
{
|
||||
XPath_Results *xpr;
|
||||
char *res;
|
||||
pgxml_udata *udata;
|
||||
XML_Parser p;
|
||||
int32 docsize;
|
||||
XPath_Results *xpr;
|
||||
char *res;
|
||||
pgxml_udata *udata;
|
||||
XML_Parser p;
|
||||
int32 docsize;
|
||||
|
||||
xpr = (XPath_Results *) palloc((sizeof(XPath_Results)));
|
||||
memset((void *)xpr, 0, sizeof(XPath_Results));
|
||||
xpr->rescount=0;
|
||||
xpr = (XPath_Results *) palloc((sizeof(XPath_Results)));
|
||||
memset((void *) xpr, 0, sizeof(XPath_Results));
|
||||
xpr->rescount = 0;
|
||||
|
||||
docsize=VARSIZE(doc)-VARHDRSZ;
|
||||
docsize = VARSIZE(doc) - VARHDRSZ;
|
||||
|
||||
/* res isn't going to be the real return type, it is just a buffer */
|
||||
/* res isn't going to be the real return type, it is just a buffer */
|
||||
|
||||
res = (char *) palloc(docsize);
|
||||
memset((void *)res, 0, docsize);
|
||||
res = (char *) palloc(docsize);
|
||||
memset((void *) res, 0, docsize);
|
||||
|
||||
xpr->resbuf = res;
|
||||
xpr->resbuf = res;
|
||||
|
||||
udata = (pgxml_udata *) palloc((sizeof(pgxml_udata)));
|
||||
memset((void *)udata,0,sizeof(pgxml_udata));
|
||||
udata = (pgxml_udata *) palloc((sizeof(pgxml_udata)));
|
||||
memset((void *) udata, 0, sizeof(pgxml_udata));
|
||||
|
||||
udata->currentpath[0]='\0';
|
||||
udata->textgrab=0;
|
||||
udata->currentpath[0] = '\0';
|
||||
udata->textgrab = 0;
|
||||
|
||||
udata->path= (char *) palloc(VARSIZE(pathstr));
|
||||
memcpy(udata->path, VARDATA(pathstr), VARSIZE(pathstr)-VARHDRSZ);
|
||||
udata->path = (char *) palloc(VARSIZE(pathstr));
|
||||
memcpy(udata->path, VARDATA(pathstr), VARSIZE(pathstr) - VARHDRSZ);
|
||||
|
||||
udata->path[VARSIZE(pathstr)-VARHDRSZ]='\0';
|
||||
udata->path[VARSIZE(pathstr) - VARHDRSZ] = '\0';
|
||||
|
||||
udata->resptr = res;
|
||||
udata->reslen = 0;
|
||||
udata->resptr = res;
|
||||
udata->reslen = 0;
|
||||
|
||||
udata->xpres = xpr;
|
||||
udata->xpres = xpr;
|
||||
|
||||
/* Now fire up the parser */
|
||||
pgxml_mhs_init();
|
||||
/* Now fire up the parser */
|
||||
pgxml_mhs_init();
|
||||
|
||||
p = XML_ParserCreate_MM(NULL,&mhs,NULL);
|
||||
if (! p) {
|
||||
elog(ERROR, "pgxml: Could not create expat parser");
|
||||
pfree(xpr);
|
||||
pfree(udata->path);
|
||||
pfree(udata);
|
||||
pfree(res);
|
||||
return NULL;
|
||||
}
|
||||
XML_SetUserData(p, (void *)udata);
|
||||
p = XML_ParserCreate_MM(NULL, &mhs, NULL);
|
||||
if (!p)
|
||||
{
|
||||
elog(ERROR, "pgxml: Could not create expat parser");
|
||||
pfree(xpr);
|
||||
pfree(udata->path);
|
||||
pfree(udata);
|
||||
pfree(res);
|
||||
return NULL;
|
||||
}
|
||||
XML_SetUserData(p, (void *) udata);
|
||||
|
||||
/* Set the handlers */
|
||||
/* Set the handlers */
|
||||
|
||||
XML_SetElementHandler(p, pgxml_starthandler, pgxml_endhandler);
|
||||
XML_SetCharacterDataHandler(p, pgxml_charhandler);
|
||||
XML_SetElementHandler(p, pgxml_starthandler, pgxml_endhandler);
|
||||
XML_SetCharacterDataHandler(p, pgxml_charhandler);
|
||||
|
||||
if (! XML_Parse(p, (char *)VARDATA(doc) , docsize, 1)) {
|
||||
/* elog(NOTICE, "Parse error at line %d:%s",
|
||||
XML_GetCurrentLineNumber(p),
|
||||
XML_ErrorString(XML_GetErrorCode(p))); */
|
||||
XML_ParserFree(p);
|
||||
pfree(xpr);
|
||||
pfree(udata->path);
|
||||
pfree(udata);
|
||||
if (!XML_Parse(p, (char *) VARDATA(doc), docsize, 1))
|
||||
{
|
||||
/*
|
||||
* elog(NOTICE, "Parse error at line %d:%s",
|
||||
* XML_GetCurrentLineNumber(p),
|
||||
* XML_ErrorString(XML_GetErrorCode(p)));
|
||||
*/
|
||||
XML_ParserFree(p);
|
||||
pfree(xpr);
|
||||
pfree(udata->path);
|
||||
pfree(udata);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pfree(udata->path);
|
||||
pfree(udata);
|
||||
XML_ParserFree(p);
|
||||
return xpr;
|
||||
pfree(udata->path);
|
||||
pfree(udata);
|
||||
XML_ParserFree(p);
|
||||
return xpr;
|
||||
}
|
||||
|
||||
|
||||
@ -166,145 +182,166 @@ PG_FUNCTION_INFO_V1(pgxml_xpath);
|
||||
Datum
|
||||
pgxml_xpath(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* called as pgxml_xpath(document,pathstr, index) for the moment*/
|
||||
/* called as pgxml_xpath(document,pathstr, index) for the moment */
|
||||
|
||||
XPath_Results *xpresults;
|
||||
text *restext;
|
||||
XPath_Results *xpresults;
|
||||
text *restext;
|
||||
|
||||
text *t = PG_GETARG_TEXT_P(0); /*document buffer */
|
||||
text *t2= PG_GETARG_TEXT_P(1);
|
||||
int32 ind = PG_GETARG_INT32(2) - 1;
|
||||
text *t = PG_GETARG_TEXT_P(0); /* document buffer */
|
||||
text *t2 = PG_GETARG_TEXT_P(1);
|
||||
int32 ind = PG_GETARG_INT32(2) - 1;
|
||||
|
||||
xpresults = build_xpath_results(t,t2);
|
||||
xpresults = build_xpath_results(t, t2);
|
||||
|
||||
/* This needs to be changed depending on the mechanism for returning
|
||||
our set of results. */
|
||||
/*
|
||||
* This needs to be changed depending on the mechanism for returning
|
||||
* our set of results.
|
||||
*/
|
||||
|
||||
if (xpresults==NULL) /*parse error (not WF or parser failure) */
|
||||
{
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
if (xpresults == NULL) /* parse error (not WF or parser failure) */
|
||||
PG_RETURN_NULL();
|
||||
|
||||
if (ind >= (xpresults->rescount))
|
||||
{
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
restext = (text *) palloc(xpresults->reslens[ind]+VARHDRSZ);
|
||||
memcpy(VARDATA(restext),xpresults->results[ind],xpresults->reslens[ind]);
|
||||
if (ind >= (xpresults->rescount))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
VARATT_SIZEP(restext) = xpresults->reslens[ind]+VARHDRSZ;
|
||||
restext = (text *) palloc(xpresults->reslens[ind] + VARHDRSZ);
|
||||
memcpy(VARDATA(restext), xpresults->results[ind], xpresults->reslens[ind]);
|
||||
|
||||
pfree(xpresults->resbuf);
|
||||
pfree(xpresults);
|
||||
VARATT_SIZEP(restext) = xpresults->reslens[ind] + VARHDRSZ;
|
||||
|
||||
PG_RETURN_TEXT_P(restext);
|
||||
pfree(xpresults->resbuf);
|
||||
pfree(xpresults);
|
||||
|
||||
PG_RETURN_TEXT_P(restext);
|
||||
}
|
||||
|
||||
|
||||
static void pgxml_pathcompare(void *userData)
|
||||
static void
|
||||
pgxml_pathcompare(void *userData)
|
||||
{
|
||||
char *matchpos;
|
||||
char *matchpos;
|
||||
|
||||
matchpos=strstr(UD->currentpath, UD->path);
|
||||
matchpos = strstr(UD->currentpath, UD->path);
|
||||
|
||||
if (matchpos == NULL) { /* Should we have more logic here ? */
|
||||
if (UD->textgrab) {
|
||||
UD->textgrab=0;
|
||||
pgxml_finalisegrabbedtext(userData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* OK, we have a match of some sort. Now we need to check that
|
||||
our match is anchored to the *end* of the string AND
|
||||
that it is immediately preceded by a '/'*/
|
||||
/* This test wouldn't work if strlen (UD->path) overran the length
|
||||
of the currentpath, but that's not possible because we got a match! */
|
||||
|
||||
if ((matchpos + strlen(UD->path))[0]=='\0')
|
||||
{
|
||||
if ((UD->path)[0]=='/') {
|
||||
if (matchpos == UD->currentpath) {
|
||||
UD->textgrab=1;
|
||||
if (matchpos == NULL)
|
||||
{ /* Should we have more logic here ? */
|
||||
if (UD->textgrab)
|
||||
{
|
||||
UD->textgrab = 0;
|
||||
pgxml_finalisegrabbedtext(userData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ((matchpos-1)[0]=='/') {
|
||||
UD->textgrab=1;
|
||||
|
||||
/*
|
||||
* OK, we have a match of some sort. Now we need to check that our
|
||||
* match is anchored to the *end* of the string AND that it is
|
||||
* immediately preceded by a '/'
|
||||
*/
|
||||
|
||||
/*
|
||||
* This test wouldn't work if strlen (UD->path) overran the length of
|
||||
* the currentpath, but that's not possible because we got a match!
|
||||
*/
|
||||
|
||||
if ((matchpos + strlen(UD->path))[0] == '\0')
|
||||
{
|
||||
if ((UD->path)[0] == '/')
|
||||
{
|
||||
if (matchpos == UD->currentpath)
|
||||
UD->textgrab = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((matchpos - 1)[0] == '/')
|
||||
UD->textgrab = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pgxml_starthandler(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts)
|
||||
static void
|
||||
pgxml_starthandler(void *userData, const XML_Char * name,
|
||||
const XML_Char ** atts)
|
||||
{
|
||||
|
||||
char sepstr[]="/";
|
||||
char sepstr[] = "/";
|
||||
|
||||
if ((strlen(name)+strlen(UD->currentpath))>MAXPATHLENGTH-2) {
|
||||
elog(NOTICE,"Path too long");
|
||||
} else {
|
||||
strncat(UD->currentpath,sepstr,1);
|
||||
strcat(UD->currentpath, name);
|
||||
}
|
||||
if (UD->textgrab)
|
||||
{
|
||||
/* Depending on user preference, should we "reconstitute"
|
||||
the element into the result text?
|
||||
*/
|
||||
} else {
|
||||
pgxml_pathcompare(userData);
|
||||
}
|
||||
if ((strlen(name) + strlen(UD->currentpath)) > MAXPATHLENGTH - 2)
|
||||
elog(NOTICE, "Path too long");
|
||||
else
|
||||
{
|
||||
strncat(UD->currentpath, sepstr, 1);
|
||||
strcat(UD->currentpath, name);
|
||||
}
|
||||
if (UD->textgrab)
|
||||
{
|
||||
/*
|
||||
* Depending on user preference, should we "reconstitute" the
|
||||
* element into the result text?
|
||||
*/
|
||||
}
|
||||
else
|
||||
pgxml_pathcompare(userData);
|
||||
}
|
||||
|
||||
static void pgxml_endhandler(void *userData, const XML_Char *name)
|
||||
static void
|
||||
pgxml_endhandler(void *userData, const XML_Char * name)
|
||||
{
|
||||
/* Start by removing the current element off the end of the
|
||||
currentpath */
|
||||
/*
|
||||
* Start by removing the current element off the end of the
|
||||
* currentpath
|
||||
*/
|
||||
|
||||
char *sepptr;
|
||||
char *sepptr;
|
||||
|
||||
sepptr=strrchr(UD->currentpath,'/');
|
||||
if (sepptr==NULL) {
|
||||
elog(ERROR,"There's a problem...");
|
||||
sepptr=UD->currentpath;
|
||||
}
|
||||
if (strcmp(name, sepptr+1) !=0) {
|
||||
elog(NOTICE,"Wanted [%s], got [%s]",sepptr,name);
|
||||
/* unmatched entry, so do nothing */
|
||||
} else {
|
||||
sepptr[0]='\0'; /* Chop that element off the end */
|
||||
}
|
||||
sepptr = strrchr(UD->currentpath, '/');
|
||||
if (sepptr == NULL)
|
||||
{
|
||||
elog(ERROR, "There's a problem...");
|
||||
sepptr = UD->currentpath;
|
||||
}
|
||||
if (strcmp(name, sepptr + 1) != 0)
|
||||
{
|
||||
elog(NOTICE, "Wanted [%s], got [%s]", sepptr, name);
|
||||
/* unmatched entry, so do nothing */
|
||||
}
|
||||
else
|
||||
{
|
||||
sepptr[0] = '\0'; /* Chop that element off the end */
|
||||
}
|
||||
|
||||
if (UD->textgrab) {
|
||||
pgxml_pathcompare(userData);
|
||||
}
|
||||
if (UD->textgrab)
|
||||
pgxml_pathcompare(userData);
|
||||
|
||||
}
|
||||
|
||||
static void pgxml_charhandler(void *userData, const XML_Char *s, int len)
|
||||
static void
|
||||
pgxml_charhandler(void *userData, const XML_Char * s, int len)
|
||||
{
|
||||
if (UD->textgrab) {
|
||||
if (len>0) {
|
||||
memcpy(UD->resptr,s,len);
|
||||
UD->resptr += len;
|
||||
UD->reslen += len;
|
||||
}
|
||||
}
|
||||
if (UD->textgrab)
|
||||
{
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(UD->resptr, s, len);
|
||||
UD->resptr += len;
|
||||
UD->reslen += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Should I be using PG list types here? */
|
||||
|
||||
static void pgxml_finalisegrabbedtext(void *userData)
|
||||
static void
|
||||
pgxml_finalisegrabbedtext(void *userData)
|
||||
{
|
||||
/* In res/reslen, we have a single result. */
|
||||
UD->xpres->results[UD->xpres->rescount]= UD->resptr - UD->reslen;
|
||||
UD->xpres->reslens[UD->xpres->rescount]= UD->reslen;
|
||||
UD->reslen=0;
|
||||
UD->xpres->rescount++;
|
||||
/* In res/reslen, we have a single result. */
|
||||
UD->xpres->results[UD->xpres->rescount] = UD->resptr - UD->reslen;
|
||||
UD->xpres->reslens[UD->xpres->rescount] = UD->reslen;
|
||||
UD->reslen = 0;
|
||||
UD->xpres->rescount++;
|
||||
|
||||
/* This effectively concatenates all the results together but we
|
||||
do know where one ends and the next begins */
|
||||
/*
|
||||
* This effectively concatenates all the results together but we do
|
||||
* know where one ends and the next begins
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -5,12 +5,12 @@ static void *pgxml_repalloc(void *ptr, size_t size);
|
||||
static void pgxml_pfree(void *ptr);
|
||||
static void pgxml_mhs_init();
|
||||
static void pgxml_handler_init();
|
||||
Datum pgxml_parse(PG_FUNCTION_ARGS);
|
||||
Datum pgxml_xpath(PG_FUNCTION_ARGS);
|
||||
static void pgxml_starthandler(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts);
|
||||
static void pgxml_endhandler(void *userData, const XML_Char *name);
|
||||
static void pgxml_charhandler(void *userData, const XML_Char *s, int len);
|
||||
Datum pgxml_parse(PG_FUNCTION_ARGS);
|
||||
Datum pgxml_xpath(PG_FUNCTION_ARGS);
|
||||
static void pgxml_starthandler(void *userData, const XML_Char * name,
|
||||
const XML_Char ** atts);
|
||||
static void pgxml_endhandler(void *userData, const XML_Char * name);
|
||||
static void pgxml_charhandler(void *userData, const XML_Char * s, int len);
|
||||
static void pgxml_pathcompare(void *userData);
|
||||
static void pgxml_finalisegrabbedtext(void *userData);
|
||||
|
||||
@ -18,43 +18,25 @@ static void pgxml_finalisegrabbedtext(void *userData);
|
||||
#define MAXRESULTS 100
|
||||
|
||||
|
||||
typedef struct {
|
||||
int rescount;
|
||||
char *results[MAXRESULTS];
|
||||
int32 reslens[MAXRESULTS];
|
||||
char *resbuf; /* pointer to the result buffer for pfree */
|
||||
} XPath_Results;
|
||||
typedef struct
|
||||
{
|
||||
int rescount;
|
||||
char *results[MAXRESULTS];
|
||||
int32 reslens[MAXRESULTS];
|
||||
char *resbuf; /* pointer to the result buffer for pfree */
|
||||
} XPath_Results;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
char currentpath[MAXPATHLENGTH];
|
||||
char *path;
|
||||
int textgrab;
|
||||
char *resptr;
|
||||
int32 reslen;
|
||||
XPath_Results *xpres;
|
||||
} pgxml_udata;
|
||||
typedef struct
|
||||
{
|
||||
char currentpath[MAXPATHLENGTH];
|
||||
char *path;
|
||||
int textgrab;
|
||||
char *resptr;
|
||||
int32 reslen;
|
||||
XPath_Results *xpres;
|
||||
} pgxml_udata;
|
||||
|
||||
|
||||
#define UD ((pgxml_udata *) userData)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -15,50 +15,57 @@
|
||||
static void *pgxml_palloc(size_t size);
|
||||
static void *pgxml_repalloc(void *ptr, size_t size);
|
||||
static void pgxml_pfree(void *ptr);
|
||||
static char *pgxml_pstrdup(const char* string);
|
||||
static char *pgxml_pstrdup(const char *string);
|
||||
|
||||
static void pgxml_parser_init();
|
||||
|
||||
static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlDocPtr doc,
|
||||
xmlChar *toptagname, xmlChar *septagname,
|
||||
static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlDocPtr doc,
|
||||
xmlChar * toptagname, xmlChar * septagname,
|
||||
int format);
|
||||
|
||||
static xmlChar *pgxml_texttoxmlchar(text *textstring);
|
||||
|
||||
|
||||
Datum pgxml_parse(PG_FUNCTION_ARGS);
|
||||
Datum pgxml_xpath(PG_FUNCTION_ARGS);
|
||||
Datum pgxml_parse(PG_FUNCTION_ARGS);
|
||||
Datum pgxml_xpath(PG_FUNCTION_ARGS);
|
||||
|
||||
/* memory handling passthrough functions (e.g. palloc, pstrdup are
|
||||
currently macros, and the others might become so...) */
|
||||
|
||||
static void *pgxml_palloc(size_t size)
|
||||
static void *
|
||||
pgxml_palloc(size_t size)
|
||||
{
|
||||
return palloc(size);
|
||||
return palloc(size);
|
||||
}
|
||||
|
||||
static void *pgxml_repalloc(void *ptr, size_t size)
|
||||
static void *
|
||||
pgxml_repalloc(void *ptr, size_t size)
|
||||
{
|
||||
return repalloc(ptr,size);
|
||||
return repalloc(ptr, size);
|
||||
}
|
||||
|
||||
static void pgxml_pfree(void *ptr)
|
||||
static void
|
||||
pgxml_pfree(void *ptr)
|
||||
{
|
||||
return pfree(ptr);
|
||||
return pfree(ptr);
|
||||
}
|
||||
|
||||
static char *pgxml_pstrdup(const char *string)
|
||||
static char *
|
||||
pgxml_pstrdup(const char *string)
|
||||
{
|
||||
return pstrdup(string);
|
||||
return pstrdup(string);
|
||||
}
|
||||
|
||||
static void pgxml_parser_init()
|
||||
static void
|
||||
pgxml_parser_init()
|
||||
{
|
||||
/* This code should also set parser settings from user-supplied
|
||||
info. Quite how these settings are made is another matter :) */
|
||||
/*
|
||||
* This code should also set parser settings from user-supplied info.
|
||||
* Quite how these settings are made is another matter :)
|
||||
*/
|
||||
|
||||
xmlMemSetup(pgxml_pfree, pgxml_palloc, pgxml_repalloc, pgxml_pstrdup);
|
||||
xmlInitParser();
|
||||
xmlMemSetup(pgxml_pfree, pgxml_palloc, pgxml_repalloc, pgxml_pstrdup);
|
||||
xmlInitParser();
|
||||
|
||||
}
|
||||
|
||||
@ -70,86 +77,98 @@ PG_FUNCTION_INFO_V1(pgxml_parse);
|
||||
Datum
|
||||
pgxml_parse(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* called as pgxml_parse(document) */
|
||||
xmlDocPtr doctree;
|
||||
text *t = PG_GETARG_TEXT_P(0); /*document buffer */
|
||||
int32 docsize = VARSIZE(t) - VARHDRSZ;
|
||||
/* called as pgxml_parse(document) */
|
||||
xmlDocPtr doctree;
|
||||
text *t = PG_GETARG_TEXT_P(0); /* document buffer */
|
||||
int32 docsize = VARSIZE(t) - VARHDRSZ;
|
||||
|
||||
pgxml_parser_init();
|
||||
pgxml_parser_init();
|
||||
|
||||
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
|
||||
if (doctree == NULL) {
|
||||
/* xmlCleanupParser(); */
|
||||
PG_RETURN_BOOL(false); /* i.e. not well-formed */
|
||||
}
|
||||
/* xmlCleanupParser(); */
|
||||
xmlFreeDoc(doctree);
|
||||
PG_RETURN_BOOL(true);
|
||||
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
|
||||
if (doctree == NULL)
|
||||
{
|
||||
/* xmlCleanupParser(); */
|
||||
PG_RETURN_BOOL(false); /* i.e. not well-formed */
|
||||
}
|
||||
/* xmlCleanupParser(); */
|
||||
xmlFreeDoc(doctree);
|
||||
PG_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
static xmlChar
|
||||
*pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
|
||||
xmlDocPtr doc,
|
||||
xmlChar *toptagname,
|
||||
xmlChar *septagname,
|
||||
int format)
|
||||
static xmlChar
|
||||
*
|
||||
pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
|
||||
xmlDocPtr doc,
|
||||
xmlChar * toptagname,
|
||||
xmlChar * septagname,
|
||||
int format)
|
||||
{
|
||||
/* Function translates a nodeset into a text representation */
|
||||
/* iterates over each node in the set and calls xmlNodeDump to write
|
||||
it to an xmlBuffer -from which an xmlChar * string is returned. */
|
||||
/* each representation is surrounded by <tagname> ... </tagname> */
|
||||
/* if format==0, add a newline between nodes?? */
|
||||
/* Function translates a nodeset into a text representation */
|
||||
|
||||
xmlBufferPtr buf;
|
||||
xmlChar *result;
|
||||
int i;
|
||||
/*
|
||||
* iterates over each node in the set and calls xmlNodeDump to write
|
||||
* it to an xmlBuffer -from which an xmlChar * string is returned.
|
||||
*/
|
||||
/* each representation is surrounded by <tagname> ... </tagname> */
|
||||
/* if format==0, add a newline between nodes?? */
|
||||
|
||||
buf =xmlBufferCreate();
|
||||
|
||||
if ((toptagname != NULL) && (xmlStrlen(toptagname)>0)) {
|
||||
xmlBufferWriteChar(buf,"<");
|
||||
xmlBufferWriteCHAR(buf,toptagname);
|
||||
xmlBufferWriteChar(buf,">");
|
||||
}
|
||||
if (nodeset != NULL) {
|
||||
for (i=0; i < nodeset->nodeNr; i++) {
|
||||
if ((septagname != NULL) && (xmlStrlen(septagname)>0)) {
|
||||
xmlBufferWriteChar(buf,"<");
|
||||
xmlBufferWriteCHAR(buf,septagname);
|
||||
xmlBufferWriteChar(buf,">");
|
||||
}
|
||||
xmlNodeDump(buf, doc, nodeset->nodeTab[i],1,(format==2));
|
||||
|
||||
if ((septagname != NULL) && (xmlStrlen(septagname)>0)) {
|
||||
xmlBufferWriteChar(buf,"</");
|
||||
xmlBufferWriteCHAR(buf,septagname);
|
||||
xmlBufferWriteChar(buf,">");
|
||||
}
|
||||
if (format) {
|
||||
xmlBufferWriteChar(buf,"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlBufferPtr buf;
|
||||
xmlChar *result;
|
||||
int i;
|
||||
|
||||
if ((toptagname != NULL) && (xmlStrlen(toptagname)>0)) {
|
||||
xmlBufferWriteChar(buf,"</");
|
||||
xmlBufferWriteCHAR(buf,toptagname);
|
||||
xmlBufferWriteChar(buf,">");
|
||||
}
|
||||
result = xmlStrdup(buf->content);
|
||||
xmlBufferFree(buf);
|
||||
return result;
|
||||
buf = xmlBufferCreate();
|
||||
|
||||
if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
|
||||
{
|
||||
xmlBufferWriteChar(buf, "<");
|
||||
xmlBufferWriteCHAR(buf, toptagname);
|
||||
xmlBufferWriteChar(buf, ">");
|
||||
}
|
||||
if (nodeset != NULL)
|
||||
{
|
||||
for (i = 0; i < nodeset->nodeNr; i++)
|
||||
{
|
||||
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
|
||||
{
|
||||
xmlBufferWriteChar(buf, "<");
|
||||
xmlBufferWriteCHAR(buf, septagname);
|
||||
xmlBufferWriteChar(buf, ">");
|
||||
}
|
||||
xmlNodeDump(buf, doc, nodeset->nodeTab[i], 1, (format == 2));
|
||||
|
||||
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
|
||||
{
|
||||
xmlBufferWriteChar(buf, "</");
|
||||
xmlBufferWriteCHAR(buf, septagname);
|
||||
xmlBufferWriteChar(buf, ">");
|
||||
}
|
||||
if (format)
|
||||
xmlBufferWriteChar(buf, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
|
||||
{
|
||||
xmlBufferWriteChar(buf, "</");
|
||||
xmlBufferWriteCHAR(buf, toptagname);
|
||||
xmlBufferWriteChar(buf, ">");
|
||||
}
|
||||
result = xmlStrdup(buf->content);
|
||||
xmlBufferFree(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
static xmlChar *pgxml_texttoxmlchar(text *textstring) {
|
||||
xmlChar *res;
|
||||
int32 txsize;
|
||||
static xmlChar *
|
||||
pgxml_texttoxmlchar(text *textstring)
|
||||
{
|
||||
xmlChar *res;
|
||||
int32 txsize;
|
||||
|
||||
txsize=VARSIZE(textstring)-VARHDRSZ;
|
||||
res = (xmlChar *) palloc(txsize+1);
|
||||
memcpy((char *)res, VARDATA(textstring), txsize);
|
||||
res[txsize]='\0';
|
||||
return res;
|
||||
txsize = VARSIZE(textstring) - VARHDRSZ;
|
||||
res = (xmlChar *) palloc(txsize + 1);
|
||||
memcpy((char *) res, VARDATA(textstring), txsize);
|
||||
res[txsize] = '\0';
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -158,81 +177,86 @@ PG_FUNCTION_INFO_V1(pgxml_xpath);
|
||||
Datum
|
||||
pgxml_xpath(PG_FUNCTION_ARGS)
|
||||
{
|
||||
xmlDocPtr doctree;
|
||||
xmlXPathContextPtr ctxt;
|
||||
xmlXPathObjectPtr res;
|
||||
xmlChar *xpath, *xpresstr, *toptag, *septag;
|
||||
xmlXPathCompExprPtr comppath;
|
||||
xmlDocPtr doctree;
|
||||
xmlXPathContextPtr ctxt;
|
||||
xmlXPathObjectPtr res;
|
||||
xmlChar *xpath,
|
||||
*xpresstr,
|
||||
*toptag,
|
||||
*septag;
|
||||
xmlXPathCompExprPtr comppath;
|
||||
|
||||
int32 docsize,ressize;
|
||||
text *t, *xpres;
|
||||
int32 docsize,
|
||||
ressize;
|
||||
text *t,
|
||||
*xpres;
|
||||
|
||||
t = PG_GETARG_TEXT_P(0); /*document buffer */
|
||||
xpath = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(1)); /* XPath expression */
|
||||
toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
|
||||
septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
|
||||
|
||||
docsize = VARSIZE(t) - VARHDRSZ;
|
||||
t = PG_GETARG_TEXT_P(0); /* document buffer */
|
||||
xpath = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(1)); /* XPath expression */
|
||||
toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
|
||||
septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
|
||||
|
||||
pgxml_parser_init();
|
||||
docsize = VARSIZE(t) - VARHDRSZ;
|
||||
|
||||
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
|
||||
if (doctree == NULL) { /* not well-formed */
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
pgxml_parser_init();
|
||||
|
||||
ctxt = xmlXPathNewContext(doctree);
|
||||
ctxt->node = xmlDocGetRootElement(doctree);
|
||||
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
|
||||
if (doctree == NULL)
|
||||
{ /* not well-formed */
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
/* compile the path */
|
||||
comppath = xmlXPathCompile(xpath);
|
||||
if (comppath == NULL) {
|
||||
elog(NOTICE, "XPath syntax error");
|
||||
xmlFreeDoc(doctree);
|
||||
pfree((void *) xpath);
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
ctxt = xmlXPathNewContext(doctree);
|
||||
ctxt->node = xmlDocGetRootElement(doctree);
|
||||
|
||||
/* Now evaluate the path expression. */
|
||||
res = xmlXPathCompiledEval(comppath,ctxt);
|
||||
xmlXPathFreeCompExpr(comppath);
|
||||
/* compile the path */
|
||||
comppath = xmlXPathCompile(xpath);
|
||||
if (comppath == NULL)
|
||||
{
|
||||
elog(NOTICE, "XPath syntax error");
|
||||
xmlFreeDoc(doctree);
|
||||
pfree((void *) xpath);
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
if (res==NULL) {
|
||||
xmlFreeDoc(doctree);
|
||||
pfree((void *)xpath);
|
||||
PG_RETURN_NULL(); /* seems appropriate */
|
||||
}
|
||||
/* now we dump this node, ?surrounding by tags? */
|
||||
/* To do this, we look first at the type */
|
||||
switch(res->type) {
|
||||
case XPATH_NODESET:
|
||||
xpresstr = pgxmlNodeSetToText(res->nodesetval,
|
||||
doctree,
|
||||
toptag, septag, 0);
|
||||
break;
|
||||
case XPATH_STRING:
|
||||
xpresstr = xmlStrdup(res->stringval);
|
||||
break;
|
||||
default:
|
||||
elog(NOTICE,"Unsupported XQuery result: %d",res->type);
|
||||
xpresstr = xmlStrdup("<unsupported/>");
|
||||
}
|
||||
|
||||
/* Now evaluate the path expression. */
|
||||
res = xmlXPathCompiledEval(comppath, ctxt);
|
||||
xmlXPathFreeCompExpr(comppath);
|
||||
|
||||
/* Now convert this result back to text */
|
||||
ressize = strlen(xpresstr);
|
||||
xpres = (text *) palloc(ressize+VARHDRSZ);
|
||||
memcpy(VARDATA(xpres),xpresstr,ressize);
|
||||
VARATT_SIZEP(xpres)=ressize + VARHDRSZ;
|
||||
if (res == NULL)
|
||||
{
|
||||
xmlFreeDoc(doctree);
|
||||
pfree((void *) xpath);
|
||||
PG_RETURN_NULL(); /* seems appropriate */
|
||||
}
|
||||
/* now we dump this node, ?surrounding by tags? */
|
||||
/* To do this, we look first at the type */
|
||||
switch (res->type)
|
||||
{
|
||||
case XPATH_NODESET:
|
||||
xpresstr = pgxmlNodeSetToText(res->nodesetval,
|
||||
doctree,
|
||||
toptag, septag, 0);
|
||||
break;
|
||||
case XPATH_STRING:
|
||||
xpresstr = xmlStrdup(res->stringval);
|
||||
break;
|
||||
default:
|
||||
elog(NOTICE, "Unsupported XQuery result: %d", res->type);
|
||||
xpresstr = xmlStrdup("<unsupported/>");
|
||||
}
|
||||
|
||||
/* Free various storage */
|
||||
xmlFreeDoc(doctree);
|
||||
pfree((void *) xpath);
|
||||
xmlFree(xpresstr);
|
||||
|
||||
PG_RETURN_TEXT_P(xpres);
|
||||
/* Now convert this result back to text */
|
||||
ressize = strlen(xpresstr);
|
||||
xpres = (text *) palloc(ressize + VARHDRSZ);
|
||||
memcpy(VARDATA(xpres), xpresstr, ressize);
|
||||
VARATT_SIZEP(xpres) = ressize + VARHDRSZ;
|
||||
|
||||
/* Free various storage */
|
||||
xmlFreeDoc(doctree);
|
||||
pfree((void *) xpath);
|
||||
xmlFree(xpresstr);
|
||||
|
||||
PG_RETURN_TEXT_P(xpres);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user