1 /*
2  * Copyright 2018 Jonathan Dieter <jdieter@gmail.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  1. Redistributions of source code must retain the above copyright notice,
8  *     this list of conditions and the following disclaimer.
9  *
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <stdio.h>
28 #include <assert.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdbool.h>
32 #include <zck.h>
33 
34 #include "zck_private.h"
35 
36 static const char *empty_error = "";
37 
38 zckCtx zck_none = {0};
39 
set_error_wf(zckCtx * zck,int fatal,const char * function,const char * format,...)40 void set_error_wf(zckCtx *zck, int fatal, const char *function,
41                   const char *format, ...) {
42     va_list args;
43     int size = 0;
44     char *old_msg = NULL;
45     int old_size = 0;
46     assert(format != NULL);
47 
48     if(zck == NULL)
49         zck = &zck_none;
50 
51     zck->error_state = 1 + (fatal > 0 ? 1 : 0);
52     va_start(args, format);
53     size = vsnprintf(NULL, 0, format, args);
54     va_end(args);
55     va_start(args, format);
56     zck_log_v(function, ZCK_LOG_ERROR, format, args);
57     va_end(args);
58     if(size < 0)
59         return;
60     if(zck->msg != NULL) {
61         old_size = strlen(zck->msg);
62         old_msg = zck->msg;
63     }
64     if(old_msg)
65         zck->msg = zmalloc(size + old_size + 3);
66     else
67         zck->msg = zmalloc(size + 2);
68     va_start(args, format);
69     vsnprintf(zck->msg, size + 1, format, args);
70     va_end(args);
71     if(old_msg) {
72         snprintf(zck->msg + size, old_size + 3, ": %s", old_msg);
73         free(old_msg);
74     } else {
75         snprintf(zck->msg + size, 2, "\n");
76     }
77 
78 }
79 
zck_is_error(zckCtx * zck)80 int PUBLIC zck_is_error(zckCtx *zck) {
81     if(zck == NULL)
82         zck = &zck_none;
83 
84     return zck->error_state;
85 }
86 
zck_get_error(zckCtx * zck)87 const char PUBLIC *zck_get_error(zckCtx *zck) {
88     if(zck == NULL)
89         zck = &zck_none;
90 
91     if(zck->msg == NULL)
92         return empty_error;
93     return zck->msg;
94 }
95 
zck_clear_error(zckCtx * zck)96 bool PUBLIC zck_clear_error(zckCtx *zck) {
97     if(zck != NULL && zck->error_state > 1)
98         return false;
99 
100     if(zck == NULL)
101         zck = &zck_none;
102 
103     free(zck->msg);
104     zck->msg = NULL;
105     zck->error_state = 0;
106     return true;
107 }
108