1/* src/interfaces/ecpg/pgtypeslib/common.c */
2
3#include "postgres_fe.h"
4
5#include "pgtypeslib_extern.h"
6#include "pgtypes.h"
7
8/* Return value is zero-filled. */
9char *
10pgtypes_alloc(long size)
11{
12 char *new = (char *) calloc(1L, size);
13
14 if (!new)
15 errno = ENOMEM;
16 return new;
17}
18
19char *
20pgtypes_strdup(const char *str)
21{
22 char *new = (char *) strdup(str);
23
24 if (!new)
25 errno = ENOMEM;
26 return new;
27}
28
29int
30pgtypes_fmt_replace(union un_fmt_comb replace_val, int replace_type, char **output, int *pstr_len)
31{
32 /*
33 * general purpose variable, set to 0 in order to fix compiler warning
34 */
35 int i = 0;
36
37 switch (replace_type)
38 {
39 case PGTYPES_TYPE_NOTHING:
40 break;
41 case PGTYPES_TYPE_STRING_CONSTANT:
42 case PGTYPES_TYPE_STRING_MALLOCED:
43 i = strlen(replace_val.str_val);
44 if (i + 1 <= *pstr_len)
45 {
46 /* include trailing terminator in what we copy */
47 memcpy(*output, replace_val.str_val, i + 1);
48 *pstr_len -= i;
49 *output += i;
50 if (replace_type == PGTYPES_TYPE_STRING_MALLOCED)
51 free(replace_val.str_val);
52 return 0;
53 }
54 else
55 return -1;
56 break;
57 case PGTYPES_TYPE_CHAR:
58 if (*pstr_len >= 2)
59 {
60 (*output)[0] = replace_val.char_val;
61 (*output)[1] = '\0';
62 (*pstr_len)--;
63 (*output)++;
64 return 0;
65 }
66 else
67 return -1;
68 break;
69 case PGTYPES_TYPE_DOUBLE_NF:
70 case PGTYPES_TYPE_INT64:
71 case PGTYPES_TYPE_UINT:
72 case PGTYPES_TYPE_UINT_2_LZ:
73 case PGTYPES_TYPE_UINT_2_LS:
74 case PGTYPES_TYPE_UINT_3_LZ:
75 case PGTYPES_TYPE_UINT_4_LZ:
76 {
77 char *t = pgtypes_alloc(PGTYPES_FMT_NUM_MAX_DIGITS);
78
79 if (!t)
80 return ENOMEM;
81 switch (replace_type)
82 {
83 case PGTYPES_TYPE_DOUBLE_NF:
84 i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
85 "%0.0g", replace_val.double_val);
86 break;
87 case PGTYPES_TYPE_INT64:
88 i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
89 INT64_FORMAT, replace_val.int64_val);
90 break;
91 case PGTYPES_TYPE_UINT:
92 i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
93 "%u", replace_val.uint_val);
94 break;
95 case PGTYPES_TYPE_UINT_2_LZ:
96 i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
97 "%02u", replace_val.uint_val);
98 break;
99 case PGTYPES_TYPE_UINT_2_LS:
100 i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
101 "%2u", replace_val.uint_val);
102 break;
103 case PGTYPES_TYPE_UINT_3_LZ:
104 i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
105 "%03u", replace_val.uint_val);
106 break;
107 case PGTYPES_TYPE_UINT_4_LZ:
108 i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
109 "%04u", replace_val.uint_val);
110 break;
111 }
112
113 if (i < 0 || i >= PGTYPES_FMT_NUM_MAX_DIGITS)
114 {
115 free(t);
116 return -1;
117 }
118 i = strlen(t);
119 *pstr_len -= i;
120
121 /*
122 * if *pstr_len == 0, we don't have enough space for the
123 * terminator and the conversion fails
124 */
125 if (*pstr_len <= 0)
126 {
127 free(t);
128 return -1;
129 }
130 strcpy(*output, t);
131 *output += i;
132 free(t);
133 }
134 break;
135 default:
136 break;
137 }
138 return 0;
139}
140
141/* Functions declared in pgtypes.h. */
142
143/* Just frees memory (mostly needed for Windows) */
144void
145PGTYPESchar_free(char *ptr)
146{
147 free(ptr);
148}
149