static int ReadStateChunk(FILE *st, SFORMAT *sf, int size) { SFORMAT *tmp; int temp; temp=ftell(st); while(ftell(st)<temp+size) { uint32 tsize; char toa[4]; if(fread(toa,1,4,st)<=0) return 0; read32le(&tsize,st); if((tmp=CheckS(sf,tsize,toa))) { fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st); #ifndef LSB_FIRST if(tmp->s&RLSB) FlipByteOrder(tmp->v,tmp->s&(~RLSB)); #endif } else fseek(st,tsize,SEEK_CUR); } // while(...) return 1; }
static int ReadStateChunk(MEMFILE *st, SFORMAT *sf, int size) { //if(scan_chunks) // return mem_fseek(st,size,SEEK_CUR) == 0; SFORMAT *tmp; int temp; temp=mem_ftell(st); while(mem_ftell(st)<temp+size) { uint32 tsize; char toa[4]; if(mem_fread(toa,1,4,st)<=0) return 0; mem_read32le(&tsize,st); if((tmp=CheckS(sf,tsize,toa))) { mem_fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st); #ifndef LSB_FIRST if(tmp->s&RLSB) FlipByteOrder(tmp->v,tmp->s&(~RLSB)); #endif } else { mem_fseek(st,tsize,SEEK_CUR); printf("ReadStateChunk: sect \"%c%c%c%c\" not handled\n", toa[0], toa[1], toa[2], toa[3]); } } // while(...) return 1; }
static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc) { while(sf->v) { if(sf->s==~0) /* Link to another SFORMAT structure. */ { SFORMAT *tmp; if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) return(tmp); sf++; continue; } if(!memcmp(desc,sf->desc,4)) { if(tsize!=(sf->s&(~RLSB))) { printf("ReadStateChunk: sect \"%c%c%c%c\" has wrong size\n", desc[0], desc[1], desc[2], desc[3]); return(0); } return(sf); } sf++; } return(0); }
static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size, int data_only) { SFORMAT *tmp; int temp; if(data_only) { DOReadChunk(st, sf); } else { temp = smem_tell(st); while(smem_tell(st) < temp + size) { uint32 tsize; char toa[32]; if(smem_read(st, toa, 32) <= 0) { puts("Unexpected EOF?"); return 0; } smem_read32le(st, &tsize); if((tmp=CheckS(sf,tsize,toa))) { int32 bytesize = tmp->s&(~(MDFNSTATE_RLSB32 | MDFNSTATE_RLSB16 | RLSB)); smem_read(st, (uint8 *)tmp->v, bytesize); if(tmp->s & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(tmp->v, bytesize / sizeof(uint32)); else if(tmp->s & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(tmp->v, bytesize / sizeof(uint16)); else if(tmp->s&RLSB) Endian_V_LE_to_NE(tmp->v, bytesize); } else if(smem_seek(st,tsize,SEEK_CUR) < 0) { puts("Seek error"); return(0); } } // while(...) } return 1; }
static bool ReadStateChunk(EMUFILE* is, const SFORMAT *sf, int size) { const SFORMAT *tmp = NULL; const SFORMAT *guessSF = NULL; int temp = is->ftell(); while(is->ftell()<temp+size) { u32 sz, count; char toa[4]; is->fread(toa,4); if(is->fail()) return false; if(!read32le(&sz,is)) return false; if(!read32le(&count,is)) return false; if((tmp=CheckS(guessSF,sf,sz,count,toa))) { #ifdef MSB_FIRST if(sz == 1) { //special case: read a huge byte array is->fread((char *)tmp->v,count); } else { for(unsigned int i=0;i<count;i++) { is->fread((char *)tmp->v + i*sz,sz); FlipByteOrder((u8*)tmp->v + i*sz,sz); } } #else // no need to ever loop one at a time if not flipping byte order is->fread((char *)tmp->v,sz*count); #endif guessSF = tmp + 1; } else { is->fseek(sz*count,SEEK_CUR); guessSF = NULL; } } // while(...) return true; }
static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc) { while (sf->v) { if (sf->s == ~0) { /* Link to another SFORMAT structure. */ SFORMAT *tmp; if ((tmp = CheckS((SFORMAT*)sf->v, tsize, desc))) return(tmp); sf++; continue; } if (!strncmp(desc, sf->desc, 4)) { if (tsize != (sf->s & (~RLSB))) return(0); return(sf); } sf++; } return(0); }
static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, const char *desc) { while(sf->s || sf->desc) // Size can sometimes be zero, so also check for the text description. These two should both be zero only at the end of a struct. { if(!sf->s || !sf->v) { sf++; continue; } if(sf->s==(uint32)~0) /* Link to another SFORMAT structure. */ { SFORMAT *tmp; if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) return(tmp); sf++; continue; } char check_str[32]; memset(check_str, 0, sizeof(check_str)); strncpy(check_str, sf->desc, 32); if(!memcmp(desc, check_str, 32)) { uint32 bytesize = sf->s&(~(MDFNSTATE_RLSB32 | MDFNSTATE_RLSB16 | RLSB)); if(tsize != bytesize) { printf("tsize != bytesize: %.32s\n", desc); return(0); } return(sf); } sf++; } return(0); }
namespace Class { struct A { constexpr A(int a, int b) : k(a + b) {} int k; }; constexpr int fn(const A &a) { return a.k; } static_assert_fold(fn(A(4,5)) == 9, ""); struct B { int n; int m; } constexpr b = { 0, b.n }; // expected-warning {{uninitialized}} struct C { constexpr C(C *this_) : m(42), n(this_->m) {} // ok int m, n; }; struct D { C c; constexpr D() : c(&c) {} }; static_assert_fold(D().c.n == 42, ""); struct E { constexpr E() : p(&p) {} void *p; }; constexpr const E &e1 = E(); // expected-error {{constant expression}} // This is a constant expression if we elide the copy constructor call, and // is not a constant expression if we don't! But we do, so it is. // FIXME: The move constructor is not currently implicitly defined as constexpr. // We notice this when evaluating an expression which uses it, but not when // checking its initializer. constexpr E e2 = E(); // unexpected-error {{constant expression}} static_assert_fold(e2.p == &e2.p, ""); // unexpected-error {{constant expression}} // FIXME: We don't pass through the fact that 'this' is ::e3 when checking the // initializer of this declaration. constexpr E e3; // unexpected-error {{constant expression}} static_assert_fold(e3.p == &e3.p, ""); extern const class F f; struct F { constexpr F() : p(&f.p) {} const void *p; }; constexpr F f = F(); struct G { struct T { constexpr T(T *p) : u1(), u2(p) {} union U1 { constexpr U1() {} int a, b = 42; } u1; union U2 { constexpr U2(T *p) : c(p->u1.b) {} int c, d; } u2; } t; constexpr G() : t(&t) {} } constexpr g; static_assert_fold(g.t.u1.a == 42, ""); // expected-error {{constant expression}} static_assert_fold(g.t.u1.b == 42, ""); static_assert_fold(g.t.u2.c == 42, ""); static_assert_fold(g.t.u2.d == 42, ""); // expected-error {{constant expression}} struct S { int a, b; const S *p; double d; const char *q; constexpr S(int n, const S *p) : a(5), b(n), p(p), d(n), q("hello") {} }; S global(43, &global); static_assert_fold(S(15, &global).b == 15, ""); constexpr bool CheckS(const S &s) { return s.a == 5 && s.b == 27 && s.p == &global && s.d == 27. && s.q[3] == 'l'; } static_assert_fold(CheckS(S(27, &global)), ""); struct Arr { char arr[3]; constexpr Arr() : arr{'x', 'y', 'z'} {} }; constexpr int hash(Arr &&a) { return a.arr[0] + a.arr[1] * 0x100 + a.arr[2] * 0x10000; } constexpr int k = hash(Arr()); static_assert_fold(k == 0x007a7978, ""); struct AggregateInit { const char &c; int n; double d; int arr[5]; void *p; }; constexpr AggregateInit agg1 = { "hello"[0] }; static_assert_fold(strcmp_ce(&agg1.c, "hello") == 0, ""); static_assert_fold(agg1.n == 0, ""); static_assert_fold(agg1.d == 0.0, ""); static_assert_fold(agg1.arr[-1] == 0, ""); // expected-error {{constant expression}} static_assert_fold(agg1.arr[0] == 0, ""); static_assert_fold(agg1.arr[4] == 0, ""); static_assert_fold(agg1.arr[5] == 0, ""); // expected-error {{constant expression}} static_assert_fold(agg1.p == nullptr, ""); namespace SimpleDerivedClass { struct B { constexpr B(int n) : a(n) {} int a; }; struct D : B { constexpr D(int n) : B(n) {} }; constexpr D d(3); static_assert_fold(d.a == 3, ""); } struct Bottom { constexpr Bottom() {} }; struct Base : Bottom { constexpr Base(int a = 42, const char *b = "test") : a(a), b(b) {} int a; const char *b; }; struct Base2 : Bottom { constexpr Base2(const int &r) : r(r) {} int q = 123; // FIXME: When we track the global for which we are computing the initializer, // use a reference here. //const int &r; int r; }; struct Derived : Base, Base2 { constexpr Derived() : Base(76), Base2(a) {} int c = r + b[1]; }; constexpr bool operator==(const Base &a, const Base &b) { return a.a == b.a && strcmp_ce(a.b, b.b) == 0; } constexpr Base base; constexpr Base base2(76); constexpr Derived derived; static_assert_fold(derived.a == 76, ""); static_assert_fold(derived.b[2] == 's', ""); static_assert_fold(derived.c == 76 + 'e', ""); static_assert_fold(derived.q == 123, ""); static_assert_fold(derived.r == 76, ""); static_assert_fold(&derived.r == &derived.a, ""); // expected-error {{}} static_assert_fold(!(derived == base), ""); static_assert_fold(derived == base2, ""); constexpr Bottom &bot1 = (Base&)derived; constexpr Bottom &bot2 = (Base2&)derived; static_assert_fold(&bot1 != &bot2, ""); constexpr Bottom *pb1 = (Base*)&derived; constexpr Bottom *pb2 = (Base2*)&derived; static_assert_fold(pb1 != pb2, ""); static_assert_fold(pb1 == &bot1, ""); static_assert_fold(pb2 == &bot2, ""); constexpr Base2 &fail = (Base2&)bot1; // expected-error {{constant expression}} constexpr Base &fail2 = (Base&)*pb2; // expected-error {{constant expression}} constexpr Base2 &ok2 = (Base2&)bot2; static_assert_fold(&ok2 == &derived, ""); constexpr Base2 *pfail = (Base2*)pb1; // expected-error {{constant expression}} constexpr Base *pfail2 = (Base*)&bot2; // expected-error {{constant expression}} constexpr Base2 *pok2 = (Base2*)pb2; static_assert_fold(pok2 == &derived, ""); static_assert_fold(&ok2 == pok2, ""); static_assert_fold((Base2*)(Derived*)(Base*)pb1 == pok2, ""); static_assert_fold((Derived*)(Base*)pb1 == (Derived*)pok2, ""); constexpr Base *nullB = 42 - 6 * 7; static_assert_fold((Bottom*)nullB == 0, ""); static_assert_fold((Derived*)nullB == 0, ""); static_assert_fold((void*)(Bottom*)nullB == (void*)(Derived*)nullB, ""); }