📄 formatting.c
字号:
DCH_hh24, DCH_hh12, DCH_hh, DCH_iw, DCH_iyyy, DCH_iyy, DCH_iy, DCH_i, DCH_j, DCH_mi, DCH_mm, DCH_month, DCH_mon, DCH_ms, DCH_p_m, DCH_pm, DCH_q, DCH_rm, DCH_ssss, DCH_ss, DCH_tz, DCH_us, DCH_ww, DCH_w, DCH_y_yyy, DCH_yyyy, DCH_yyy, DCH_yy, DCH_y, /* last */ _DCH_last_} DCH_poz;typedef enum{ NUM_COMMA, NUM_DEC, NUM_0, NUM_9, NUM_B, NUM_C, NUM_D, NUM_E, NUM_FM, NUM_G, NUM_L, NUM_MI, NUM_PL, NUM_PR, NUM_RN, NUM_SG, NUM_SP, NUM_S, NUM_TH, NUM_V, NUM_b, NUM_c, NUM_d, NUM_e, NUM_fm, NUM_g, NUM_l, NUM_mi, NUM_pl, NUM_pr, NUM_rn, NUM_sg, NUM_sp, NUM_s, NUM_th, NUM_v, /* last */ _NUM_last_} NUM_poz;/* ---------- * KeyWords for DATE-TIME version * ---------- */static const KeyWord DCH_keywords[] = {/* keyword, len, func, type, isitdigit is in Index */ {"A.D.", 4, dch_date, DCH_A_D, FALSE}, /* A */ {"A.M.", 4, dch_time, DCH_A_M, FALSE}, {"AD", 2, dch_date, DCH_AD, FALSE}, {"AM", 2, dch_time, DCH_AM, FALSE}, {"B.C.", 4, dch_date, DCH_B_C, FALSE}, /* B */ {"BC", 2, dch_date, DCH_BC, FALSE}, {"CC", 2, dch_date, DCH_CC, TRUE}, /* C */ {"DAY", 3, dch_date, DCH_DAY, FALSE}, /* D */ {"DDD", 3, dch_date, DCH_DDD, TRUE}, {"DD", 2, dch_date, DCH_DD, TRUE}, {"DY", 2, dch_date, DCH_DY, FALSE}, {"Day", 3, dch_date, DCH_Day, FALSE}, {"Dy", 2, dch_date, DCH_Dy, FALSE}, {"D", 1, dch_date, DCH_D, TRUE}, {"FX", 2, dch_global, DCH_FX, FALSE}, /* F */ {"HH24", 4, dch_time, DCH_HH24, TRUE}, /* H */ {"HH12", 4, dch_time, DCH_HH12, TRUE}, {"HH", 2, dch_time, DCH_HH, TRUE}, {"IW", 2, dch_date, DCH_IW, TRUE}, /* I */ {"IYYY", 4, dch_date, DCH_IYYY, TRUE}, {"IYY", 3, dch_date, DCH_IYY, TRUE}, {"IY", 2, dch_date, DCH_IY, TRUE}, {"I", 1, dch_date, DCH_I, TRUE}, {"J", 1, dch_date, DCH_J, TRUE}, /* J */ {"MI", 2, dch_time, DCH_MI, TRUE}, {"MM", 2, dch_date, DCH_MM, TRUE}, {"MONTH", 5, dch_date, DCH_MONTH, FALSE}, {"MON", 3, dch_date, DCH_MON, FALSE}, {"MS", 2, dch_time, DCH_MS, TRUE}, {"Month", 5, dch_date, DCH_Month, FALSE}, {"Mon", 3, dch_date, DCH_Mon, FALSE}, {"P.M.", 4, dch_time, DCH_P_M, FALSE}, /* P */ {"PM", 2, dch_time, DCH_PM, FALSE}, {"Q", 1, dch_date, DCH_Q, TRUE}, /* Q */ {"RM", 2, dch_date, DCH_RM, FALSE}, /* R */ {"SSSS", 4, dch_time, DCH_SSSS, TRUE}, /* S */ {"SS", 2, dch_time, DCH_SS, TRUE}, {"TZ", 2, dch_time, DCH_TZ, FALSE}, /* T */ {"US", 2, dch_time, DCH_US, TRUE}, /* U */ {"WW", 2, dch_date, DCH_WW, TRUE}, /* W */ {"W", 1, dch_date, DCH_W, TRUE}, {"Y,YYY", 5, dch_date, DCH_Y_YYY, TRUE}, /* Y */ {"YYYY", 4, dch_date, DCH_YYYY, TRUE}, {"YYY", 3, dch_date, DCH_YYY, TRUE}, {"YY", 2, dch_date, DCH_YY, TRUE}, {"Y", 1, dch_date, DCH_Y, TRUE}, {"a.d.", 4, dch_date, DCH_a_d, FALSE}, /* a */ {"a.m.", 4, dch_time, DCH_a_m, FALSE}, {"ad", 2, dch_date, DCH_ad, FALSE}, {"am", 2, dch_time, DCH_am, FALSE}, {"b.c.", 4, dch_date, DCH_b_c, FALSE}, /* b */ {"bc", 2, dch_date, DCH_bc, FALSE}, {"cc", 2, dch_date, DCH_CC, TRUE}, /* c */ {"day", 3, dch_date, DCH_day, FALSE}, /* d */ {"ddd", 3, dch_date, DCH_DDD, TRUE}, {"dd", 2, dch_date, DCH_DD, TRUE}, {"dy", 2, dch_date, DCH_dy, FALSE}, {"d", 1, dch_date, DCH_D, TRUE}, {"fx", 2, dch_global, DCH_FX, FALSE}, /* f */ {"hh24", 4, dch_time, DCH_HH24, TRUE}, /* h */ {"hh12", 4, dch_time, DCH_HH12, TRUE}, {"hh", 2, dch_time, DCH_HH, TRUE}, {"iw", 2, dch_date, DCH_IW, TRUE}, /* i */ {"iyyy", 4, dch_date, DCH_IYYY, TRUE}, {"iyy", 3, dch_date, DCH_IYY, TRUE}, {"iy", 2, dch_date, DCH_IY, TRUE}, {"i", 1, dch_date, DCH_I, TRUE}, {"j", 1, dch_time, DCH_J, TRUE}, /* j */ {"mi", 2, dch_time, DCH_MI, TRUE}, /* m */ {"mm", 2, dch_date, DCH_MM, TRUE}, {"month", 5, dch_date, DCH_month, FALSE}, {"mon", 3, dch_date, DCH_mon, FALSE}, {"ms", 2, dch_time, DCH_MS, TRUE}, {"p.m.", 4, dch_time, DCH_p_m, FALSE}, /* p */ {"pm", 2, dch_time, DCH_pm, FALSE}, {"q", 1, dch_date, DCH_Q, TRUE}, /* q */ {"rm", 2, dch_date, DCH_rm, FALSE}, /* r */ {"ssss", 4, dch_time, DCH_SSSS, TRUE}, /* s */ {"ss", 2, dch_time, DCH_SS, TRUE}, {"tz", 2, dch_time, DCH_tz, FALSE}, /* t */ {"us", 2, dch_time, DCH_US, TRUE}, /* u */ {"ww", 2, dch_date, DCH_WW, TRUE}, /* w */ {"w", 1, dch_date, DCH_W, TRUE}, {"y,yyy", 5, dch_date, DCH_Y_YYY, TRUE}, /* y */ {"yyyy", 4, dch_date, DCH_YYYY, TRUE}, {"yyy", 3, dch_date, DCH_YYY, TRUE}, {"yy", 2, dch_date, DCH_YY, TRUE}, {"y", 1, dch_date, DCH_Y, TRUE},/* last */{NULL, 0, NULL, 0}};/* ---------- * KeyWords for NUMBER version (now, isitdigit info is not needful here..) * ---------- */static const KeyWord NUM_keywords[] = {/* keyword, len, func. type is in Index */ {",", 1, NULL, NUM_COMMA}, /* , */ {".", 1, NULL, NUM_DEC}, /* . */ {"0", 1, NULL, NUM_0}, /* 0 */ {"9", 1, NULL, NUM_9}, /* 9 */ {"B", 1, NULL, NUM_B}, /* B */ {"C", 1, NULL, NUM_C}, /* C */ {"D", 1, NULL, NUM_D}, /* D */ {"E", 1, NULL, NUM_E}, /* E */ {"FM", 2, NULL, NUM_FM}, /* F */ {"G", 1, NULL, NUM_G}, /* G */ {"L", 1, NULL, NUM_L}, /* L */ {"MI", 2, NULL, NUM_MI}, /* M */ {"PL", 2, NULL, NUM_PL}, /* P */ {"PR", 2, NULL, NUM_PR}, {"RN", 2, NULL, NUM_RN}, /* R */ {"SG", 2, NULL, NUM_SG}, /* S */ {"SP", 2, NULL, NUM_SP}, {"S", 1, NULL, NUM_S}, {"TH", 2, NULL, NUM_TH}, /* T */ {"V", 1, NULL, NUM_V}, /* V */ {"b", 1, NULL, NUM_B}, /* b */ {"c", 1, NULL, NUM_C}, /* c */ {"d", 1, NULL, NUM_D}, /* d */ {"e", 1, NULL, NUM_E}, /* e */ {"fm", 2, NULL, NUM_FM}, /* f */ {"g", 1, NULL, NUM_G}, /* g */ {"l", 1, NULL, NUM_L}, /* l */ {"mi", 2, NULL, NUM_MI}, /* m */ {"pl", 2, NULL, NUM_PL}, /* p */ {"pr", 2, NULL, NUM_PR}, {"rn", 2, NULL, NUM_rn}, /* r */ {"sg", 2, NULL, NUM_SG}, /* s */ {"sp", 2, NULL, NUM_SP}, {"s", 1, NULL, NUM_S}, {"th", 2, NULL, NUM_th}, /* t */ {"v", 1, NULL, NUM_V}, /* v *//* last */{NULL, 0, NULL, 0}};/* ---------- * KeyWords index for DATE-TIME version * ---------- */static const int DCH_index[KeyWord_INDEX_SIZE] = {/*0 1 2 3 4 5 6 7 8 9*/ /*---- first 0..31 chars are skipped ----*/ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1, DCH_FX, -1, DCH_HH24, DCH_IW, DCH_J, -1, -1, DCH_MI, -1, -1, DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZ, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY, -1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc, DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iw, DCH_j, -1, -1, DCH_mi, -1, -1, DCH_p_m, DCH_q, DCH_rm, DCH_ssss, DCH_tz, DCH_us, -1, DCH_ww, -1, DCH_y_yyy, -1, -1, -1, -1 /*---- chars over 126 are skiped ----*/};/* ---------- * KeyWords index for NUMBER version * ---------- */static const int NUM_index[KeyWord_INDEX_SIZE] = {/*0 1 2 3 4 5 6 7 8 9*/ /*---- first 0..31 chars are skiped ----*/ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, NUM_COMMA, -1, NUM_DEC, -1, NUM_0, -1, -1, -1, -1, -1, -1, -1, -1, NUM_9, -1, -1, -1, -1, -1, -1, -1, -1, NUM_B, NUM_C, NUM_D, NUM_E, NUM_FM, NUM_G, -1, -1, -1, -1, NUM_L, NUM_MI, -1, -1, NUM_PL, -1, NUM_RN, NUM_SG, NUM_TH, -1, NUM_V, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, NUM_b, NUM_c, NUM_d, NUM_e, NUM_fm, NUM_g, -1, -1, -1, -1, NUM_l, NUM_mi, -1, -1, NUM_pl, -1, NUM_rn, NUM_sg, NUM_th, -1, NUM_v, -1, -1, -1, -1, -1, -1, -1 /*---- chars over 126 are skiped ----*/};/* ---------- * Number processor struct * ---------- */typedef struct NUMProc{ bool is_to_char; NUMDesc *Num; /* number description */ int sign, /* '-' or '+' */ sign_wrote, /* was sign write */ num_count, /* number of write digits */ num_in, /* is inside number */ num_curr, /* current position in number */ num_pre, /* space before first number */ read_dec, /* to_number - was read dec. point */ read_post, /* to_number - number of dec. digit */ read_pre; /* to_number - number non-dec. digit */ char *number, /* string with number */ *number_p, /* pointer to current number position */ *inout, /* in / out buffer */ *inout_p, /* pointer to current inout position */ *last_relevant, /* last relevant number after decimal point */ *L_negative_sign, /* Locale */ *L_positive_sign, *decimal, *L_thousands_sep, *L_currency_symbol;} NUMProc;/* ---------- * Functions * ---------- */static const KeyWord *index_seq_search(char *str, const KeyWord *kw, const int *index);static KeySuffix *suff_search(char *str, KeySuffix *suf, int type);static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);static void parse_format(FormatNode *node, char *str, const KeyWord *kw, KeySuffix *suf, const int *index, int ver, NUMDesc *Num);static char *DCH_processor(FormatNode *node, char *inout, bool is_to_char, bool is_interval, void *data);#ifdef DEBUG_TO_FROM_CHARstatic void dump_index(const KeyWord *k, const int *index);static void dump_node(FormatNode *node, int max);#endifstatic char *get_th(char *num, int type);static char *str_numth(char *dest, char *num, int type);static int strdigits_len(char *str);static char *str_toupper(char *buff);static char *str_tolower(char *buff);/* static int is_acdc(char *str, int *len); */static int seq_search(char *name, char **array, int type, int max, int *len);static void do_to_timestamp(text *date_txt, text *fmt, struct pg_tm * tm, fsec_t *fsec);static char *fill_str(char *str, int c, int max);static FormatNode *NUM_cache(int len, NUMDesc *Num, char *pars_str, bool *shouldFree);static char *int_to_roman(int number);static void NUM_prepare_locale(NUMProc *Np);static char *get_last_relevant_decnum(char *num);static void NUM_numpart_from_char(NUMProc *Np, int id, int plen);static void NUM_numpart_to_char(NUMProc *Np, int id);static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, int plen, int sign, bool is_to_char);static DCHCacheEntry *DCH_cache_search(char *str);static DCHCacheEntry *DCH_cache_getnew(char *str);static NUMCacheEntry *NUM_cache_search(char *str);static NUMCacheEntry *NUM_cache_getnew(char *str);static void NUM_cache_remove(NUMCacheEntry *ent);/* ---------- * Fast sequential search, use index for data selection which * go to seq. cycle (it is very fast for unwanted strings) * (can't be used binary search in format parsing) * ---------- */static const KeyWord *index_seq_search(char *str, const KeyWord *kw, const int *index){ int poz; if (!KeyWord_INDEX_FILTER(*str)) return NULL; if ((poz = *(index + (*str - ' '))) > -1) { const KeyWord *k = kw + poz; do { if (!strncmp(str, k->name, k->len)) return k; k++; if (!k->name) return NULL; } while (*str == *k->name); } return NULL;}static KeySuffix *suff_search(char *str, KeySuffix *suf, int type){ KeySuffix *s; for (s = suf; s->name != NULL; s++) { if (s->type != type) continue; if (!strncmp(str, s->name, s->len)) return s; } return NULL;}/* ---------- * Prepare NUMDesc (number description struct) via FormatNode struct * ---------- */static voidNUMDesc_prepare(NUMDesc *num, FormatNode *n){ if (n->type != NODE_TYPE_ACTION) return; switch (n->key->id) { case NUM_9: if (IS_BRACKET(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("\"9\" must be ahead of \"PR\""))); } if (IS_MULTI(num)) { ++num->multi; break; } if (IS_DECIMAL(num)) ++num->post; else ++num->pre; break; case NUM_0: if (IS_BRACKET(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("\"0\" must be ahead of \"PR\""))); } if (!IS_ZERO(num) && !IS_DECIMAL(num)) { num->flag |= NUM_F_ZERO; num->zero_start = num->pre + 1; } if (!IS_DECIMAL(num)) ++num->pre; else ++num->post; num->zero_end = num->pre + num->post; break; case NUM_B: if (num->pre == 0 && num->post == 0 && (!IS_ZERO(num))) num->flag |= NUM_F_BLANK; break; case NUM_D: num->flag |= NUM_F_LDECIMAL; num->need_locale = TRUE; case NUM_DEC: if (IS_DECIMAL(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple decimal points"))); } if (IS_MULTI(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot use \"V\" and decimal point together"))); } num->flag |= NUM_F_DECIMAL; break; case NUM_FM: num->flag |= NUM_F_FILLMODE; break; case NUM_S: if (IS_LSIGN(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("not unique \"S\""))); } if (IS_PLUS(num) || IS_MINUS(num) || IS_BRACKET(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together"))); } if (!IS_DECIMAL(num)) { num->lsign = NUM_LSIGN_PRE; num->pre_lsign_num = num->pre; num->need_locale = TRUE; num->flag |= NUM_F_LSIGN; } else if (num->lsign == NUM_LSIGN_NONE) { num->lsign = NUM_LSIGN_POST; num->need_locale = TRUE; num->flag |= NUM_F_LSIGN; } break; case NUM_MI: if (IS_LSIGN(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot use \"S\" and \"MI\" together"))); } num->flag |= NUM_F_MINUS; if (IS_DECIMAL(num)) num->flag |= NUM_F_MINUS_POST; break; case NUM_PL: if (IS_LSIGN(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot use \"S\" and \"PL\" together"))); } num->flag |= NUM_F_PLUS; if (IS_DECIMAL(num)) num->flag |= NUM_F_PLUS_POST; break; case NUM_SG: if (IS_LSIGN(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot use \"S\" and \"SG\" together"))); } num->flag |= NUM_F_MINUS; num->flag |= NUM_F_PLUS; break; case NUM_PR: if (IS_LSIGN(num) || IS_PLUS(num) || IS_MINUS(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together"))); } num->flag |= NUM_F_BRACKET; break; case NUM_rn: case NUM_RN: num->flag |= NUM_F_ROMAN; break; case NUM_L: case NUM_G: num->need_locale = TRUE; break; case NUM_V: if (IS_DECIMAL(num)) { NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot use \"V\" and decimal point together"))); } num->flag |= NUM_F_MULTI; break; case NUM_E: NUM_cache_remove(last_NUMCacheEntry); ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("\"E\" is not supported"))); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -