Source file: /~heha/ewa/Reluktanzmotor/cdesk-201007.zip/lvprintf.cpp

#include "lvprintf.h"
#include <windows.h>

extern TCHAR sDecimal[];

class lvprintf{
  UINT cp;
  union S{
    char*a;
    wchar_t*w;
    S(char*x):a(x) {}
    S(wchar_t*x):w(x) {}
  };
  S s;
  int slen;
  union const_S{
    const char*a;
    const wchar_t*w;
    const_S(const char*x):a(x) {}
    const_S(const wchar_t*x):w(x) {}
  };
  const_S fmt;
  va_list va;
  int dlen;
  struct P{
    int f,j,k;
    void reset() {f=0; j=-1, k=-1;}
    int&jk() {return f&0x0006 ? k:j;}
  }p;
  int pk;	// Punkt oder Komma
  void exec();
  int getchar();
  int peekchar(int);
  void putchar(int);
  char buf[34];
  void putbuf() {putstr(buf);}
  void putstr(const_S, bool=false,int maxch=-1);
public:
  lvprintf(char*_s,int _slen,const char*_fmt,va_list _va):
   cp(CP_ACP),
   s(_s),
   slen(_slen),
   fmt(_fmt),
   va(_va) {
    exec();
  }
  lvprintf(wchar_t*_s,int _slen,const wchar_t*_fmt,va_list _va):
   cp(1200),
   s(_s),
   slen(_slen),
   fmt(_fmt),
   va(_va) {
    exec();
  }
  operator int() {return dlen;}
};

void lvprintf::exec() {
  dlen=0;
  pk=*sDecimal;
  while (int c=getchar()) {
    if (c=='%') {
      p.reset();
      for (int i=0;c=peekchar(i);i++) switch (c) {
        case 'h': p.f|=0x0800; break;
        case 'l': p.f+=0x1000; break;
        case '.': p.f|=0x0002; break;	// Kommastellen
        case ',': p.f|=0x0004; break;	// Kommastellen
        case '0': p.f|=0x0008; break;
        case '+': p.f|=0x0010; break;
        case '-': p.f|=0x0020; break;	// linksbündig
        case '_': p.f|=0x0040; break;	// Signifikante Stellen
        case '\'': p.f|=0x0080; break;
        case ' ': p.f|=0x0100; break;
        case '#': p.f|=0x0200; break;
        case '*': p.jk()=va_arg(va,int); break;
	default: if ('1'<=c && c<='9') {
	  int i=p.jk();
	  if (i<0) i=0;
	  p.jk()=i*10+c-'0';
	}else switch (c) {
	  case ';': pk=p.f&0x02?'.':p.f&0x04?',':*sDecimal; break;
	  case 'd': _itoa(va_arg(va,int),buf,0); putbuf(); break;
	  case 'x':
	  case 'X': _itoa(va_arg(va,unsigned),buf,16); putbuf(); break;
	  case 's': putstr(va_arg(va,const char*),cp==1200,p.k); break;
	  case 'S': putstr(va_arg(va,const char*),cp!=1200,p.k); break;
	}
      }
    }else putchar(c);
  }
  putchar(0);
}

int lvprintf::getchar() {
  if (cp==1200) return *fmt.w++;
  return *fmt.a++;
}

int lvprintf::peekchar(int i) {
  if (cp==1200) return fmt.w[i];
  return fmt.a[i];
}

void lvprintf::putchar(int c) {
  if (!slen) return;
  if (cp==1200) *s.w++=c;
  else *s.a++=c;
  --slen;
  dlen++;
}

void lvprintf::putstr(const_S s,bool wide,int maxch) {
  int l=wide?wcslen(s.w):strlen(s.a);
  if (maxch>=0 && l>maxch) l=maxch;
  int padding=p.j-l; if (padding<0) padding=0;
  if (!(p.f&0x0020) && padding) do putchar(p.f&0x0008?'0':' '); while(--padding);
  if (l) do putchar(wide?*s.w++:*s.a++); while (--l);
  if (p.f&0x0020 && padding) do putchar(p.f&0x0008?'0':' '); while(--padding);
}

DLLFUNC int _stdcall lvvsprintfW(wchar_t*s,int slen,const wchar_t*fmt,va_list va) {
  return lvprintf(s,slen,fmt,va);	// ruft den Konstruktor und den Cast-Operator
}

DLLFUNC int _cdecl lvsprintfW(wchar_t*s,int slen,const wchar_t*fmt,...) {
  va_list va;
  va_start(va,fmt);
  int ret=lvprintf(s,slen,fmt,va);
  va_end(va);
  return ret;
}

DLLFUNC int _stdcall lvvsprintfA(char*s,int slen,const char*fmt,va_list va) {
  return lvprintf(s,slen,fmt,va);	// ruft den Konstruktor und den Cast-Operator
}

DLLFUNC int _cdecl lvsprintfA(char*s,int slen,const char*fmt,...) {
  va_list va;
  va_start(va,fmt);
  int ret=lvprintf(s,slen,fmt,va);
  va_end(va);
  return ret;
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded