summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2008-12-15 21:46:27 +0100
committerMartin Nagy <mnagy@redhat.com>2008-12-15 21:46:27 +0100
commit6d2e95e27e6a1d108077296b3fa84e3c7321d8d5 (patch)
treec9708e59b9e0e431fbd89dd6c66d9861bbb2b6bf
parent69409a1ce90a17e8aaf0d6cd1585cbb0926b4c47 (diff)
downloadldap_driver-6d2e95e27e6a1d108077296b3fa84e3c7321d8d5.tar.gz
ldap_driver-6d2e95e27e6a1d108077296b3fa84e3c7321d8d5.tar.xz
ldap_driver-6d2e95e27e6a1d108077296b3fa84e3c7321d8d5.zip
Add a string library.
-rw-r--r--Makefile5
-rw-r--r--str.c305
-rw-r--r--str.h56
3 files changed, 365 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 22cea06..f2d24ea 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ LIBMINOR = 0
LIBNAME = libdnsldap.so.$(LIBMAJOR).$(LIBMINOR).0
LIBSONAME = libdnsldap.so.$(LIBMAJOR)
-LIBSOURCES = ldap_driver.c semaphore.o log.o
+LIBSOURCES = ldap_driver.c semaphore.o log.o str.o
ALL_CFLAGS = -Wall -Wextra -pedantic -std=c99 -g -fPIC $(CFLAGS)
@@ -23,3 +23,6 @@ semaphore.o: semaphore.c
log.o: log.c
$(CC) $(ALL_CFLAGS) -c $+ -o $@
+
+str.o: str.c
+ $(CC) $(ALL_CFLAGS) -c $+ -o $@
diff --git a/str.c b/str.c
new file mode 100644
index 0000000..4655320
--- /dev/null
+++ b/str.c
@@ -0,0 +1,305 @@
+/* Authors: Martin Nagy <mnagy@redhat.com>
+ *
+ * Copyright (C) 2008 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * TODO:
+ * Write some test cases.
+ *
+ * Review all the REQUIRE() macros.
+ */
+
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+
+#include <string.h>
+
+#include "str.h"
+
+
+#define IGNORE(expr) if (expr) return
+#define IGNORE_R(expr) if (expr) return ISC_R_SUCCESS
+
+#define ALLOC_BASE_SIZE 16
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto cleanup; \
+ } while (0)
+
+
+/* Custom string, these shouldn't use these directly */
+struct ld_string {
+ char *data; /* String is stored here. */
+ size_t allocated; /* Number of bytes allocated. */
+ isc_mem_t *mctx; /* Memory context. */
+#if ISC_MEM_TRACKLINES
+ const char *file; /* File where the allocation occured. */
+ int line; /* Line in the file. */
+#endif
+};
+
+
+/*
+ * Private functions.
+ */
+
+
+/*
+ * Make sure we have enough space for at least len + 1 bytes.
+ * This function is private.
+ */
+static isc_result_t
+str_alloc(ld_string_t *str, size_t len)
+{
+ size_t new_size;
+ char *new_buffer;
+
+ REQUIRE(str != NULL);
+ IGNORE_R(str->allocated > len);
+
+ len++; /* Account for the last '\0'. */
+ new_size = ISC_MAX(str->allocated, ALLOC_BASE_SIZE);
+ while (new_size <= len)
+ new_size *= 2;
+
+ new_size *= sizeof (char);
+#if ISC_MEM_TRACKLINES
+ new_buffer = isc__mem_get(str->mctx, new_size, str->file, str->line);
+#else
+ new_buffer = isc_mem_get(str->mctx, new_size);
+#endif
+
+ if (new_buffer == NULL)
+ return ISC_R_NOMEMORY;
+
+ if (str->data != NULL) {
+ strncpy(new_buffer, str->data, len);
+ new_buffer[len] = '\0';
+ isc_mem_put(str->mctx, str->data, new_size);
+ } else {
+ new_buffer[0] = '\0';
+ }
+
+ str->data = new_buffer;
+
+ return ISC_R_SUCCESS;
+}
+
+/*
+ * Return length of a string. This function is internal, we may decide to
+ * implement caching of the string length in the future for performance
+ * reasons.
+ */
+static size_t
+str_len_internal(const ld_string_t *str)
+{
+ REQUIRE(str != NULL);
+
+ if (str->allocated == 0)
+ return 0;
+
+ return strlen(str->data);
+}
+
+
+/*
+ * Public functions.
+ */
+
+
+/*
+ * Allocate a new string.
+ */
+isc_result_t
+str__new(isc_mem_t *mctx, ld_string_t **new_str _STR_MEM_FLARG)
+{
+ ld_string_t *str;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(new_str != NULL && *new_str == NULL);
+
+#if ISC_MEM_TRACKLINES
+ str = isc__mem_get(mctx, sizeof(ld_string_t), file, line);
+#else
+ str = isc_mem_get(mctx, sizeof(ld_string_t));
+#endif
+ if (str == NULL)
+ return ISC_R_NOMEMORY;
+
+ str->data = NULL;
+ str->allocated = 0;
+ str->mctx = NULL;
+
+ isc_mem_attach(mctx, &str->mctx);
+
+#if ISC_MEM_TRACKLINES
+ str->file = file;
+ str->line = line;
+#endif
+
+ *new_str = str;
+
+ return ISC_R_SUCCESS;
+}
+
+/*
+ * Destroy string, i.e. also free the ld_string_t struct.
+ */
+void
+str__destroy(ld_string_t **str _STR_MEM_FLARG)
+{
+ IGNORE(str == NULL || *str == NULL);
+
+#if ISC_MEM_TRACKLINES
+ isc__mem_put((*str)->mctx, (void *)(*str)->data,
+ (*str)->allocated * sizeof(char), file, line);
+ isc__mem_putanddetach(&(*str)->mctx, (void *)*str, sizeof(ld_string_t),
+ file, line);
+#else
+ isc_mem_put((*str)->mctx, (void *)(*str)->data,
+ (*str)->allocated * sizeof(char));
+ isc_mem_putanddetach(&(*str)->mctx, (void *)*str, sizeof(ld_string_t));
+#endif
+
+ *str = NULL;
+}
+
+/*
+ * Return length of a string.
+ */
+size_t
+str_len(const ld_string_t *str)
+{
+ return str_len_internal(str);
+}
+
+/*
+ * Retrun a const char * type.
+ */
+const char *
+str_buf(const ld_string_t *src)
+{
+ REQUIRE(src != NULL && src->data != NULL);
+
+ return src->data;
+}
+
+/*
+ * Copy string from src to dest.
+ */
+isc_result_t
+str_copy(ld_string_t *dest, const ld_string_t *src)
+{
+ isc_result_t result;
+
+ REQUIRE(dest != NULL);
+ REQUIRE(src != NULL);
+ IGNORE_R(src->data == NULL);
+
+ CHECK(str_alloc(dest, str_len_internal(src) * sizeof(char)));
+ strncpy(dest->data, src->data, dest->allocated);
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ return result;
+}
+
+/*
+ * Make a new string and copy src to it.
+ */
+isc_result_t
+str_clone(ld_string_t **dest, const ld_string_t *src _STR_MEM_FLARG)
+{
+ isc_result_t result;
+
+ REQUIRE(src != NULL);
+ REQUIRE(dest != NULL && *dest == NULL);
+
+ CHECK(str__new(src->mctx, dest _STR_MEM_FLARG_PASS));
+ CHECK(str_copy(*dest, src));
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ return result;
+}
+
+/*
+ * Initialize string from char *.
+ */
+isc_result_t
+str_init_char(ld_string_t *dest, const char *src)
+{
+ isc_result_t result;
+
+ REQUIRE(dest != NULL);
+ IGNORE_R(src == NULL);
+
+ CHECK(str_alloc(dest, strlen(src) * sizeof(char)));
+ strncpy(dest->data, src, dest->allocated);
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ return result;
+}
+
+/*
+ * Concatenate char *src to string dest.
+ */
+isc_result_t
+str_cat_char(ld_string_t *dest, const char *src)
+{
+ isc_result_t result;
+ char *from;
+ size_t dest_size;
+ size_t src_size;
+
+ REQUIRE(dest != NULL);
+ IGNORE_R(src == NULL);
+
+ dest_size = str_len_internal(dest);
+ src_size = strlen(src);
+
+ CHECK(str_alloc(dest, (dest_size + src_size) * sizeof(char)));
+ from = dest->data + dest_size;
+ strncpy(from, src, src_size + 1);
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ return result;
+}
+
+/*
+ * Concatenate string src to string dest.
+ */
+isc_result_t
+str_cat(ld_string_t *dest, const ld_string_t *src)
+{
+ REQUIRE(dest != NULL);
+ IGNORE_R(src == NULL);
+ IGNORE_R(src->data == NULL);
+
+ return str_cat_char(dest, src->data);
+}
diff --git a/str.h b/str.h
new file mode 100644
index 0000000..e3ff17a
--- /dev/null
+++ b/str.h
@@ -0,0 +1,56 @@
+/* Authors: Martin Nagy <mnagy@redhat.com>
+ *
+ * Copyright (C) 2008 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LD_STR_H_
+#define _LD_STR_H_
+
+#include <isc/mem.h>
+
+#if ISC_MEM_TRACKLINES
+#define _STR_MEM_FILELINE , __FILE__, __LINE__
+#define _STR_MEM_FLARG , const char *file, int line
+#define _STR_MEM_FLARG_PASS , file, line
+#else
+#define _STR_MEM_FILELINE
+#define _STR_MEM_FLAG
+#define _STR_MEM_FLARG_PASS
+#endif
+
+typedef struct ld_string ld_string_t;
+
+/*
+ * Public functions.
+ */
+
+#define str_new(m, s) str__new((m), (s) _STR_MEM_FILELINE)
+#define str_destroy(s) str__destroy((s) _STR_MEM_FILELINE)
+
+size_t str_len(const ld_string_t *str);
+const char * str_buf(const ld_string_t *src);
+isc_result_t str_copy(ld_string_t *dest, const ld_string_t *src);
+isc_result_t str_clone(ld_string_t **dest, const ld_string_t *src _STR_MEM_FLARG);
+isc_result_t str_init_char(ld_string_t *dest, const char *src);
+isc_result_t str_cat_char(ld_string_t *dest, const char *src);
+isc_result_t str_cat(ld_string_t *dest, const ld_string_t *src);
+
+/* These are pseudo-private functions and shouldn't be called directly. */
+isc_result_t str__new(isc_mem_t *mctx, ld_string_t **new_str _STR_MEM_FLARG);
+void str__destroy(ld_string_t **str _STR_MEM_FLARG);
+
+#endif /* !_LD_STR_H_ */