C file operations on different architectures

As a research project, we are writing an abstraction layer on top of the standard C file processing library (BINARY) (stdio), providing several additional functions for processing files with transactions.

The workflow is as follows:

  • the user opens a file with our API (or standard fopen). Both return FILE*. File opened in BINARY mode!
  • the user writes data to a file using standard library commands (for example, fwrite)
  • the user opens an open file transaction using our API: TRANSACTION a = trans_start(FILE* )
  • the user sets the data validators for the object TRANSACTION(set_validator(TRANSACTION, int(*)(char*))
  • the user "writes" data to a file using our own API (int trans_write_string(TRANSACTION*, char*, length)
    • in fact, this "record" puts its data in memory for the validators defined above, which could perform operations on the data and set some flags somewhere ... not related to the question.
  • The user uses trans_commit(TRANSACTION)to actually write data to a file. Now, depending on the flags set by the validators, it CANNOT write data to a file, but report an error to the user (which can be resolved programmatically ... not so important for the question).
  • the user closes the file using the standard API fclose.

API (trans_write_string), . , , ..... , ..... fwrite (, C, ++ ).

(... ) API, (16 , 32 , 64 ), ... , C API stdio . , , , N ( ), 2 16- , M , 8 64- , 2 16- ..

" , , //os/endianness".

char (char* addr = &my_16bit_int) *(addr) *(addr + 1) (.. N ) , , , endiannes ? , "" - 16- ? 64- , ?

?

EDIT: , (XML), (: N 8- , 1 16- , ..) ( ). "" - "", 16- , .., - XML- "".

EDIT2: , , 20- :)

EDIT3: , !

+4
3

, , htons htonl int16 int32. int64 , :

, , , "" .

typedef union{
    unsigned char c[2];
    unsigned short s;
}U2;

//you can use the standard htons or this
unsigned short htons(unsigned short s)
{
    U2 mask,res;
    unsigned char* p = (unsigned char*)&s; 
    mask.s = 0x0001;
    res.c[mask.c[0]] = p[0];
    res.c[mask.c[1]] = p[1];
    return res.s;
}

//the same for 4 bytes
typedef union{
    unsigned char c[4];
    unsigned short s[2];
    unsigned long l;
}U4;

//you can use the standard htonl or this
unsigned long htonl(unsigned long l)
{
    U4 mask,res;
    unsigned char* p = (unsigned char*)&l; 
    mask.l = 0x00010203;
    res.c[mask.c[0]] = p[0];
    res.c[mask.c[1]] = p[1];
    res.c[mask.c[2]] = p[2];
    res.c[mask.c[3]] = p[3];
    return res.l;
}

typedef union{
    unsigned char c[8];
    unsigned char c2[2][4];
    unsigned short s[4];    
    unsigned long l[2];
    unsigned long long ll; 
}U8; 

//for int64 you can use the int64 and do the same, or you can to do it with 2*4 like i did
//you can give a void pointer as well.. 
unsigned long long htonll(unsigned long long ll)//void htonll(void* arg, void* result)
{
    U2 mask1;
    U4 mask2;
    U8 res;

    unsigned char* p = (unsigned char*)≪ //or (unsigned char*)arg   
    mask1.s = 0x0001;
    mask2.l = 0x00010203;
    //I didn't use the int64 for convertion 
    res.c2[mask1.c[0]][mask2.c[0]] = p[0];
    res.c2[mask1.c[0]][mask2.c[1]] = p[1];
    res.c2[mask1.c[0]][mask2.c[2]] = p[2];
    res.c2[mask1.c[0]][mask2.c[3]] = p[3];
    res.c2[mask1.c[1]][mask2.c[0]] = p[4];
    res.c2[mask1.c[1]][mask2.c[1]] = p[5];
    res.c2[mask1.c[1]][mask2.c[2]] = p[6];
    res.c2[mask1.c[1]][mask2.c[3]] = p[7];

    //memcpy(result,res.c,8);
    return res.ll;
}
//or if you want to use the htonl:
unsigned long long htonll2(unsigned long long ll)
{
    U2 mask1;
    U8 res;
    mask1.s = 0x0001;
    unsigned long* p = (unsigned long*)≪
    res.l[0] = htonl(p[mask1.c[0]]);
    res.l[1] = htonl(p[mask1.c[1]]);
    return res.ll;
}

int main()
{
    unsigned short s = 0x1122;
    cout<<hex<<htons(s)<<endl;
    unsigned long l = 0x11223344;
    cout<<hex<<htonl(l)<<endl;
    unsigned long long ll=0x1122334455667788;
    cout<<hex<<htonll(ll)<<endl;
    cout<<hex<<htonll2(ll)<<endl;
    return 0;
}
+2

, XDR, . , , 32- XDR:

void
write32Bits( FILE* dest, uint_least32_t value )
{
    putc( (value >> 24) & 0xFF, dest );
    putc( (value >> 16) & 0xFF, dest );
    putc( (value >>  8) & 0xFF, dest );
    putc( (value      ) & 0xFF, dest );
}

, , IEEE, pun float uint32_t double uint64_t, unsigned int. , 2- 32- , ( uint32_t int32_t).

: , IEEE , , 2 , . ( IBM - 2 , IEEE. Unisys 2 32- . , , .)

0

If you use glibc, you can use its functions to convert le & lt- → be from "endian.h":

SYNOPSIS
   #define _BSD_SOURCE             /* See feature_test_macros(7) */
   #include <endian.h>

   uint16_t htobe16(uint16_t host_16bits);
   uint16_t htole16(uint16_t host_16bits);
   uint16_t be16toh(uint16_t big_endian_16bits);
   uint16_t le16toh(uint16_t little_endian_16bits);

   uint32_t htobe32(uint32_t host_32bits);
   uint32_t htole32(uint32_t host_32bits);
   uint32_t be32toh(uint32_t big_endian_32bits);
   uint32_t le32toh(uint32_t little_endian_32bits);

   uint64_t htobe64(uint64_t host_64bits);
   uint64_t htole64(uint64_t host_64bits);
   uint64_t be64toh(uint64_t big_endian_64bits);
   uint64_t le64toh(uint64_t little_endian_64bits);

If you are not using glibc, you can just take a look at glibc-2.18 / bits / byteswap.h

0
source

All Articles