2016-06-08 18 views
7

mio UUID è strutturato in questo modo:Come convertire UUID in big endian?

struct UUID_FIELDS 
{ 
    uint32_t time_low;     
    uint16_t time_mid;     
    uint16_t time_hi_and_version;  
    uint8_t clock_seq_hi_and_reserved; 
    uint8_t clock_seq_low;    
    uint8_t node[6];     

}; 

Ho funzioni che swap lungo 32 bit e confini di un swap function che scambia lungo 16 bit confini. Ho provato a chiamare swap32() su time_low e swap16() su time_mid e time_hi_and_version. Non credo di aver bisogno di scambiare byte per il resto dei campi perché due di loro sono campi a 8 bit e ho letto che la parte del nodo di un uuid non cambia. Here is a link for that reference.

Il problema è quando ho completato lo scambio il uuid che è stampato non corrisponde a quello che era in little endian prima di essere convertito.

Qual è il modo corretto per convertire un uuid seguente RFC-4122 standard di da little endian a big endian. E una volta convertiti, gli uuid dovrebbero combaciare?

+0

vedere: [online hex conversion] (http://www.scadacore.com/field-applications/programming-calculators/online-hex-converter/) –

+0

Se si è su un sistema little-endian e si riceve l'UUID come per lo standard RFC-4122 (rappresentazione big-endian) allora sì dovrete scambiare byte su 'time_low',' time_mid' e 'time_high_and_version' per usarli correttamente. – vu1p3n0x

+2

@MohammadrezaPanahi si consiglia di specificare in che modo il sito di conversione può essere correlato alla domanda specifica dell'OP (e ben formulata, posso aggiungere). Un sito utile, certo, ma come aiuta a risolvere * questo * problema? – WhozCraig

risposta

4

Re:

Aggiornamento: UUID A partire dal little endian:

446831D3-FBA1-477B-BB07-CB067B00E86B 

Risultato da correttamente scambiano i campi necessari:

FBA1477B-31D3-4468-6BE8-007B06CB07BB 

Questo sembra terribilmente sbagliato. Possiamo dedurre che se gli swap sono corrette e colpiscono solo i campi 32 e 16 bit, quindi senza scambiare i campi necessari, sarebbe questo:

Original: 446831D3-FBA1-477B-BB07-CB067B00E86B 
      |  _______/ |  _______/ 
      \____ /_______  \____ /______ 
      _____/  \ _____/  \ 
     /    |/   | 
Received: 7B47A1FB-D331-6844-6BE8-007B06CB07BB # "de-swapped". 

Cosa ti sembra di avere avere succedendo qui è byte di scambio all'interno di unità a 64 bit da qualche parte nella tua pipeline. Anche l'array di byte viene invertito, suggerendo che potrebbe essere caricato da qualche parte come parte di un carico a 64 bit, che è soggetto a un'operazione di swap64.

+0

Credo che ciò che hai dichiarato sia corretto perché ho usato una funzione di swap64 lungo un limite di 32 bit in modo da 64 bit int x = 0xAABBCCDD11223344 x swappato = 0x11223344AABBCCDD Poi ho trattato l'intero uuid come 4 32 bit inti Ho usato lo swap 32 per darmi: 0x44332211DDCCBBAA. – sebenalern

+0

La tua domanda non dice nulla su un 'swap64', però, haha. – Kaz

+0

Bene, ho una libreria di funzioni, quindi ho deciso di provarlo su tutto l'uuid invece di ogni campo. Quindi ho praticamente fatto: swap64along32 (uuid); swap32 (uuid); Non sono sicuro del motivo per cui lo scambio dei singoli campi non funzionasse. Immagino quello che hai detto. Stava trattando l'uuid come due interi a 64 bit. – sebenalern

3

Hai provato ad accedere ai singoli byte?

uint8_t packet[4]; 
uint32_t value; 
packet[0] = (value >> 24) & 0xFF; 
packet[1] = (value >> 16) & 0xFF; 
packet[2] = (value >> 8) & 0xFF; 
packet[3] = value & 0xFF; 

Probabilmente più efficiente del richiamo di una funzione. :-)

Nota: il metodo di cui sopra è indipendente dalla piattaforma. Non richiede alcuna conoscenza su come viene memorizzato il value.

Spiegazione:
Let packet essere una destinazione buffer di memoria o per un uint32_t che ha bisogno di essere memorizzati nel buffer in formato Big Endian (byte più significativo per primo).

L'espressione (value >> 24) sposta il byte più significativo nella posizione meno significativa (byte). L'espressione "& 0xff" tronca, interrompe, qualsiasi valore estraneo, risultando in un valore a 8 bit senza segno. Il valore viene quindi memorizzato nella posizione più significativa nel buffer nella prima posizione.

Allo stesso modo per i restanti byte.

+0

Non ho provato questo. Cosa rappresenta il pacchetto? Scusa, non lo seguo davvero. Puoi elaborare di più? – sebenalern

+0

Il pacchetto rappresenta il pacchetto o il buffer di destinazione. –

+0

Inoltre, non sono ancora sicuro se tutti i byte nel uuid devono essere scambiati o solo i byte che ho specificato sopra. – sebenalern

0

Il metodo consigliato è quello di utilizzare la funzione htonl (htons per 16 bit interi) convertire da byte order dell'host di rete ordine byte, e ntohl (ntohs per 16 bit interi) per convertire dall'ordine dei byte di rete per ospitare byte order

Data la seguente struttura:

struct UUID_FIELDS 
{ 
    uint32_t time_low;     
    uint16_t time_mid;     
    uint16_t time_hi_and_version;  
    uint8_t clock_seq_hi_and_reserved; 
    uint8_t clock_seq_low;    
    uint8_t node[6];     
}; 

il codice per la serializzazione e deserializzazione potrebbe essere il seguente:

std::string serialize(UUID_FIELDS fields) { 
    std::string buffer(sizeof(fields), '\0'); 

    // convert all fields with size > 1 byte to big endian (network byte order) 
    fields.time_low = htonl(fields.time_low); 
    fields.time_mid = htons(fields.time_mid); 
    fields.time_hi_and_version = htons(fields.time_hi_and_version); 

    memcpy(&buffer[0], &fields, sizeof(fields)); 

    return buffer; 
} 

UUID_FIELDS deserialize(const std::string& buffer) { 
    UUID_FIELDS fields; 

    assert(buffer.size() == sizeof(fields)); 

    memcpy(&fields, &buffer[0], sizeof(fields)); 

    // convert all fields with size > 1 byte to little endian (maybe) (host byte order) 
    fields.time_low = ntohl(fields.time_low); 
    fields.time_mid = ntohs(fields.time_mid); 
    fields.time_hi_and_version = ntohs(fields.time_hi_and_version); 

    return fields; 
} 

Si noti che è necessario concordare con il destinatario/mittente nell'endpoint remoto che si stanno inviando/ricevendo numeri in big endian.

+0

Funzionerà solo se l'host è little-endian. Se non lo è, non farà nulla. – EJP

+0

@EJP Sì, hai ragione, ecco un link che fa riferimento a questo: https://beej.us/guide/bgnet/output/html/multipage/htonsman.html "Ciò significa che su Intel queste funzioni scambiano tutti i byte in giro, e su PowerPC non fanno nulla perché i byte sono già in ordine di byte di rete. " – sebenalern

+0

@EJP Ecco come dovrebbe funzionare. Scambia i morsi se l'ordine dei byte host è little endian, non fare nulla se l'ordine dei byte host è big endian. Forse ti stavi riferendo all'altra risposta in cui i byte vengono sempre scambiati? –

Problemi correlati