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 * 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 * 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 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 145 PGTYPESchar_free(char *ptr) 146 { 147 free(ptr); 148 } 149