#include <stdio.h>
#include <stdint.h>
#include <sys/time.h>

long long curTime( )
{
    timeval cur_tm;
    gettimeofday(&cur_tm,NULL);
    return (long long)cur_tm.tv_sec*1000000 + cur_tm.tv_usec;
}

inline uint32_t get_unaligned_cast32(const char *p)
{
    return *(uint32_t*)p;
}

inline uint32_t get_unaligned_memmove32(const char *p)
{
    union { uint32_t ui32; char ch[4]; } tmp;
    for(int i = 0; i < 4; i++) tmp.ch[i] = p[i];
    return tmp.ui32;
}

struct __una_u32 { uint32_t x __attribute__((packed)); };

inline uint32_t get_unaligned_cpu32(const char *p)
{
    const struct __una_u32 *ptr = (const struct __una_u32 *)p;
    return ptr->x;
}

int main()
{
    uint32_t b32;
    uint32_t bm32[10000];

    printf("Bytes order check\n");
    union
    {
	unsigned l;
	unsigned char c[4];
    } u;
    u.l = 0x12345678;
    printf("Value l = %xh\n",u.l);
    for(int i = 0; i < 4; i++)
	printf("Value c[%d] = %xh\n",i,u.c[i]);
    if(u.c[0] == 0x78) printf("Little-Endian, typical for x86.\n");
    else if(u.c[0] == 0x12) printf("Big-Endian, not typical for x86.\n");
    else printf("Unknown-Endian!\n");

    printf("Align check\n");
    char val[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
    printf("Value val{8}[1] = %x\n",val[1]);
    printf("Direct casting val{16}+1 = %x\n",*(uint16_t*)(val+1));

    //> Direct casting time
    for(int i = 0; i < 4; i++)
	printf("Direct casting val{32}+%d = %x\n",i,get_unaligned_cast32(val+i));
    long long stTime = curTime();
    for(int i = 0; i < 10000; i++)
	bm32[i] = get_unaligned_cast32(val+(i%10));
    printf("Direct casting time for 32bit 10000 integers: %0.6g ms\n",1e-3*(curTime()-stTime));

    //> Unaligned read by copy
    for(int i = 0; i < 4; i++)
	printf("Unaligned read by copy val{32}+%d = %x\n",i,get_unaligned_memmove32(val+i));
    stTime = curTime();
    for(int i = 0; i < 10000; i++)
	bm32[i] = get_unaligned_memmove32(val+(i%10));
    printf("Unaligned read by copy time for 32bit 10000 integers: %0.6g ms\n",1e-3*(curTime()-stTime));

    //> Unaligned read by attribute casting
    for(int i = 0; i < 4; i++)
	printf("Unaligned read by attribute casting val{32}+%d = %x\n",i,get_unaligned_cpu32(val+i));
    stTime = curTime();
    for(int i = 0; i < 10000; i++)
	bm32[i] = get_unaligned_cpu32(val+(i%10));
    printf("Unaligned read by attribute casting time for 32bit 10000 integers: %0.6g ms\n",1e-3*(curTime()-stTime));

    return 0;
}
