#ifndef IRI_H_
# define IRI_H_ 1
+# if !defined(LIBIRI_INTERNAL)
typedef struct iri_struct iri_t;
+# endif
struct iri_struct
{
- void *_private;
const char *display;
const char *scheme;
const char *user;
EXTERNC_ iri_t *iri_parse(const char *src);
EXTERNC_ void iri_destroy(iri_t *iri);
+EXTERNC_ iri_t *iri_dup(iri_t *iri);
#endif /* !IRI_H_ */
libiri_la_LDFLAGS = -avoid-version
+libiri_la_CPPFLAGS = -DLIBIRI_INTERNAL=1
+
libiri_la_SOURCES = \
p_libiri.h \
- parse.c destroy.c
+ parse.c destroy.c dup.c
{
if(NULL != iri)
{
- free(iri->_private);
+ free(iri->base);
free(iri);
}
}
--- /dev/null
+/*
+ * libiri: An IRI/URI/URL parsing library
+ * @(#) $Id$
+ */
+
+/*
+ * Copyright (c) 2005, 2008 Mo McRoberts.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the author(s) of this software may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * AUTHORS OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "p_libiri.h"
+
+static inline void
+iri__dupcopy(const char **dest, const char *src, const char *srcbase, size_t buflen, const char *destbase)
+{
+ if(NULL == src)
+ {
+ *dest = NULL;
+ }
+ else if(src >= srcbase && src <= srcbase + buflen)
+ {
+ *dest = destbase + (src - srcbase);
+ }
+ else
+ {
+ *dest = strdup(src);
+ }
+}
+
+iri_t *
+iri_dup(iri_t *iri)
+{
+ iri_t *p;
+
+ if(NULL == (p = (iri_t *) calloc(1, sizeof(iri_t))))
+ {
+ return NULL;
+ }
+ if(NULL == (p->base = (char *) calloc(1, iri->nbytes)))
+ {
+ free(p);
+ return NULL;
+ }
+ p->nbytes = iri->nbytes;
+ p->iri.port = iri->iri.port;
+ memcpy(p->base, iri->base, p->nbytes);
+ iri__dupcopy(&(p->iri.display), iri->iri.display, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.scheme), iri->iri.scheme, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.user), iri->iri.user, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.auth), iri->iri.auth, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.password), iri->iri.password, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.host), iri->iri.host, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.path), iri->iri.path, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.query), iri->iri.query, iri->base, iri->nbytes, p->base);
+ iri__dupcopy(&(p->iri.anchor), iri->iri.anchor, iri->base, iri->nbytes, p->base);
+ return p;
+}
#include <string.h>
#include <ctype.h>
+typedef struct iri_internal_struct iri_t;
+
#include "iri.h"
-#endif /* !P_LIBIRI_H_ */
\ No newline at end of file
+struct iri_internal_struct
+{
+ struct iri_struct iri;
+ void *base;
+ size_t nbytes;
+};
+
+#endif /* !P_LIBIRI_H_ */
}
static inline char *
-iri__allocbuf(const char *src)
+iri__allocbuf(const char *src, size_t *len)
{
/* Calculate the size of the buffer required to hold a decoded version of
* src, including enough breathing space for null bytes.
*/
/* XXX: This is way too much; we need to actually count it */
- return (char *) calloc(1, (strlen(src) * 4) + 16);
+ *len = (strlen(src) * 4) + 16;
+ return (char *) calloc(1, *len);
}
iri_t *
iri_t *p;
char *bufstart, *endp, *bufp;
const char *at, *colon, *slash;
+ size_t buflen;
if(NULL == (p = (iri_t *) calloc(1, sizeof(iri_t))))
{
return NULL;
}
- if(NULL == (bufstart = iri__allocbuf(src)))
+ if(NULL == (bufstart = iri__allocbuf(src, &buflen)))
{
free(p);
return NULL;
}
- p->_private = bufp = bufstart;
+ p->base = bufp = bufstart;
+ p->nbytes = buflen;
at = strchr(src, '@');
slash = strchr(src, '/');
colon = strchr(src, ':');
if(colon && !at)
{
/* Definitely a scheme */
- p->scheme = bufp;
+ p->iri.scheme = bufp;
while(*src && *src != ':')
{
src = iri__copychar_decode(&bufp, src, 0);
/* This could be scheme://user[;auth][:password]@host or [scheme:]user[;auth][:password]@host (urgh) */
if(colon[1] == '/')
{
- p->scheme = bufp;
+ p->iri.scheme = bufp;
while(*src && *src != ':')
{
src = iri__copychar_decode(&bufp, src, 0);
src++;
/* src[0-1] SHOULD == '/' */
for(; *src == '/'; src++);
- p->user = bufp;
+ p->iri.user = bufp;
}
else
{
- p->scheme = bufp;
+ p->iri.scheme = bufp;
}
while(*src && *src != ':' && *src != '@' && *src != ';')
{
{
/* Following authentication parameters */
src++;
- p->auth = bufp;
+ p->iri.auth = bufp;
while(*src && *src != ':' && *src != '@')
{
/* Don't decode, so it can be extracted properly */
{
/* Following password data */
src++;
- p->password = bufp;
+ p->iri.password = bufp;
while(*src && *src != ':' && *src != '@')
{
src = iri__copychar_decode(&bufp, src, 0);
{
src++;
/* It was actually scheme:user:auth@host */
- p->user = p->auth;
- p->password = bufp;
+ p->iri.user = p->iri.auth;
+ p->iri.password = bufp;
while(*src && *src != '@')
{
src = iri__copychar_decode(&bufp, src, 0);
else if(at)
{
/* user[;auth]@host[/path...] */
- p->user = bufp;
+ p->iri.user = bufp;
while(*src != '@' && *src != ';')
{
src = iri__copychar_decode(&bufp, src, 0);
if(*src == ';')
{
src++;
- p->auth = bufp;
+ p->iri.auth = bufp;
while(*src && *src != '@')
{
/* Don't decode, so it can be extracted properly */
src++;
}
}
- p->host = bufp;
+ p->iri.host = bufp;
while(*src && *src != ':' && *src != '/' && *src != '?' && *src != '#')
{
src = iri__copychar_decode(&bufp, src, 0);
/* Port part */
src++;
endp = (char *) src;
- p->port = strtol(src, &endp, 10);
+ p->iri.port = strtol(src, &endp, 10);
src = endp;
}
if(*src == '/')
{
- p->path = bufp;
+ p->iri.path = bufp;
while(*src && *src != '?' && *src != '#')
{
src = iri__copychar_decode(&bufp, src, 0);
}
if(*src == '?')
{
- p->query = bufp;
+ p->iri.query = bufp;
src++;
while(*src && *src != '#')
{
}
if(*src == '#')
{
- p->anchor = bufp;
+ p->iri.anchor = bufp;
while(*src)
{
src = iri__copychar_decode(&bufp, src, 0);
if(*src)
{
/* Still stuff left? It must be a path... of sorts */
- p->path = bufp;
+ p->iri.path = bufp;
while(*src && *src != '?' && *src != '#')
{
src = iri__copychar_decode(&bufp, src, 0);