#pragma once
#include <assert.h>
#if _MSC_VER < 1400 // Visual C++ 6
extern "C" unsigned long _cdecl _byteswap_ulong(unsigned long);
extern "C" unsigned __int64 _cdecl _byteswap_uint64(unsigned __int64);
namespace std{
__forceinline uint32 rotl(uint32 x, byte n) { // rotate x left by n bits
_asm mov cl,n
_asm rol x,cl
return x;
}
__forceinline uint32 rotr(uint32 x, byte n) { // rotate x right by n bits
_asm mov cl,n
_asm ror x,cl
return x;
}
__forceinline uint64 rotl(uint64 x, byte n) {return x<<n | x>>(64-n);}
__forceinline uint64 rotr(uint64 x, byte n) {return x>>n | x<<(64-n);}
#else
# include <stdlib.h>
#pragma intrinsic(_byteswap_ulong,_byteswap_uint64,_rotl,_rotr,_rotl64,_rotr64)
namespace std{
__forceinline uint32 rotl(uint32 x,byte cl) {return _rotl(x,cl);}
__forceinline uint32 rotr(uint32 x,byte cl) {return _rotr(x,cl);}
__forceinline uint64 rotl(uint64 x,byte cl) {return _rotl64(x,cl);}
__forceinline uint64 rotr(uint64 x,byte cl) {return _rotr64(x,cl);}
#endif
__forceinline uint32 byteswap(uint32 x) {
return _byteswap_ulong(x);
// _asm bswap x // geht nicht, Compilerfehler!
}
__forceinline uint64 byteswap(uint64 x) {
return _byteswap_uint64(x);
}
}
// Ein unique_ptr für die Rückgabe von Funktionen
// (die im Innern realloc() aurufen müssen)
template<class T>class autofreeptr{
T*h;
public:
autofreeptr(autofreeptr<T>&o) {h=o.h; o.h=0;} // Raubkopier-Konstruktor
autofreeptr(T*o):h(o) {} // Konstruktor mit Pointer-Übernahme (muss von alloc/realloc kommen)
~autofreeptr() {free(h);} // Destruktor = Dreierregel
void operator=(autofreeptr<T>&o) {free(h); h=o.h; o.h=0;} // Raubkopier-Zuweisung
void operator=(T*o) {free(h); h=o;} // Pointer-Übernahme (darf auch nullptr sein)
operator const T*() const {return h;}
const T*operator->() const {return h;}
};
template<class T>class fix_array{ // wie oben aber ohne operator-> für non-struct/union/class-Typen
T*h;
public:
fix_array(size_t n):h(new T[n]) {}
~fix_array() {delete[]h;}
fix_array(const fix_array&o) {h=o.h; o.h=0;}
void operator=(fix_array&o) {delete[]h; h=o.h; o.h=0;}
operator T*() {return h;}
};
// Mini-Implementierung von Strings variabler(!) Länge als Returnwert von Funktionen.
// std::string generiert umständlichen Kode.
// Auch dieser String wird (leider) per __$ReturnUdt durchgewurstelt,
// auch wenn's in 32 Bit passt, leider.
class autostring{
mutable char*s; // Nur ein Pointer!
public:
const char*c_str() const {return s;} // (Einziger) Typecast, nach Möglichkeit auch für ... verwenden
autostring(size_t n):s(new char[n]) {*s=0;} // Genereller Konstruktor
autostring(const autostring&a):s(a.s) {a.s=0;} // kommt bei return() auf den Plan
autostring(char*_s):s(_s) {} // _s muss mit new[] alloziert sein!
~autostring() {delete[]s;} // mit s==0 tut delete[] nichts, zum Glück
};
inline byte digit(char c) {
if (c<0) return c; // Fehler
if (c<='9') return c-'0';
c&=' '; // klein->groß, aber auch '@' (40) -> ' ' (20)
c-='A';
if (c<0) return c; // Fehler
return c+10;
}
// Wenn schon __$ReturnUdt dann für Strings von einigermaßen bekannter Länge!
// Das erspart new und delete komplett: Kein Heap erforderlich.
// gcc und MSVC2008+ optimieren den Kopierkonstruktor bei return weg,
// d.h. rettype buf benutzt __$ReturnUdt statt neuen Platz auf dem Stack.
// MSVC6 hingegen optimiert den Kopierkonstruktor nur bei gleichen Pointern weg.
template<unsigned N,class T=char>class String{
T s[(N+sizeof(void*)-1)&~(sizeof(void*)-1)]; // in 4-Byte- oder 8-Byte-Stückelung allokieren
public:
enum{capacity=N};
operator T*() {return s;} // so Zugriff mittels *__$ReturnUdt
const T*c_str() const {return s;} // Erforderlich für ...-Argument
};
// Lästiges Aneinanderreihen von Strings in einen Puffer per sprintf
// inklusive Überlaufschutz erleichtert diese Hilfsklasse
class Printbuf{
protected:
char*s;
unsigned n,k; // muss nicht size_t sein
public:
Printbuf(char*o,unsigned os):s(o),n(os) {reset();} // gleich nullterminieren
void reset() {s[k=0]=0;}
unsigned size() const {return k;}
unsigned capacity() const {return n;}
void _cdecl operator() (const char*,...);
};
#ifdef _MSC_VER
# define MAKEBUF(size) String<size>&buf=*__$ReturnUdt // Alias für __$ReturnUdt
#else
# define MAKEBUF(size) String<size>buf // gcc, allgemein: neuer Platz, return Kopie (wird alles wegoptimiert)
#endif
#define MAKEPRINTBUF(size) \
MAKEBUF(size); \
Printbuf print(buf,buf.capacity);
Detected encoding: ANSI (CP1252) | 4
|
|