Home > Net >  Split unsigned char array into array of multiple unsigned char array
Split unsigned char array into array of multiple unsigned char array

Time:10-19

My application is composed of a controller which has several children. The controller use pipe to communicate with is a first child, and child use pipe between us to transfer the question to the next sibling. When a child can process the question, it sends a frame to the controller pipe to make an acquittal.

My problem is because every child could write in the controller pipe, It's possible that the controller read multiple child's frame in the same stream.

So, I want to split this stream to process the child frame individual.

The controller receives only one type of frame :

Acquittal Frame
0                 1                 2                 3
 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
 - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|       CMD       |     NODE ID     |    ERROR FLAG   |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|      DATA LENGTH (optional)       |                 |
 - - - - - - - - - - - - - - - - - -                  |
|   DATA WITH UNDETERMINED SIZE (char *) (optional)   |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    END FRAME    |
 - - - - - - - - - 

This frame is compose of multiple information :

  • CMD : the acquittal commend that say to controller which question the child respond
  • NODE ID : the unique identifier of a child
  • Error flag : that can have different value in function of result and commands

The commands :

  • A_SET(0xA2) :
    • This command admits only 2 error flag SUCCESS(0x20) and INTERNAL_ERROR(0x50)
    • With this cmd the frame size is 4 no data length and data
  • A_DUMP(0xD2) :
    • This command admits only 2 error flag SUCCESS(0x20) and INTERNAL_ERROR(0x50)
    • With this cmd the frame size is 4 no data length and data
  • A_LOOKUP(0xB2) :
    • If this command has error flag INTERNAL_ERROR(0x50) or NOT_FOUND(0x44) the frame size will be 4
    • If this command has error flag SUCCESS(0x20) the frame size will be 4 DATA LENGTH witch is encode in two bytes

So in my case for example I want this :

{0xd2,0x04,0x20,0x04,0xd2,0x05,0x20,0x04,0xd2,0x06,0x20,0x04,0xd2,0x07,0x20,0x04,0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}

And I want to extract an array that look like that :

[0] : {0xd2,0x04,0x20,0x04}
[1] : {0xd2,0x05,0x20,0x04}
[2] : {0xd2,0x06,0x20,0x04}
[3] : {0xd2,0x07,0x20,0x04}
[4] : {0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}

I have tried multiple thing to do that : with manual array parkour, with strtok() function. So, I show you the last attempt with the stork function here:

enum frameComponents {
    END_FRAME=(unsigned char)0x04,
    ...
}
...

unsigned int getNbFrames(unsigned char * framesStream){
    unsigned int lenFrames = strlen((char * )framesStream);
    unsigned int i,k;
    for(i=0,k=0;i<lenFrames;i  ){
        if(framesStream[i]==END_FRAME){
            k  ;
        }
    }
    return k;
}


unsigned char ** deserialisation(unsigned char * frameStream){
    //this function return the number of identify frame in the stream
    unsigned int nbFrame = getNbFrames(frameStream);
    unsigned int lenFrames = strlen((char * )frameStream);
    unsigned char **framesArray = malloc(nbFrame * sizeof(unsigned char *));
    unsigned char *tempFrameStream = malloc(sizeof(unsigned char)*lenFrames 1);
    unsigned char * extractedFrame = (unsigned char *) strtok(tempFrameStream, (char *)END_FRAME);
    strcpy((char *)tempFrameStream,(char *) frameStream);
    int i = 0;
    while(extractedFrame != NULL ) {
        extractedFrame = (unsigned char *) strtok(NULL, (char *)END_FRAME);
        framesArray[i]= malloc(strlen((char *)extractedFrame) 1);
        strcpy((char *)framesArray[i],(char *)extractedFrame);
        i  ;
    }
    free(tempFrameStream);
    free(extractedFrame);
    return framesArray;
}

But I have multiple problem here

First, strtok() don't seem to work properly because when I try with one string, I have null return in my array. I don't know if that come from the unsigned int type of my array?

Secondly, when I try to access to frame array outside the function, I have segmentation fault. Even with the malloc() in my array

CodePudding user response:

As your input data isn't a string but a raw byte stream (aka a stream of unsigned chars), you can't use string functions for the decoder.

You need to implement a parser that takes the protocol into account, i.e. you need to look at each frame and see what command it is. Once you know the command, you can parse the data accordingly.

I will not implement a full parser for you but below is some code that show the principal. The code doesn't put the frames into allocated memory (I'll leave that to you), the code just prints the frame (in 2 out of 3 cases, the last I will leave to you to implement.

#define A_SET (0xA2)
#define A_DUMP (0xD2)
#define A_LOOKUP (0xB2)

void deserialisation(unsigned char * frameStream, size_t n)
{
    size_t index = 0;
    while (index < n)
    {
        switch(frameStream[index])
        {
            case A_SET:
                if (index   4 > n)
                {
                    puts("Too little data! can't continue...");
                    index = n;
                }
                else
                {
                    // Good frame - just print it for now
                    printf("A_SET cmd: ");
                    for (size_t i = 0; i < 4;   i) printf("0xX ", frameStream[index   i]);
                    puts("");
                    index  = 4;
                }
                break;
                
            case A_DUMP:
                if (index   4 > n)
                {
                    puts("Too little data! can't continue...");
                    index = n;
                }
                else
                {
                    // Good frame - just print it for now
                    printf("A_DUMP cmd: ");
                    for (size_t i = 0; i < 4;   i) printf("0xX ", frameStream[index   i]);
                    puts("");
                    index  = 4;
                }
                break;
                
            case A_LOOKUP:
                printf("A_LOOKUP cmd: ");
                // Add code here...
                break;
                
            default:
                puts("Unknow frame! Can't continue...");
                index = n;
                break;
        }
    }
}
    
int main(void)
{
    unsigned char pipeData[] = {0xA2, 0x01, 0x20, 0x04, 0xD2, 0x14, 0x50, 0x04};
    deserialisation(pipeData, sizeof pipeData / sizeof pipeData[0]);
    return 0;
}

Output:

A_SET cmd: 0xA2 0x01 0x20 0x04 
A_DUMP cmd: 0xD2 0x14 0x50 0x04 
  • Related