formatting.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,989 行 · 第 1/5 页
C
2,989 行
/* * Postfix */ if (ver == DCH_TYPE && *str && (s = suff_search(str, suf, SUFFTYPE_POSTFIX)) != NULL) { suffix |= s->id; if (s->len) str += s->len; } } else if (*str) { /* * Special characters '\' and '"' */ if (*str == '"' && last != '\\') { int x = 0; while (*(++str)) { if (*str == '"' && x != '\\') { str++; break; } else if (*str == '\\' && x != '\\') { x = '\\'; continue; } n->type = NODE_TYPE_CHAR; n->character = *str; n->key = (KeyWord *) NULL; n->suffix = 0; ++n; x = *str; } node_set = 0; suffix = 0; last = 0; } else if (*str && *str == '\\' && last != '\\' && *(str + 1) == '"') { last = *str; str++; } else if (*str) { n->type = NODE_TYPE_CHAR; n->character = *str; n->key = (KeyWord *) NULL; node_set = 1; last = 0; str++; } } /* end */ if (node_set) { if (n->type == NODE_TYPE_ACTION) n->suffix = suffix; ++n; n->suffix = 0; node_set = 0; } } n->type = NODE_TYPE_END; n->suffix = 0; return;}/* ---------- * Call keyword's function for each of (action) node in format-node tree * ---------- */static char *DCH_processor(FormatNode *node, char *inout, int flag, void *data){ FormatNode *n; char *s; /* * Zeroing global flags */ DCH_global_flag = 0; for (n = node, s = inout; n->type != NODE_TYPE_END; n++) { if (flag == FROM_CHAR && *s=='\0') /* * The input string is shorter than format picture, * so it's good time to break this loop... * * Note: this isn't relevant for TO_CHAR mode, beacuse * it use 'inout' allocated by format picture length. */ break; if (n->type == NODE_TYPE_ACTION) { int len; /* * Call node action function */ len = n->key->action(n->key->id, s, n->suffix, flag, n, data); if (len > 0) s += len; else if (len == -1) continue; } else { /* * Remove to output char from input in TO_CHAR */ if (flag == TO_CHAR) *s = n->character; else { /* * Skip blank space in FROM_CHAR's input */ if (isspace((unsigned char) n->character) && IS_FX == 0) { while (*s != '\0' && isspace((unsigned char) *(s + 1))) ++s; } } } ++s; /* ! */ } if (flag == TO_CHAR) *s = '\0'; return inout;}/* ---------- * DEBUG: Dump the FormatNode Tree (debug) * ---------- */#ifdef DEBUG_TO_FROM_CHAR#define DUMP_THth(_suf) (S_TH(_suf) ? "TH" : (S_th(_suf) ? "th" : " "))#define DUMP_FM(_suf) (S_FM(_suf) ? "FM" : " ")static voiddump_node(FormatNode *node, int max){ FormatNode *n; int a; elog(DEBUG_elog_output, "to_from-char(): DUMP FORMAT"); for (a = 0, n = node; a <= max; n++, a++) { if (n->type == NODE_TYPE_ACTION) elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION '%s'\t(%s,%s)", a, n->key->name, DUMP_THth(n->suffix), DUMP_FM(n->suffix)); else if (n->type == NODE_TYPE_CHAR) elog(DEBUG_elog_output, "%d:\t NODE_TYPE_CHAR '%c'", a, n->character); else if (n->type == NODE_TYPE_END) { elog(DEBUG_elog_output, "%d:\t NODE_TYPE_END", a); return; } else elog(DEBUG_elog_output, "%d:\t unknown NODE!", a); }}#endif /* DEBUG *//***************************************************************************** * Private utils *****************************************************************************//* ---------- * Return ST/ND/RD/TH for simple (1..9) numbers * type --> 0 upper, 1 lower * ---------- */static char *get_th(char *num, int type){ int len = strlen(num), last, seclast; last = *(num + (len - 1)); if (!isdigit((unsigned char) last)) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("\"%s\" is not a number", num))); /* * All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get * 'ST/st', 'ND/nd', 'RD/rd', respectively */ if ((len > 1) && ((seclast = num[len - 2]) == '1')) last = 0; switch (last) { case '1': if (type == TH_UPPER) return numTH[0]; return numth[0]; case '2': if (type == TH_UPPER) return numTH[1]; return numth[1]; case '3': if (type == TH_UPPER) return numTH[2]; return numth[2]; default: if (type == TH_UPPER) return numTH[3]; return numth[3]; } return NULL;}/* ---------- * Convert string-number to ordinal string-number * type --> 0 upper, 1 lower * ---------- */static char *str_numth(char *dest, char *num, int type){ sprintf(dest, "%s%s", num, get_th(num, type)); return dest;}/* ---------- * Convert string to upper-string. Input string is modified in place. * ---------- */static char *str_toupper(char *buff){ char *p_buff = buff; if (!buff) return NULL; while (*p_buff) { *p_buff = toupper((unsigned char) *p_buff); ++p_buff; } return buff;}/* ---------- * Convert string to lower-string. Input string is modified in place. * ---------- */static char *str_tolower(char *buff){ char *p_buff = buff; if (!buff) return NULL; while (*p_buff) { *p_buff = tolower((unsigned char) *p_buff); ++p_buff; } return buff;}/* ---------- * Sequential search with to upper/lower conversion * ---------- */static intseq_search(char *name, char **array, int type, int max, int *len){ char *p, *n, **a; int last, i; *len = 0; if (!*name) return -1; /* set first char */ if (type == ONE_UPPER || type == ALL_UPPER) *name = toupper((unsigned char) *name); else if (type == ALL_LOWER) *name = tolower((unsigned char) *name); for (last = 0, a = array; *a != NULL; a++) { /* comperate first chars */ if (*name != **a) continue; for (i = 1, p = *a + 1, n = name + 1;; n++, p++, i++) { /* search fragment (max) only */ if (max && i == max) { *len = i; return a - array; } /* full size */ if (*p == '\0') { *len = i; return a - array; } /* Not found in array 'a' */ if (*n == '\0') break; /* * Convert (but convert new chars only) */ if (i > last) { if (type == ONE_UPPER || type == ALL_LOWER) *n = tolower((unsigned char) *n); else if (type == ALL_UPPER) *n = toupper((unsigned char) *n); last = i; }#ifdef DEBUG_TO_FROM_CHAR /* * elog(DEBUG_elog_output, "N: %c, P: %c, A: %s (%s)", *n, *p, * *a, name); */#endif if (*n != *p) break; } } return -1;}#ifdef DEBUG_TO_FROM_CHAR/* ----------- * DEBUG: Call for debug and for index checking; (Show ASCII char * and defined keyword for each used position * ---------- */static voiddump_index(KeyWord *k, int *index){ int i, count = 0, free_i = 0; elog(DEBUG_elog_output, "TO-FROM_CHAR: Dump KeyWord Index:"); for (i = 0; i < KeyWord_INDEX_SIZE; i++) { if (index[i] != -1) { elog(DEBUG_elog_output, "\t%c: %s, ", i + 32, k[index[i]].name); count++; } else { free_i++; elog(DEBUG_elog_output, "\t(%d) %c %d", i, i + 32, index[i]); } } elog(DEBUG_elog_output, "\n\t\tUsed positions: %d,\n\t\tFree positions: %d", count, free_i);}#endif /* DEBUG *//* ---------- * Skip TM / th in FROM_CHAR * ---------- */#define SKIP_THth(_suf) (S_THth(_suf) ? 2 : 0)/* ---------- * Global format option for DCH version * ---------- */static intdch_global(int arg, char *inout, int suf, int flag, FormatNode *node, void *data){ if (arg == DCH_FX) DCH_global_flag |= DCH_F_FX; return -1;}/* ---------- * Return TRUE if next format picture is not digit value * ---------- */static boolis_next_separator(FormatNode *n){ if (n->type == NODE_TYPE_END) return FALSE; if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix)) return TRUE; /* * Next node */ n++; if (n->type == NODE_TYPE_END) return FALSE; if (n->type == NODE_TYPE_ACTION) { if (n->key->isitdigit) return FALSE; return TRUE; } else if (isdigit((unsigned char) n->character)) return FALSE; return TRUE; /* some non-digit input (separator) */}static intstrdigits_len(char *str){ char *p = str; int len = 0; while (*p && isdigit((unsigned char) *p) && len <= DCH_MAX_ITEM_SIZ) { len++; p++; } return len;}#define AMPM_ERROR ereport(ERROR, \ (errcode(ERRCODE_INVALID_DATETIME_FORMAT), \ errmsg("invalid AM/PM string")));/* ---------- * Master function of TIME for: * TO_CHAR - write (inout) formated string * FROM_CHAR - scan (inout) string by course of FormatNode * ---------- */static intdch_time(int arg, char *inout, int suf, int flag, FormatNode *node, void *data){ char *p_inout = inout; struct tm *tm = NULL; TmFromChar *tmfc = NULL; TmToChar *tmtc = NULL; if (flag == TO_CHAR) { tmtc = (TmToChar *) data; tm = tmtcTm(tmtc); } else tmfc = (TmFromChar *) data; switch (arg) { case DCH_A_M: case DCH_P_M: if (flag == TO_CHAR) { strcpy(inout, ((tm->tm_hour > 11 && tm->tm_hour < 24) ? P_M_STR : A_M_STR)); return 3; } else if (flag == FROM_CHAR) { if (strncmp(inout, P_M_STR, 4) == 0) tmfc->pm = TRUE; else if (strncmp(inout, A_M_STR, 4) == 0) tmfc->am = TRUE; else AMPM_ERROR; return 3; } break; case DCH_AM: case DCH_PM: if (flag == TO_CHAR) { strcpy(inout, ((tm->tm_hour > 11 && tm->tm_hour < 24) ? PM_STR : AM_STR)); return 1; } else if (flag == FROM_CHAR) { if (strncmp(inout, PM_STR, 2) == 0) tmfc->pm = TRUE; else if (strncmp(inout, AM_STR, 2) == 0) tmfc->am = TRUE; else AMPM_ERROR; return 1; } break; case DCH_a_m: case DCH_p_m: if (flag == TO_CHAR) { strcpy(inout, ((tm->tm_hour > 11 && tm->tm_hour < 24) ? p_m_STR : a_m_STR)); return 3; } else if (flag == FROM_CHAR) { if (strncmp(inout, p_m_STR, 4) == 0) tmfc->pm = TRUE; else if (strncmp(inout, a_m_STR, 4) == 0) tmfc->am = TRUE; else AMPM_ERROR; return 3; } break; case DCH_am: case DCH_pm: if (flag == TO_CHAR) { strcpy(inout, ((tm->tm_hour > 11 && tm->tm_hour < 24) ? pm_STR : am_STR)); return 1; } else if (flag == FROM_CHAR) { if (strncmp(inout, pm_STR, 2) == 0) tmfc->pm = TRUE; else if (strncmp(inout, am_STR, 2) == 0) tmfc->am = TRUE; else AMPM_ERROR; return 1; } break; case DCH_HH: case DCH_HH12: if (flag == TO_CHAR) { sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_hour == 0 ? 12 : tm->tm_hour < 13 ? tm->tm_hour : tm->tm_hour - 12); if (S_THth(suf)) str_numth(p_inout, inout, 0); if (S_FM(suf) || S_THth(suf)) return strlen(p_inout) - 1; else return 1; } else if (flag == FROM_CHAR) { if (S_FM(suf) || is_next_separator(node)) { sscanf(inout, "%d", &tmfc->hh); return strdigits_len(inout) - 1 + SKIP_THth(suf); } else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?