Search code examples
iosobjective-ccocoastructnsdata

NSData to Struct messing up data


So I have 2 structs, Level and Item. When i try to read the level struct everything works. But once i try to load an item my values get messed up. I've got this hex-values:

    Level-Struct| Item-Struct 
    spRot|count | type | anchorX: 25 | anchorY:375 |count
... 00 00 05 00   00 00 19 00   00 00 77 01   00 00 04 00 ...

After reading the data into a struct the values are:

type = 0
anchorX = 24576000
anchorY = 262144
pointCount = 0

it seems that it "fills" type correctly with 0 but is then going on using 00 00 77 01 (which is 24576000) instead of the correct 19 00 00 00 (25). How can i get my program to read it correct? Here are the important parts of the source:

typedef struct ItemPoint {
    SInt32 x;
    SInt32 y;
} ItemPoint;

typedef struct Item {
    UInt16 type;
    UInt32 anchorX;
    UInt32 anchorY;
    UInt32 pointCount;
    ItemPoint *points;
} Item;

typedef struct LevelStruct {
    UInt32 width;
    UInt32 height;
    UInt32 spawnX;
    UInt32 spawnY;
    UInt16 spawnRot;
    UInt16 itemCount;
    void *items;
} LevelStruct;



// Test Function

LevelStruct level;
NSUInteger byteOffset = 20;
[data getBytes:&level length:byteOffset];
BlockPolygon *poly = malloc(sizeof(BlockPolygon));
[data getBytes:poly range:NSMakeRange(byteOffset, 14)];

Solution

  • If you want to marshal your structs you should declare them as packed and use sizeof instead of magic numbers.

    typedef struct __attribute__((__packed__)) ItemPoint {
        SInt32 x;
        SInt32 y;
    } ItemPoint;
    
    typedef struct __attribute__((__packed__)) Item {
        UInt16 type;
        UInt32 anchorX;
        UInt32 anchorY;
        UInt32 pointCount;
        ItemPoint *points;
    } Item;
    
    typedef struct __attribute__((__packed__)) LevelStruct {
        UInt32 width;
        UInt32 height;
        UInt32 spawnX;
        UInt32 spawnY;
        UInt16 spawnRot;
        UInt16 itemCount;
        void *items;
    } LevelStruct;
    
    
    
    // Test Function    
    LevelStruct level;
    size_t length = sizeof(LevelStruct);
    size_t offset = 0;
    
    [data getBytes:&level length:length];
    
    offset += length;
    length = sizeof(BlockPolygon);
    
    BlockPolygon *poly = malloc(length);
    [data getBytes:poly range:NSMakeRange(offset, length)];