8
\$\begingroup\$

This is a byte stream implementation in C. Its usage and purpose should be evident from main.

Implementation is not finished; this is just start. Comments are still welcome.

.h:

#include <stdint.h>


typedef struct
{
    uint8_t * data;
    uint32_t length;
    uint32_t offset;
} ByteStream;


int32_t BSInitWithSize(ByteStream *bs, uint32_t len);
uint32_t BSNrOfRemainingBytes(ByteStream *bs);
int32_t BSFreeUnderlyingArray(ByteStream *bs);
void BSPrintContents(ByteStream *bs);
void BSRewind(ByteStream *bs);
int32_t BSPutU8(ByteStream *bs, uint8_t v);
int32_t BSGetU8(ByteStream *bs, uint8_t *out);
int32_t BSPutU16LE(ByteStream *bs, uint16_t v);

.c:

#include "ByteStream.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int32_t BSInitWithSize(ByteStream *bs, uint32_t len)
{
    if (NULL == bs)
        return -1;

    // Allocate data array of sufficient length
    bs->data = (uint8_t*)malloc(len); // Note: Probably should check return value here
    memset(bs->data,0,len); // set values to nil

    bs->length = len;
    bs->offset = 0;

    return 0;
}

uint32_t BSNrOfRemainingBytes(ByteStream *bs)
{
    return bs->length - bs->offset;
}

void BSRewind(ByteStream *bs)
{
    bs->offset=0;
}

int32_t BSPutU8(ByteStream *bs, uint8_t v)
{
    if(BSNrOfRemainingBytes(bs)<1)
        return -1;

    bs->data[bs->offset]=v;
    bs->offset++;

    return 0;
}

int32_t BSGetU8(ByteStream *bs, uint8_t *out)
{
    if(BSNrOfRemainingBytes(bs)<1)
        return -1;

    bs->offset++;
    *out= bs->data[bs->offset-1];

    return 0;
}

int32_t BSPutU16LE(ByteStream *bs, uint16_t v)
{
    if(BSNrOfRemainingBytes(bs)<2)
        return -1;

    // This code compiles on LE machine, so
    // copying a integer to buffer will write
    // the integer into the buffer in a little endian way
    // exactly what this method is supposed to do
    // Note: Probably this is not portable
    memcpy(&bs->data[bs->offset],&v,2);
    bs->offset+=2;

    return 0;

}

void BSPrintContents(ByteStream *bs)
{
    int i = 0;
    for(i=0; i<bs->offset; i++)
    {
        printf("%02X ",bs->data[i]);
    }
}

int32_t BSFreeUnderlyingArray(ByteStream *bs)
{
    // Free underlying data array of BS object if it is not NULL
    if(NULL != bs->data)
    {
        free(bs->data);
        bs->data=NULL; // Set to NULL
        return 0;
    }

    return -1;
}

main:

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern "C"
{
#include "ByteStream.h"
}

int _tmain(int argc, _TCHAR* argv[])
{
    ByteStream b;
    memset(&b,0,sizeof(b));

    // Init bs
    BSInitWithSize(&b,14);

    // Add values
    for(int i=0;i<12;i++)
    {
        if(-1 == BSPutU8(&b, (uint8_t)i))
            printf("Error putting data \n");

        printf("Remaining Free Bytes: %d\n",BSNrOfRemainingBytes(&b));
    }

    // Rewind
    printf("---\n");
    BSRewind(&b);

    // Print values
    for(int i=0;i<12;i++)
    {
        uint8_t t;

        if(-1 == BSGetU8(&b, &t))
        {
            printf("ERROR Getting value \n");
        }
        else
            printf("Value at %d is %d \n", i, t);
    }

    // Put short integer in a little endian way
    if(-1 == BSPutU16LE(&b,765))
        printf("Error putting short \n");

    BSPrintContents(&b);

    // Free underlying buffer
    BSFreeUnderlyingArray(&b);


    return 0;
}

In many cases I decided to return error code from functions, and pass return values as out parameters.

\$\endgroup\$

1 Answer 1

6
\$\begingroup\$

A few things:

  • You are casting the result of your calls to malloc. That is something you shouldn't do actually.
  • If possible, try not to used fixed-size integer types (uint32_t, int32_t, etc...) for they are only conditionally supported by the compiler. For example, I doubt that you need a fixed-size type for your error codes. At least, use int_least32_t instead.
  • When you are not using any format string, you should consider using puts to printf (e.g. puts("---") instead of printf("---\n"). That's both shorther and safer.
  • Also, you initialize i to 0 twice in BSPrintContents. That seems pretty useless.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.