Add iri_dup; hide implementation details of iri_t.
authormo@ilaven.net <mo@ilaven.net@68b1170a-6346-0410-b79c-01ab32b2924b>
Sun, 23 Nov 2008 22:16:46 +0000 (22:16 +0000)
committermo@ilaven.net <mo@ilaven.net@68b1170a-6346-0410-b79c-01ab32b2924b>
Sun, 23 Nov 2008 22:16:46 +0000 (22:16 +0000)
git-svn-id: http://libiri.googlecode.com/svn/trunk@6 68b1170a-6346-0410-b79c-01ab32b2924b

include/iri.h
libiri/Makefile.am
libiri/destroy.c
libiri/dup.c [new file with mode: 0644]
libiri/p_libiri.h
libiri/parse.c

index 2adefab..32a0fa3 100644 (file)
 #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;
@@ -60,5 +61,6 @@ struct iri_struct
 
 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_ */
index 056f50c..3763392 100644 (file)
@@ -29,7 +29,9 @@ lib_LTLIBRARIES = libiri.la
 
 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
 
index 24bbd8c..ff2533d 100644 (file)
@@ -41,7 +41,7 @@ iri_destroy(iri_t *iri)
 {
        if(NULL != iri)
        {
-               free(iri->_private);
+               free(iri->base);
                free(iri);
        }
 }
diff --git a/libiri/dup.c b/libiri/dup.c
new file mode 100644 (file)
index 0000000..7ce1eb7
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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;
+}
index beb2610..077f27b 100644 (file)
 #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_ */
index d96a350..368e841 100644 (file)
@@ -97,13 +97,14 @@ iri__copychar_decode(char **dest, const char *src, int convert_space)
 }
 
 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 *
@@ -112,17 +113,19 @@ iri_parse(const char *src)
        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, ':');
@@ -134,7 +137,7 @@ iri_parse(const char *src)
        if(colon && !at)
        {
                /* Definitely a scheme */
-               p->scheme = bufp;
+               p->iri.scheme = bufp;
                while(*src && *src != ':')
                {
                        src = iri__copychar_decode(&bufp, src, 0);
@@ -150,7 +153,7 @@ iri_parse(const char *src)
                /* 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);
@@ -160,11 +163,11 @@ iri_parse(const char *src)
                        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 != ';')
                {
@@ -176,7 +179,7 @@ iri_parse(const char *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 */
@@ -189,7 +192,7 @@ iri_parse(const char *src)
                {
                        /* Following password data */
                        src++;
-                       p->password = bufp;
+                       p->iri.password = bufp;
                        while(*src && *src != ':' && *src != '@')
                        {
                                src = iri__copychar_decode(&bufp, src, 0);
@@ -200,8 +203,8 @@ iri_parse(const char *src)
                        {
                                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);
@@ -223,7 +226,7 @@ iri_parse(const char *src)
        else if(at)
        {
                /* user[;auth]@host[/path...] */
-               p->user = bufp;
+               p->iri.user = bufp;
                while(*src != '@' && *src != ';')
                {
                        src = iri__copychar_decode(&bufp, src, 0);
@@ -233,7 +236,7 @@ iri_parse(const char *src)
                if(*src == ';')
                {
                        src++;
-                       p->auth = bufp;
+                       p->iri.auth = bufp;
                        while(*src && *src != '@')
                        {
                                /* Don't decode, so it can be extracted properly */
@@ -247,7 +250,7 @@ iri_parse(const char *src)
                        src++;
                }
        }
-       p->host = bufp;
+       p->iri.host = bufp;
        while(*src && *src != ':' && *src != '/' && *src != '?' && *src != '#')
        {
                src = iri__copychar_decode(&bufp, src, 0);
@@ -259,12 +262,12 @@ iri_parse(const char *src)
                /* 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);
@@ -274,7 +277,7 @@ iri_parse(const char *src)
        }
        if(*src == '?')
        {
-               p->query = bufp; 
+               p->iri.query = bufp; 
                src++;
                while(*src && *src != '#')
                {
@@ -287,7 +290,7 @@ iri_parse(const char *src)
        }
        if(*src == '#')
        {
-               p->anchor = bufp; 
+               p->iri.anchor = bufp; 
                while(*src)
                {
                        src = iri__copychar_decode(&bufp, src, 0);
@@ -298,7 +301,7 @@ iri_parse(const char *src)
        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);