Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can not leave or re-enter the container when parsing the SENML-CBOR array #252

Open
Antdigapony opened this issue Apr 24, 2024 · 2 comments

Comments

@Antdigapony
Copy link

Antdigapony commented Apr 24, 2024

Hello, I am dealing with a such SENML-CBOR array:

[{0: "/3/0/10", 2: 55}]
It has one item and 2 maps as you can see.

Also this aray may be bigger, for example:
[{0: "/3/0/10", 2: 55}, {0: "/3/0/12", 3: "ResetErrors"}, {0: "/3/0/13", 6: 2889055551}, {0: "/3/0/4", 3: "Reboot"}, {0: "/3/0/9", 2: 100}].

I am trying to run through this array once, check the every first map of every item of the array and then I need to get back to the begining of this array and parse it to the end.
But I have an issue with getting back to the array's begining/start.

Here is my code with yours library've been implemented:

    err = cbor_parser_init(buffer, bufferLen, 0, &parser, &array);    
    if (err != CborNoError)
    {
        LOG_ARG("cbor_parser_init FAILED with error %d", err);
        return -1;
    }

    CborType type = cbor_value_get_type(&array);
    LOG_ARG("type = %x(%d)", type, type);
    if (type == CborArrayType) 
    {
        err = cbor_value_get_array_length(&array, &arrLen);
        if (err != CborNoError)
        {
            LOG_ARG("cbor_value_get_array_length FAILED with error %d", err);
            return -1;
        }
        LOG_ARG("array length = %d", arrLen);
        if (arrLen <= 0) {
            LOG("wrong array length FAILED");
            return -1;
        }
        if (arrLen > 0) 
        {
            sCount = prv_count_s_in_array(&array);
            LOG_ARG("s quantity = %d", sCount);
            LOG_ARG("array remaining = %d", array.remaining);
            /// Here I need to get back to the array.start and parse it "once again"
        }                                    
        
  /*  prv_count_s_in_array brief*/      
 size_t prv_count_s_in_array(CborValue* array) {
    CborValue map;
    CborError err;
    CborValue arrayStart;
    int sCount = 0;

    // Enter the CBOR array
    err = cbor_value_enter_container(array, array);
    if (err != CborNoError)
    {
        LOG_ARG("cbor_value_enter_container array FAILED with error %d", err);
        return -1;
    }

    // Save the starting position of the array
    cbor_value_get_next_byte(&arrayStart);
    arrayStart.parser = array->parser;

    // Iterate through each map in the array
    while (!cbor_value_at_end(array)) 
    {
        LOG("CHECKPOINT 1 -------------------------------------------");
        err = cbor_value_enter_container(array, &map); // Enter each map
        if (err != CborNoError)
        {
            LOG_ARG("cbor_value_enter_container map FAILED with error %d", err);
            return -1;
        }

        while (!cbor_value_at_end(&map)) 
        {
            LOG("CHECKPOINT 2 -------------------------------------------");
                
            // Skip the key
            err = cbor_value_advance(&map);
            if (err != CborNoError) {
                printf("Error advancing to value\n");
                return -1;
            }  
            // Get the value
            CborType typeMap = cbor_value_get_type(&map);
            if (typeMap == CborTextStringType) 
            {
            // If the value is a text string, count the backslashes
            // if (cbor_value_is_text_string(&map)) {
                size_t len;
                char *text;
                
                cbor_value_dup_text_string(&map, &text, &len, NULL);
                // Count *** in the string
                int sCount = countS(text);
                // Check if the count is equal to 3 (indicating a resource)
                if (sCount == 2) {
                    sCount++;
                }
            }/// MAP_NAME
            // Move to the next key-value pair
            err = cbor_value_advance(&map);
            if (err != CborNoError) {
                LOG_ARG("cbor_value_advance map FAILED with error %d", err);
                return -1;
            }
        }///!while not end map
        LOG("CHECKPOINT 4 -------------------------------------------");
        err = cbor_value_leave_container(array, &map); /// leave the map
        if (err != CborNoError)
        {
            LOG_ARG("cbor_value_leave_container array FAILED with error %d", err);
            return -1;
        }
        LOG("CHECKPOINT 5 -------------------------------------------");
        LOG_ARG("array->remaining %d", array->remaining);
        /// Move to the next map
        if (array->remaining > 1){
            err = cbor_value_advance(array);
            if (err != CborNoError) {
                LOG_ARG("cbor_value_advance array FAILED with error %d", err);
                return -1;
            }
        }
    }///!while not end of array
    /// Here I have tried to leave the array-array-container or/and enter the array-array-container once more but FAILED
    /// err = cbor_value_leave_container(array, array); /// leave the array
    ///    if (err != CborNoError)
    ///    {
    ///        LOG_ARG("cbor_value_leave_container array FAILED with error %d", err);
    ///        return -1;
    ///    }
    LOG("CHECKPOINT 6 -------------------------------------------");
    /// err = cbor_value_enter_container(array, array); /// re-enter the array
    ///    if (err != CborNoError)
    ///    {
    ///        LOG_ARG("cbor_value_leave_container array FAILED with error %d", err);
    ///        return -1;
    ///    }

    // Reset the array pointer to the starting position
    *array = arrayStart;

    return resourceCount;
} 
        

So, is the entering of the same container possible? Or, maybe, there is some other method to switch back the CborValue to the start of the cbor-buffer?
I guess that leave-container() may not work, cause there may be NO next array - we have only one array and leave_container seems to need the next value to switch to.
But, why the enter-container does not work? I have checked the array.remaining and it was 0 in the end of my function.
Now I am using a workaround - I am saving the starting point and re-setting it when I finish my checking function.
Also I want to admit that leave_container(array,map) works fine. So, question is about re-entering the array mainly.
Maybe there is something I have missed. Will be glad and grateful for any advice.

In any way, thanks for your library! Have a nice day, cheers!

@thiagomacieira
Copy link
Member

[{0: "/3/0/10", 2: 55}]
It has one item and 2 maps as you can see.

That's one array with one map, and the map has two entries. That's different from:

[{0: "/3/0/10", 2: 55}, {0: "/3/0/12", 3: "ResetErrors"}, {0: "/3/0/13", 6: 2889055551}, {0: "/3/0/4", 3: "Reboot"}, {0: "/3/0/9", 2: 100}]

That's an array with multiple maps, each of which has two entries.

   // Save the starting position of the array
   cbor_value_get_next_byte(&arrayStart);
   arrayStart.parser = array->parser;
...
   // Reset the array pointer to the starting position
   *array = arrayStart;

Don't do that. Just save the CborValue object at that state. Those objects are copyable and, if you're just reading from a buffer, you can do it all over again.

@thiagomacieira
Copy link
Member

        LOG("CHECKPOINT 4 -------------------------------------------");
        err = cbor_value_leave_container(array, &map); /// leave the map
        if (err != CborNoError)
        {
            LOG_ARG("cbor_value_leave_container array FAILED with error %d", err);
            return -1;
        }
        LOG("CHECKPOINT 5 -------------------------------------------");
        LOG_ARG("array->remaining %d", array->remaining);
        /// Move to the next map
        if (array->remaining > 1){
            err = cbor_value_advance(array);
            if (err != CborNoError) {
                LOG_ARG("cbor_value_advance array FAILED with error %d", err);
                return -1;
            }
        }

You shouldn't do that advance. The cbor_value_leave_container repositions the array iterator to the next element. I think you can just delete the block starting from CHECKPOINT 5 to the end of the loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants