1 /* src/interfaces/ecpg/pgtypeslib/common.c */
2 
3 #include "postgres_fe.h"
4 
5 #include "extern.h"
6 #include "pgtypes.h"
7 
8 /* Return value is zero-filled. */
9 char *
pgtypes_alloc(long size)10 pgtypes_alloc(long size)
11 {
12 	char	   *new = (char *) calloc(1L, size);
13 
14 	if (!new)
15 		errno = ENOMEM;
16 	return new;
17 }
18 
19 char *
pgtypes_strdup(const char * str)20 pgtypes_strdup(const char *str)
21 {
22 	char	   *new = (char *) strdup(str);
23 
24 	if (!new)
25 		errno = ENOMEM;
26 	return new;
27 }
28 
29 int
pgtypes_fmt_replace(union un_fmt_comb replace_val,int replace_type,char ** output,int * pstr_len)30 pgtypes_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) */
144 void
PGTYPESchar_free(char * ptr)145 PGTYPESchar_free(char *ptr)
146 {
147 	free(ptr);
148 }
149