"Fossies" - the Fresh Open Source Software Archive

Member "dateutils-0.4.6/lib/dt-core-strpf.c" (19 Mar 2019, 11060 Bytes) of package /linux/privat/dateutils-0.4.6.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dt-core-strpf.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.4.5_vs_0.4.6.

    1 /*** dt-core-strpf.c -- parser and formatter funs for dt-core
    2  *
    3  * Copyright (C) 2011-2019 Sebastian Freundt
    4  *
    5  * Author:  Sebastian Freundt <freundt@ga-group.nl>
    6  *
    7  * This file is part of dateutils.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  *
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  *
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * 3. Neither the name of the author nor the names of any contributors
   21  *    may be used to endorse or promote products derived from this
   22  *    software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   27  * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   31  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
   33  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
   34  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  *
   36  **/
   37 /* implementation part of date-core-strpf.h */
   38 #if !defined INCLUDED_dt_core_strpf_c_
   39 #define INCLUDED_dt_core_strpf_c_
   40 
   41 #if defined HAVE_CONFIG_H
   42 # include "config.h"
   43 #endif  /* HAVE_CONFIG_H */
   44 #include "strops.h"
   45 #include "token.h"
   46 #include "dt-core.h"
   47 #include "dt-core-strpf.h"
   48 
   49 #if defined __INTEL_COMPILER
   50 /* we MUST return a char* */
   51 # pragma warning (disable:2203)
   52 #elif defined __GNUC__
   53 # pragma GCC diagnostic ignored "-Wcast-qual"
   54 #endif  /* __INTEL_COMPILER */
   55 
   56 #if !defined DEFUN
   57 # define DEFUN
   58 #endif  /* !DEFUN */
   59 
   60 #if defined SKIP_LEAP_ARITH
   61 # undef WITH_LEAP_SECONDS
   62 #endif  /* SKIP_LEAP_ARITH */
   63 
   64 static int32_t
   65 try_zone(const char *str, const char **ep)
   66 {
   67     int minusp = 0;
   68     const char *sp = str;
   69     int32_t res = 0;
   70 
   71     switch (*sp) {
   72         int32_t tmp;
   73         const char *tp;
   74         const char *up;
   75     case '-':
   76         minusp = 1;
   77     case '+':
   78         /* read hour part */
   79         if ((tmp = strtoi_lim(sp + 1U, &tp, 0, 14)) < 0) {
   80             break;
   81         } else if (tp - sp < 3U) {
   82             /* only accept fully zero-padded hours */
   83             break;
   84         }
   85         res += 3600 * tmp;
   86         /* colon separator is optional */
   87         if (*tp == ':') {
   88             tp++;
   89         }
   90 
   91         /* read minute part */
   92         if ((tmp = strtoi_lim(tp, &up, 0, 59)) < 0) {
   93             break;
   94         } else if (up - tp < 2U) {
   95             /* only accept zero-padded minutes */
   96             break;
   97         } else {
   98             tp = up;
   99         }
  100         res += 60 * tmp;
  101         /* at least we've got hours and minutes */
  102         sp = tp;
  103         /* again colon separator is optional */
  104         if (*tp == ':') {
  105             tp++;
  106         }
  107 
  108         /* read second part */
  109         if ((tmp = strtoi_lim(tp, &tp, 0, 59)) < 0) {
  110             break;
  111         }
  112         res += tmp;
  113         /* fully determined */
  114         sp = tp;
  115         break;
  116     case 'Z':
  117         /* accept Zulu specifier */
  118         sp++;
  119         break;
  120     default:
  121         /* clearly a mistake to advance SP */
  122         break;
  123     }
  124     /* res.typ coincides with DT_SANDWICH_D_ONLY() if we jumped here */
  125     if (ep != NULL) {
  126         *ep = sp;
  127     }
  128     return minusp ? -res : res;
  129 }
  130 
  131 static struct dt_dt_s
  132 __fixup_zdiff(struct dt_dt_s dt, int32_t zdiff)
  133 {
  134 /* apply time zone difference */
  135     /* reuse dt for result */
  136 #if defined HAVE_ANON_STRUCTS_INIT
  137     dt = dt_dtadd(dt, (struct dt_dtdur_s){DT_DURS, .dv = -zdiff});
  138 #else
  139     {
  140         struct dt_dtdur_s tmp = {DT_DURS};
  141         tmp.dv = -zdiff;
  142         dt = dt_dtadd(dt, tmp);
  143     }
  144 #endif
  145     dt.znfxd = 1;
  146     return dt;
  147 }
  148 
  149 DEFUN struct dt_dt_s
  150 __strpdt_std(const char *str, char **ep)
  151 {
  152 /* code dupe, see __strpd_std() */
  153     struct dt_dt_s res = {DT_UNK};
  154     struct strpdt_s d = {0};
  155     const char *sp;
  156 
  157     if ((sp = str) == NULL) {
  158         goto out;
  159     }
  160     /* check for epoch notation */
  161     if (*sp == '@') {
  162         /* yay, epoch */
  163         const char *tmp;
  164         d.i = strtoi(++sp, &tmp);
  165         if (UNLIKELY(d.i == -1 && sp == tmp)) {
  166             sp--;
  167         } else {
  168             /* let's make a DT_SEXY */
  169             res.typ = DT_SEXY;
  170             res.sxepoch = d.i;
  171         }
  172         goto out;
  173     }
  174     with (char *tmp) {
  175         /* let date-core do the hard yakka */
  176         if ((res.d = __strpd_std(str, &tmp)).typ == DT_DUNK) {
  177             /* not much use parsing on */
  178             goto try_time;
  179         }
  180         sp = tmp;
  181     }
  182     /* check for the d/t separator */
  183     switch (*sp) {
  184     case 'T':
  185     case ' ':
  186     case '\t':
  187         /* could be a time, could be something, else
  188          * make sure we leave a mark */
  189         str = sp++;
  190         break;
  191     default:
  192         /* should be a no-op */
  193         dt_make_d_only(&res, res.d.typ);
  194         goto out;
  195     }
  196 try_time:
  197     /* and now parse the time */
  198     if ((d.st.h = strtoi_lim(sp, &sp, 0, 24)) < 0 ||
  199         *sp != ':') {
  200         sp = str;
  201         goto out;
  202     } else if ((sp++, d.st.m = strtoi_lim(sp, &sp, 0, 59)) < 0) {
  203         d.st.m = 0;
  204         goto out;
  205     } else if (*sp != ':') {
  206         goto eval_time;
  207     } else if ((sp++, d.st.s = strtoi_lim(sp, &sp, 0, 60)) < 0) {
  208         d.st.s = 0;
  209     } else if (*sp != '.') {
  210         goto eval_time;
  211     } else if ((sp++, d.st.ns = strtoi_lim(sp, &sp, 0, 999999999)) < 0) {
  212         d.st.ns = 0;
  213         goto eval_time;
  214     }
  215 eval_time:
  216     if (UNLIKELY(d.st.h == 24)) {
  217         if (d.st.m || d.st.s || d.st.ns) {
  218             sp = str;
  219             goto out;
  220         }
  221     }
  222     res.t.hms.h = d.st.h;
  223     res.t.hms.m = d.st.m;
  224     res.t.hms.s = d.st.s;
  225     if (res.d.typ > DT_DUNK) {
  226         const char *tp;
  227         dt_make_sandwich(&res, res.d.typ, DT_HMS);
  228         /* check for the zone stuff */
  229         if ((d.zdiff = try_zone(sp, &tp))) {
  230             res = __fixup_zdiff(res, d.zdiff);
  231         } else if (tp > sp) {
  232             res.znfxd = 1U;
  233         }
  234         sp = tp;
  235     } else {
  236         dt_make_t_only(&res, DT_HMS);
  237     }
  238 out:
  239     /* res.typ coincides with DT_SANDWICH_D_ONLY() if we jumped here */
  240     if (ep != NULL) {
  241         *ep = (char*)sp;
  242     }
  243     return res;
  244 }
  245 
  246 DEFUN int
  247 __strpdt_card(struct strpdt_s *d, const char *sp, struct dt_spec_s s, char **ep)
  248 {
  249     int res = 0;
  250 
  251     switch (s.spfl) {
  252     default:
  253     case DT_SPFL_UNK:
  254         res = -1;
  255         break;
  256     case DT_SPFL_N_DSTD:
  257     case DT_SPFL_N_YEAR:
  258     case DT_SPFL_N_MON:
  259     case DT_SPFL_N_DCNT_MON:
  260     case DT_SPFL_N_DCNT_WEEK:
  261     case DT_SPFL_N_DCNT_YEAR:
  262     case DT_SPFL_N_WCNT_MON:
  263     case DT_SPFL_N_WCNT_YEAR:
  264     case DT_SPFL_S_WDAY:
  265     case DT_SPFL_S_MON:
  266     case DT_SPFL_S_QTR:
  267     case DT_SPFL_N_QTR:
  268         res = __strpd_card(&d->sd, sp, s, ep);
  269         goto out_direct;
  270 
  271     case DT_SPFL_N_TSTD:
  272     case DT_SPFL_N_HOUR:
  273     case DT_SPFL_N_MIN:
  274     case DT_SPFL_N_SEC:
  275     case DT_SPFL_N_NANO:
  276     case DT_SPFL_S_AMPM:
  277         res = __strpt_card(&d->st, sp, s, ep);
  278         goto out_direct;
  279 
  280     case DT_SPFL_N_EPOCH: {
  281         /* read over @ */
  282         const char *tp = sp;
  283         tp += *tp == '@';
  284         d->i = strtoi(tp, &tp);
  285         if (UNLIKELY(d->i < 0 || tp == sp)) {
  286             res = -1;
  287         } else {
  288             sp = tp;
  289         }
  290         break;
  291     }
  292 
  293     case DT_SPFL_N_ZDIFF: {
  294         const char *tp;
  295         if ((d->zdiff = try_zone(sp, &tp)) || tp > sp) {
  296             d->zngvn = 1;
  297         }
  298         sp = tp;
  299         break;
  300     }
  301 
  302     case DT_SPFL_LIT_PERCENT:
  303         if (*sp++ != '%') {
  304             res = -1;
  305         }
  306         break;
  307     case DT_SPFL_LIT_TAB:
  308         if (*sp++ != '\t') {
  309             res = -1;
  310         }
  311         break;
  312     case DT_SPFL_LIT_NL:
  313         if (*sp++ != '\n') {
  314             res = -1;
  315         }
  316         break;
  317     }
  318     /* assign end pointer */
  319     if (ep != NULL) {
  320         *ep = (char*)sp;
  321     }
  322 out_direct:
  323     return res;
  324 }
  325 
  326 DEFUN size_t
  327 __strfdt_card(
  328     char *buf, size_t bsz, struct dt_spec_s s,
  329     struct strpdt_s *d, struct dt_dt_s that)
  330 {
  331     size_t res = 0;
  332 
  333     switch (s.spfl) {
  334     default:
  335     case DT_SPFL_UNK:
  336         break;
  337     case DT_SPFL_N_DSTD:
  338     case DT_SPFL_N_YEAR:
  339     case DT_SPFL_N_MON:
  340     case DT_SPFL_N_DCNT_WEEK:
  341     case DT_SPFL_N_DCNT_MON:
  342     case DT_SPFL_N_DCNT_YEAR:
  343     case DT_SPFL_N_WCNT_MON:
  344     case DT_SPFL_N_WCNT_YEAR:
  345     case DT_SPFL_S_WDAY:
  346     case DT_SPFL_S_MON:
  347     case DT_SPFL_S_QTR:
  348     case DT_SPFL_N_QTR:
  349         res = __strfd_card(buf, bsz, s, &d->sd, that.d);
  350         break;
  351 
  352     case DT_SPFL_N_TSTD:
  353     case DT_SPFL_N_HOUR:
  354     case DT_SPFL_N_MIN:
  355     case DT_SPFL_N_SEC:
  356     case DT_SPFL_S_AMPM:
  357     case DT_SPFL_N_NANO:
  358         res = __strft_card(buf, bsz, s, &d->st, that.t);
  359         break;
  360 
  361     case DT_SPFL_N_EPOCH: {
  362         /* convert to sexy */
  363         int64_t sexy = dt_conv_to_sexy(that).sexy;
  364         res = snprintf(buf, bsz, "%" PRIi64, sexy);
  365         break;
  366     }
  367 
  368     case DT_SPFL_N_ZDIFF: {
  369         int32_t z = d->zdiff;
  370         char sign = '+';
  371 
  372         if (z < 0) {
  373             z = -z;
  374             sign = '-';
  375         }
  376         res = snprintf(
  377             buf, bsz, "%c%02u:%02u",
  378             sign, (uint32_t)z / 3600U, ((uint32_t)z / 60U) % 60U);
  379         break;
  380     }
  381 
  382     case DT_SPFL_LIT_PERCENT:
  383         /* literal % */
  384         buf[res++] = '%';
  385         break;
  386     case DT_SPFL_LIT_TAB:
  387         /* literal tab */
  388         buf[res++] = '\t';
  389         break;
  390     case DT_SPFL_LIT_NL:
  391         /* literal \n */
  392         buf[res++] = '\n';
  393         break;
  394     }
  395     return res;
  396 }
  397 
  398 DEFUN size_t
  399 __strfdt_dur(
  400     char *buf, size_t bsz, struct dt_spec_s s,
  401     struct strpdt_s *d, struct dt_dtdur_s that)
  402 {
  403     switch (s.spfl) {
  404     default:
  405     case DT_SPFL_UNK:
  406         return 0;
  407 
  408     case DT_SPFL_N_DSTD:
  409     case DT_SPFL_N_YEAR:
  410     case DT_SPFL_N_MON:
  411     case DT_SPFL_N_DCNT_WEEK:
  412     case DT_SPFL_N_DCNT_MON:
  413     case DT_SPFL_N_DCNT_YEAR:
  414     case DT_SPFL_N_WCNT_MON:
  415     case DT_SPFL_N_WCNT_YEAR:
  416     case DT_SPFL_S_WDAY:
  417     case DT_SPFL_S_MON:
  418     case DT_SPFL_S_QTR:
  419     case DT_SPFL_N_QTR:
  420         return __strfd_dur(buf, bsz, s, &d->sd, that.d);
  421 
  422         /* noone's ever bothered doing the same thing for times */
  423     case DT_SPFL_N_TSTD:
  424     case DT_SPFL_N_SEC:;
  425         int64_t dv;
  426 
  427         dv = that.dv;
  428         switch (that.durtyp) {
  429         default:
  430             if (that.d.durtyp != DT_DURD) {
  431                 return 0U;
  432             }
  433             dv = (int64_t)that.d.dv * HOURS_PER_DAY;
  434             /*@fallthrough@*/
  435         case DT_DURH:
  436             dv *= MINS_PER_HOUR;
  437             /*@fallthrough@*/
  438         case DT_DURM:
  439             dv *= SECS_PER_MIN;
  440             /*@fallthrough@*/
  441         case DT_DURS:
  442             if (LIKELY(!that.tai)) {
  443                 return (size_t)snprintf(
  444                     buf, bsz, "%" PRIi64 "s", dv);
  445             } else {
  446                 return (size_t)snprintf(
  447                     buf, bsz, "%" PRIi64 "rs", dv);
  448             }
  449             break;
  450         }
  451         break;
  452 
  453     case DT_SPFL_N_NANO: {
  454         int64_t dur = that.dv;
  455 
  456         switch (that.durtyp) {
  457         case DT_DURS:
  458             dur *= NANOS_PER_SEC;
  459             /*@fallthrough@*/
  460         case DT_DURNANO:
  461             if (LIKELY(!that.tai)) {
  462                 return (size_t)snprintf(
  463                     buf, bsz, "%" PRIi64 "ns", dur);
  464             } else {
  465                 return (size_t)snprintf(
  466                     buf, bsz, "%" PRIi64 "rns", dur);
  467             }
  468         default:
  469             break;
  470         }
  471         break;
  472     }
  473 
  474     case DT_SPFL_LIT_PERCENT:
  475         /* literal % */
  476         *buf = '%';
  477         break;
  478     case DT_SPFL_LIT_TAB:
  479         /* literal tab */
  480         *buf = '\t';
  481         break;
  482     case DT_SPFL_LIT_NL:
  483         /* literal \n */
  484         *buf = '\n';
  485         break;
  486     }
  487     return 1;
  488 }
  489 
  490 static size_t
  491 __strfdt_xdn(char *buf, size_t bsz, struct dt_dt_s that)
  492 {
  493     double dn;
  494 
  495     switch (that.d.typ) {
  496     case DT_JDN:
  497         dn = (double)that.d.jdn;
  498         break;
  499     case DT_LDN:
  500         dn = (double)that.d.ldn;
  501         if (dt_sandwich_only_d_p(that)) {
  502             return snprintf(buf, bsz, "%.0f", dn);
  503         }
  504         break;
  505     case DT_MDN:
  506         dn = (double)that.d.mdn;
  507         if (dt_sandwich_only_d_p(that)) {
  508             return snprintf(buf, bsz, "%.0f", dn);
  509         }
  510         break;
  511     default:
  512         return 0;
  513     }
  514 
  515     if (dt_sandwich_p(that)) {
  516         unsigned int ss = __secs_since_midnight(that.t);
  517         dn += (double)ss / (double)SECS_PER_DAY;
  518     }
  519     return snprintf(buf, bsz, "%.6f", dn);
  520 }
  521 
  522 #endif  /* INCLUDED_dt_core_strpf_c_ */