Ejemplo n.º 1
0
nbt_node* nbt_parse_path(const char* filename)
{
    FILE* fp = fopen(filename, "rb");

    if(fp == NULL)
    {
        errno = NBT_EIO;
        return NULL;
    }

    nbt_node* r = nbt_parse_file(fp);
    fclose(fp);
    return r;
}
Ejemplo n.º 2
0
void dump_nbt(const char *filename)
{
    assert(errno == NBT_OK);

    FILE* f = fopen(filename, "rb");
    nbt_node* root = nbt_parse_file(f);
    fclose(f);

    if(errno != NBT_OK)
    {
        fprintf(stderr, "Parsing error!\n");
        return;
    }

    char* str = nbt_dump_ascii(root);
    nbt_free(root);

    if(str == NULL)
        fprintf(stderr, "Printing error!");

    printf("%s", str);

    free(str);
}
Ejemplo n.º 3
0
/*
 * Reads in uncompressed data and returns a buffer with the $(strat)-compressed
 * data within. Returns a NULL buffer on failure, and sets errno appropriately.
 */
static struct buffer __compress(const void* mem,
                                size_t len,
                                nbt_compression_strategy strat)
{
    struct buffer ret;
    BUFFER_INIT_(&ret);

    errno = NBT_OK;

    z_stream stream = {
        .zalloc   = Z_NULL,
        .zfree    = Z_NULL,
        .opaque   = Z_NULL,
        .next_in  = Z_NULL,//(void*)mem,
        .avail_in = 0//len
    };
    stream.next_in = (void*)mem;
    stream.avail_in = 0;

    /* "The default value is 15"... */
    int windowbits = 15;

    /* ..."Add 16 to windowBits to write a simple gzip header and trailer around
     * the compressed data instead of a zlib wrapper." */
    if(strat == STRAT_GZIP)
        windowbits += 16;

    if(deflateInit2(&stream,
                    Z_DEFAULT_COMPRESSION,
                    Z_DEFLATED,
                    windowbits,
                    8,
                    Z_DEFAULT_STRATEGY
                   ) != Z_OK)
    {
        errno = NBT_EZ;
        return ret;
    }

    assert(stream.avail_in == len); /* I'm not sure if zlib will clobber this */

    do {
        if(buffer_reserve(&ret, ret.len + CHUNK_SIZE))
        {
            errno = NBT_EMEM;
            goto compression_error;
        }

        stream.next_out  = ret.data + ret.len;
        stream.avail_out = CHUNK_SIZE;

        if(deflate(&stream, Z_FINISH) == Z_STREAM_ERROR)
            goto compression_error;

        ret.len += CHUNK_SIZE - stream.avail_out;

    } while(stream.avail_out == 0);

    (void)deflateEnd(&stream);
    return ret;

compression_error:
    if(errno == NBT_OK)
        errno = NBT_EZ;

    (void)deflateEnd(&stream);
    buffer_free(&ret);
    BUFFER_INIT_(&ret);
    return ret;
}

/*
 * Reads in zlib-compressed data, and returns a buffer with the decompressed
 * data within. Returns a NULL buffer on failure, and sets errno appropriately.
 */
static struct buffer __decompress(const void* mem, size_t len)
{
    struct buffer ret;
    BUFFER_INIT_(&ret);

    errno = NBT_OK;

    z_stream stream = {
        .zalloc   = Z_NULL,
        .zfree    = Z_NULL,
        .opaque   = Z_NULL,
        .next_in  = Z_NULL,//(void*)mem,
        .avail_in = 0//len
    };
    stream.next_in = (void*)mem;
    stream.avail_in = len;

    /* "Add 32 to windowBits to enable zlib and gzip decoding with automatic
     * header detection" */
    if(inflateInit2(&stream, 15 + 32) != Z_OK)
    {
        errno = NBT_EZ;
        return ret;
    }

    int zlib_ret;

    do {
        if(buffer_reserve(&ret, ret.len + CHUNK_SIZE))
        {
            errno = NBT_EMEM;
            goto decompression_error;
        }

        stream.avail_out = CHUNK_SIZE;
        stream.next_out  = (unsigned char*)ret.data + ret.len;

        switch((zlib_ret = inflate(&stream, Z_NO_FLUSH)))
        {
        case Z_MEM_ERROR:
            errno = NBT_EMEM;
            /* fall through */

        case Z_DATA_ERROR: case Z_NEED_DICT:
            goto decompression_error;

        default:
            /* update our buffer length to reflect the new data */
            ret.len += CHUNK_SIZE - stream.avail_out;
        }

    } while(stream.avail_out == 0);

    /*
     * If we're at the end of the input data, we'd sure as hell be at the end
     * of the zlib stream.
     */
    if(zlib_ret != Z_STREAM_END) goto decompression_error;
    (void)inflateEnd(&stream);

    return ret;

decompression_error:
    if(errno == NBT_OK)
        errno = NBT_EZ;

    (void)inflateEnd(&stream);

    buffer_free(&ret);
    BUFFER_INIT_(&ret);
    return ret;
}

/*
 * No incremental parsing goes on. We just dump the whole compressed file into
 * memory then pass the job off to nbt_parse_chunk.
 */
nbt_node* nbt_parse_file(FILE* fp)
{
    errno = NBT_OK;

    struct buffer compressed = read_file(fp);

    if(compressed.data == NULL)
        return NULL;

    nbt_node* ret = nbt_parse_compressed(compressed.data, compressed.len);

    buffer_free(&compressed);
    return ret;
}

nbt_node* nbt_parse_path(const char* filename)
{
    FILE* fp = fopen(filename, "rb");

    if(fp == NULL)
    {
        errno = NBT_EIO;
        return NULL;
    }

    nbt_node* r = nbt_parse_file(fp);
    fclose(fp);
    return r;
}