gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

pputf.cxx (6379B)


      1 /*
      2  *
      3  *  C++ Portable Types Library (PTypes)
      4  *  Version 2.1.1  Released 27-Jun-2007
      5  *
      6  *  Copyright (C) 2001-2007 Hovik Melikyan
      7  *
      8  *  http://www.melikyan.com/ptypes/
      9  *
     10  */
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 #include <stdarg.h>
     16 
     17 #include "ptypes.h"
     18 #include "pstreams.h"
     19 #include "pinet.h"      // for ipaddress type
     20 #include "ptime.h"      // for dttotm()
     21 
     22 #ifndef PTYPES_ST
     23 #include "pasync.h"     // for mutex locking in logfile::vputf()
     24 #endif
     25 
     26 
     27 namespace ptypes {
     28 
     29 
     30 // %t and %T formats
     31 const char* const shorttimefmt = "%d-%b-%Y %X";
     32 const char* const longtimefmt = "%a %b %d %X %Y";
     33 
     34 
     35 static cset fmtopts = " #+~-0-9.";
     36 
     37 
     38 enum fmt_type_t
     39 {
     40     FMT_NONE,
     41     FMT_CHAR,
     42     FMT_SHORT,
     43     FMT_INT,
     44     FMT_LONG,
     45     FMT_LARGE,
     46     FMT_STR,
     47     FMT_PTR,
     48     FMT_DOUBLE,
     49     FMT_LONG_DOUBLE,
     50     FMT_IPADDR,
     51     FMT_TIME,
     52     FMT_LONGTIME
     53 };
     54 
     55 
     56 void outstm::vputf(const char* fmt, va_list va)
     57 {
     58     const char* p = fmt;
     59     while (*p != 0)
     60     {
     61         // write out raw data between format specifiers
     62         const char* e = strchr(p, '%');
     63         if (e == 0)
     64             e = p + strlen(p);
     65         if (e > p)
     66             write(p, e - p);
     67 
     68         if (*e != '%')
     69             break;
     70 
     71         e++;
     72         if (*e == '%')
     73         {
     74             // write out a single '%'
     75             put('%');
     76             p = e + 1;
     77             continue;
     78         }
     79 
     80         // build a temporary buffer for the conversion specification
     81         char fbuf[128];
     82         fbuf[0] = '%';
     83         char* f = fbuf + 1;
     84         bool modif = false;
     85 
     86         // formatting flags and width specifiers
     87         while (*e & fmtopts && uint(f - fbuf) < sizeof(fbuf) - 5)
     88         {
     89             *f++ = *e++;
     90             modif = true;
     91         }
     92 
     93         // prefixes
     94         fmt_type_t fmt_type = FMT_NONE;
     95         switch(*e)
     96         {
     97         case 'h': 
     98             fmt_type = FMT_SHORT; 
     99             *f++ = *e++;
    100             break;
    101         case 'L': 
    102             fmt_type = FMT_LONG_DOUBLE; 
    103             *f++ = *e++;
    104             break;
    105         case 'l':
    106             e++;
    107             if (*e == 'l')
    108             {
    109 #if defined(_MSC_VER) || defined(__BORLANDC__)
    110                 *f++ = 'I';
    111                 *f++ = '6';
    112                 *f++ = '4';
    113 #else
    114                 *f++ = 'l';
    115                 *f++ = 'l';
    116 #endif
    117                 e++;
    118                 fmt_type = FMT_LARGE;
    119             }
    120             else
    121             {
    122                 *f++ = 'l';
    123                 fmt_type = FMT_LONG;
    124             }
    125             break;
    126         }
    127 
    128         // format specifier
    129         switch(*e)
    130         {
    131         case 'c':
    132             fmt_type = FMT_CHAR;
    133             *f++ = *e++;
    134             break;
    135         case 'd':
    136         case 'i':
    137         case 'o':
    138         case 'u':
    139         case 'x':
    140         case 'X':
    141             if (fmt_type < FMT_SHORT || fmt_type > FMT_LARGE)
    142                 fmt_type = FMT_INT;
    143             *f++ = *e++;
    144             break;
    145         case 'e':
    146         case 'E':
    147         case 'f':
    148         case 'g':
    149         case 'G':
    150             if (fmt_type != FMT_LONG_DOUBLE)
    151                 fmt_type = FMT_DOUBLE;
    152             *f++ = *e++;
    153             break;
    154         case 's':
    155             fmt_type = FMT_STR;
    156             *f++ = *e++;
    157             break;
    158         case 'p':
    159             fmt_type = FMT_PTR;
    160             *f++ = *e++;
    161             break;
    162         case 'a':
    163             fmt_type = FMT_IPADDR;
    164             *f++ = *e++;
    165             break;
    166         case 't':
    167             fmt_type = FMT_TIME;
    168             *f++ = *e++;
    169             break;
    170         case 'T':
    171             fmt_type = FMT_LONGTIME;
    172             *f++ = *e++;
    173             break;
    174         }
    175 
    176         if (fmt_type == FMT_NONE)
    177             break;
    178 
    179         *f = 0;
    180 
    181         // some formatters are processed here 'manually',
    182         // while others are passed to snprintf
    183         char buf[4096];
    184         int s = 0;
    185         switch(fmt_type)
    186         {
    187         case FMT_NONE: 
    188             break; // to avoid compiler warning
    189         case FMT_CHAR:
    190             if (modif)
    191                 s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,int)); 
    192             else
    193                 put(char(va_arg(va,int)));
    194             break;
    195         case FMT_SHORT:
    196             s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,int)); 
    197             break;
    198         case FMT_INT:
    199             s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,int)); 
    200             break;
    201         case FMT_LONG:
    202             s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,long)); 
    203             break;
    204         case FMT_LARGE:
    205             s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,large)); 
    206             break;
    207         case FMT_STR:
    208             if (modif)
    209                 s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,char*));
    210             else
    211                 put(va_arg(va,const char*));
    212             break;
    213         case FMT_PTR:
    214             s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,void*)); 
    215             break;
    216         case FMT_DOUBLE:
    217             s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,double)); 
    218             break;
    219         case FMT_LONG_DOUBLE:
    220             s = snprintf(buf, sizeof(buf), fbuf, va_arg(va,long double)); 
    221             break;
    222 
    223         case FMT_IPADDR:
    224             {
    225                 ipaddress ip = va_arg(va,long);
    226                 s = snprintf(buf, sizeof(buf), "%d.%d.%d.%d", 
    227                     uint(ip[0]), uint(ip[1]), uint(ip[2]), uint(ip[3]));
    228             }
    229             break;
    230 
    231         case FMT_TIME:
    232         case FMT_LONGTIME:
    233             {
    234                 const char* const fmt = (fmt_type == FMT_TIME) ? shorttimefmt : longtimefmt;
    235                 struct tm t;
    236                 datetime dt = va_arg(va,large);
    237                 if (dt < 0)
    238                     dt = 0;
    239                 s = strftime(buf, sizeof(buf), fmt, dttotm(dt, t));
    240             }
    241             break;
    242         }
    243         if (s > 0)
    244             write(buf, s);
    245         
    246         p = e;
    247     }
    248 }
    249 
    250 
    251 void outstm::putf(const char* fmt, ...)
    252 {
    253     va_list va;
    254     va_start(va, fmt);
    255     vputf(fmt, va);
    256     va_end(va);
    257 }
    258 
    259 
    260 void fdxstm::putf(const char* fmt, ...)
    261 {
    262     va_list va;
    263     va_start(va, fmt);
    264     out.vputf(fmt, va);
    265     va_end(va);
    266 }
    267 
    268 
    269 void logfile::vputf(const char* fmt, va_list va)
    270 {
    271 #ifndef PTYPES_ST
    272     scopelock sl(lock);
    273 #endif
    274     outfile::vputf(fmt, va);
    275 }
    276 
    277 
    278 void logfile::putf(const char* fmt, ...)
    279 {
    280     va_list va;
    281     va_start(va, fmt);
    282     vputf(fmt, va);
    283     va_end(va);
    284 }
    285 
    286 
    287 }