From c94f299fc8e602912a7d68c57404a96b98da4037 Mon Sep 17 00:00:00 2001 From: Love Hornquist Astrand Date: Sun, 25 Sep 2011 19:03:23 +0200 Subject: [PATCH] add heim_error_t --- base/Makefile.am | 1 + base/NTMakefile | 1 + base/error.c | 132 ++++++++++++++++++++++++++++++++++++++++++++ base/heimbase.h | 18 ++++++ base/heimbasepriv.h | 1 + base/test_base.c | 22 +++++++- 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 base/error.c diff --git a/base/Makefile.am b/base/Makefile.am index 639136f79..a7e10c8ef 100644 --- a/base/Makefile.am +++ b/base/Makefile.am @@ -17,6 +17,7 @@ dist_libheimbase_la_SOURCES = \ baselocl.h \ bool.c \ dict.c \ + error.c \ heimbase.c \ heimbasepriv.h \ heimqueue.h \ diff --git a/base/NTMakefile b/base/NTMakefile index 0668cd699..c95dff8d9 100644 --- a/base/NTMakefile +++ b/base/NTMakefile @@ -39,6 +39,7 @@ libheimbase_OBJS = \ $(OBJ)\array.obj \ $(OBJ)\bool.obj \ $(OBJ)\dict.obj \ + $(OBJ)\error.obj \ $(OBJ)\heimbase.obj \ $(OBJ)\null.obj \ $(OBJ)\number.obj \ diff --git a/base/error.c b/base/error.c new file mode 100644 index 000000000..4a9871919 --- /dev/null +++ b/base/error.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 THE INSTITUTE OR CONTRIBUTORS 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. + */ + +#include "baselocl.h" + +struct heim_error { + int error_code; + heim_string_t msg; + struct heim_error *next; +}; + +static void +error_dealloc(void *ptr) +{ + struct heim_error *p = ptr; + heim_release(p->msg); + heim_release(p->next); +} + +static int +error_cmp(void *a, void *b) +{ + struct heim_error *ap = a, *bp = b; + if (ap->error_code == ap->error_code) + return ap->error_code - ap->error_code; + return heim_cmp(ap->msg, bp->msg); +} + +static unsigned long +error_hash(void *ptr) +{ + struct heim_error *p = ptr; + return p->error_code; +} + +struct heim_type_data _heim_error_object = { + HEIM_TID_ERROR, + "error-object", + NULL, + error_dealloc, + NULL, + error_cmp, + error_hash +}; + +heim_error_t +heim_error_create(int error_code, const char *fmt, ...) +{ + heim_error_t e; + va_list ap; + + va_start(ap, fmt); + e = heim_error_createv(error_code, fmt, ap); + va_end(ap); + + return e; +} + +heim_error_t +heim_error_createv(int error_code, const char *fmt, va_list ap) +{ + heim_error_t e; + char *str = NULL; + int len; + + len = vasprintf(&str, fmt, ap); + if (len < 0 || str == NULL) + return NULL; + + e = _heim_alloc_object(&_heim_error_object, sizeof(struct heim_error)); + if (e) { + e->msg = heim_string_create(str); + e->error_code = error_code; + } + free(str); + + return e; +} + +heim_string_t +heim_error_copy_string(heim_error_t error) +{ + /* XXX concat all strings */ + return heim_retain(error->msg); +} + +int +heim_error_get_code(heim_error_t error) +{ + return error->error_code; +} + +heim_error_t +heim_error_append(heim_error_t top, heim_error_t append) +{ + if (top->next) + heim_release(top->next); + top->next = heim_retain(append); + return top; +} diff --git a/base/heimbase.h b/base/heimbase.h index ad1b3f0c4..4dfeb2fac 100644 --- a/base/heimbase.h +++ b/base/heimbase.h @@ -185,4 +185,22 @@ heim_auto_release_t heim_auto_release_create(void); void heim_auto_release_drain(heim_auto_release_t); void heim_auto_release(heim_object_t); + +/* + * + */ + +typedef struct heim_error * heim_error_t; + +heim_error_t heim_error_create(int, const char *, ...) + HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 3)); + +heim_error_t heim_error_createv(int, const char *, va_list) + HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 0)); + +heim_string_t heim_error_copy_string(heim_error_t); +int heim_error_get_code(heim_error_t); + +heim_error_t heim_error_append(heim_error_t, heim_error_t); + #endif /* HEIM_BASE_H */ diff --git a/base/heimbasepriv.h b/base/heimbasepriv.h index 772962548..a3bb19853 100644 --- a/base/heimbasepriv.h +++ b/base/heimbasepriv.h @@ -54,6 +54,7 @@ enum { HEIM_TID_DICT = 130, HEIM_TID_STRING = 131, HEIM_TID_AUTORELEASE = 132, + HEIM_TID_ERROR = 133, HEIM_TID_USER = 255 }; diff --git a/base/test_base.c b/base/test_base.c index 80ab967d4..4772d21e2 100644 --- a/base/test_base.c +++ b/base/test_base.c @@ -35,6 +35,7 @@ #include #include +#include #include "heimbase.h" #include "heimbasepriv.h" @@ -138,6 +139,24 @@ test_string(void) return 0; } +static int +test_error(void) +{ + heim_error_t e; + heim_string_t s; + + e = heim_error_create(10, "foo: %s", "bar"); + heim_assert(heim_error_get_code(e) == 10, "error_code != 10"); + + s = heim_error_copy_string(e); + heim_assert(strcmp(heim_string_get_utf8(s), "foo: bar") == 0, "msg wrong"); + + heim_release(s); + heim_release(e); + + return 0; +} + int main(int argc, char **argv) { @@ -147,6 +166,7 @@ main(int argc, char **argv) res |= test_dict(); res |= test_auto_release(); res |= test_string(); + res |= test_error(); - return res; + return res ? 1 : 0; }