Skip to content

File notation_wptt.c

File List > note-wptt > src > notation_wptt.c

Go to the documentation of this file

#include "notation_wptt.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"

/******************************************************************************/
/************************** Private Typedef ***********************************/
/******************************************************************************/

typedef uint8_t (*char_handler_funptr_t)(char **str);

typedef struct note_wptt_decode_char_dic_t {
    char *                char_class;
    char_handler_funptr_t funptr;
} note_wptt_decode_char_dic_t;

/******************************************************************************/
/************************** Defines *******************************************/
/******************************************************************************/

#define NOTE_WPTT_V4_LABEL_I_STR      ('i')

#define NOTE_WPTT_V4_LABEL_X_STR      ('x')

#define NOTE_WPTT_V4_LABEL_Y_STR      ('y')

#define NOTE_WPTT_V4_LABEL_Z_STR      ('z')

#define NOTE_WPTT_STACK_SIZE          (UTIL_TANG_DEFS_MAX_CROSSINGNUM)

#define NOTE_WPTT_DECODE_DICT_SIZE    (6u)

#define NOTE_WPTT_INT_BASE            (10u)

/******************************************************************************/
/************************** Private Function Declarations *********************/
/******************************************************************************/

/************************** Decode path Function Declarations *****************/
STATIC_INLINE_UINT8 note_wptt_decode_push_node();
STATIC_INLINE note_wptt_V4_label_e note_wptt_decode_get_v4_label(char label);
STATIC_INLINE bool note_wptt_decode_check_charset(const char *valid_chars,
                                                  const char str);
STATIC_INLINE_UINT8 note_wptt_decode_add_child();
STATIC_INLINE_UINT8 note_wptt_decode_space_handler(char **str);
STATIC_INLINE_UINT8 note_wptt_decode_opn_p_handler(char **str);
STATIC_INLINE_UINT8 note_wptt_decode_opn_a_handler(char **str);
STATIC_INLINE_UINT8 note_wptt_decode_opn_b_handler(char **str);
STATIC_INLINE_UINT8 note_wptt_decode_cls_handler(char **str);
STATIC_INLINE_UINT8 note_wptt_decode_weight_handler(char **str);

/************************** Encode path Function Declarations *****************/

STATIC_INLINE bool note_wptt_encode_stick_check(note_wptt_node_t *active_node_p);
STATIC_INLINE void note_wptt_encode_normalize_node_order(note_wptt_node_t *active_node_p);
STATIC_INLINE_UINT8 note_wptt_encode_insert_label(note_wptt_V4_label_e label,
                                                  char **str_p,
                                                  const char *buffer_end_p);

STATIC_INLINE_UINT8 note_wptt_encode_insert_char(char new_char,
                                                 char **str_p,
                                                 const char *buffer_end_p);

STATIC_INLINE_UINT8 note_wptt_encode_insert_int(int8_t new_int,
                                                char **str_p,
                                                const char *buffer_end_p);

STATIC_INLINE_UINT8 note_wptt_encode_insert_space(char **str_p,
                                                  const char *buffer_start_p,
                                                  const char *buffer_end_p);

STATIC_INLINE_UINT8 note_wptt_encode_insert_stick(note_wptt_node_t *active_node_p,
                                                  char **str_p,
                                                  const char *buffer_end_p);

STATIC_INLINE_UINT8 note_wptt_encode_complete_active_node(const note_wptt_node_t *active_node_p,
                                                          char **str_p,
                                                          size_t ordered_child_idx,
                                                          const char *buffer_start_p,
                                                          const char *buffer_end_p);
STATIC_INLINE_UINT8 note_wptt_encode_process_active_node(note_wptt_node_t *active_node_p,
                                                         char **str_p,
                                                         size_t ordered_child_idx,
                                                         const char *buffer_start_p,
                                                         const char *buffer_end_p);

/******************************************************************************/
/************************** Local Variables ***********************************/
/******************************************************************************/

static note_wptt_node_t *wptt_node_stack[NOTE_WPTT_STACK_SIZE] = { NULL };

static size_t wptt_stack_len = 0;

static note_wptt_node_buffer_t *decode_buffer = NULL;

uint8_t child_idx_stack[UTIL_TANG_DEFS_MAX_CROSSINGNUM];
/******************************************************************************/
/************************** Public Function Definitions ***********************/
/******************************************************************************/

/*
 *  Documentation in header
 */
uint8_t note_wptt_decode(char *str, note_wptt_t *wptt)
{
    uint8_t retval = NOTE_DEFS_DECODE_SUCCESS;

    /*Clear the buffer and stack*/
    decode_buffer      = NULL;
    wptt_node_stack[0] = NULL;
    wptt_stack_len     = 0;

    /*Initialize the character checking dictionary*/
    const note_wptt_decode_char_dic_t charcheck_dict[] = {
        { "(",           &note_wptt_decode_opn_p_handler  },
        { "<",           &note_wptt_decode_opn_a_handler  },
        { "[",           &note_wptt_decode_opn_b_handler  },
        { ")>",          &note_wptt_decode_cls_handler    },
        { " ",           &note_wptt_decode_space_handler  },
        { "-0123456789", &note_wptt_decode_weight_handler }
    };

    /*Do basic error checking.*/
    if (strlen(str) <= 2)
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_EMPTY_STR);
    }
    else if (NULL == wptt)
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_NULL_DEST);
    }
    else if ((NULL == wptt->node_buffer->buffer) || (0 == wptt->node_buffer->size))
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_BUFFER_ERROR);
    }
    else
    {
        /*Main logic of the decode flow*/

        /*Initialize buffer reference to node buffer*/
        decode_buffer = wptt->node_buffer;

        /*Initialize wptt root from buffer*/
        wptt->root        = &(decode_buffer->buffer[decode_buffer->idx]);
        wptt->root->order = NOTE_WPTT_ORDER_FORWARD;

        /*Check if the string has a V_4 label*/
        wptt->label = note_wptt_decode_get_v4_label(str[0]);
        if (NOTE_WPTT_V4_LABEL_NONE != wptt->label)
        {
            str++;
        }

        /*While string still has content and nothing has gone wrong*/
        while (str[0] != '\0' && (NOTE_DEFS_DECODE_SUCCESS == retval))
        {
            size_t i;

            /*For each item in the dictionary*/
            for (i = 0u; i < NOTE_WPTT_DECODE_DICT_SIZE; i++)
            {
                if (true == note_wptt_decode_check_charset(charcheck_dict[i].char_class, str[0]))
                {
                    retval |= charcheck_dict[i].funptr(&str);
                    break;
                }
            }
            /*If current character is not in any set throw error*/
            if (i == NOTE_WPTT_DECODE_DICT_SIZE)
            {
                retval |= NOTE_STATUS_BLDR(NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_BAD_STR);
            }
        }
    }
    return retval;
}

/*
 *  Documentation in header
 */
uint8_t note_wptt_encode(note_wptt_t wptt, char *str, size_t buffer_size)
{
    uint8_t     retval = NOTE_DEFS_ENCODE_SUCCESS;
    const char *buffer_end_p;
    const char *buffer_start_p;

    wptt_node_stack[0]  = wptt.root;
    wptt_stack_len      = 0x1u;
    child_idx_stack[0u] = 0;

    /*Do basic error checking.*/
    if (0 == buffer_size)
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_STR_BUF);
    }
    else if (NULL == str)
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_STR_BUF);
    }
    else
    {
        buffer_end_p   = str + (buffer_size - 1);
        buffer_start_p = str;
        retval        |= note_wptt_encode_insert_label(wptt.label, &str, buffer_end_p);
        /*While stack is not empty and string buffer has space*/
        while ((0 < wptt_stack_len) && (str < buffer_end_p) &&
               (NOTE_DEFS_ENCODE_SUCCESS == retval))
        {
            note_wptt_node_t *active_node_p = wptt_node_stack[wptt_stack_len - 1];

            /*Do basic error checking.*/
            if (NULL == active_node_p)
            {
                retval |= NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_MALFORMED);
                break;
            }
            else if (active_node_p->order == NOTE_WPTT_ORDER_UNINIT)
            {
                retval |= NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_MALFORMED);
                break;
            }
            else
            {
                note_wptt_encode_normalize_node_order(active_node_p);
                size_t ordered_child_idx = child_idx_stack[wptt_stack_len - 1];
                /*Check if active node is complete*/
                if (active_node_p->number_of_children <
                    child_idx_stack[wptt_stack_len - 1])
                {
                    retval |= note_wptt_encode_complete_active_node(active_node_p,
                                                                    &str,
                                                                    ordered_child_idx,
                                                                    buffer_start_p,
                                                                    buffer_end_p);

                    /*Pop stack*/
                    if (0 < wptt_stack_len)
                    {
                        wptt_stack_len--;
                    }
                    else
                    {
                        retval |= NOTE_STATUS_BLDR(
                            NOTE_DEFS_ENCODE_FAIL,
                            NOTE_WPTT_ENCODE_OVRUNDR_ERROR);
                    }
                }
                else
                {
                    retval |= note_wptt_encode_process_active_node(active_node_p,
                                                                   &str,
                                                                   ordered_child_idx,
                                                                   buffer_start_p,
                                                                   buffer_end_p);
                }
            }
        }
        /*Finish string*/
        if (str < buffer_end_p)
        {
            str[0] = '\0';
        }
        else
        {
            retval |= NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_OVRUNDR_ERROR);
        }
    }
    return retval;
}

/******************************************************************************/
/************************** Private Function Definitions **********************/

/************************** Decode Path Functions *****************************/

STATIC_INLINE note_wptt_V4_label_e note_wptt_decode_get_v4_label(char label)
{
    note_wptt_V4_label_e retval = NOTE_WPTT_V4_LABEL_UNINIT;

    /*Check if the string has a V_4 label*/
    switch (label)
    {
    case NOTE_WPTT_V4_LABEL_I_STR:
    {
        retval = NOTE_WPTT_V4_LABEL_I;
        break;
    }

    case NOTE_WPTT_V4_LABEL_X_STR:
    {
        retval = NOTE_WPTT_V4_LABEL_X;
        break;
    }

    case NOTE_WPTT_V4_LABEL_Y_STR:
    {
        retval = NOTE_WPTT_V4_LABEL_Y;
        break;
    }

    case NOTE_WPTT_V4_LABEL_Z_STR:
    {
        retval = NOTE_WPTT_V4_LABEL_Z;
        break;
    }

    default:
    {
        retval = NOTE_WPTT_V4_LABEL_NONE;
    }
    }
    return retval;
}

STATIC_INLINE bool note_wptt_decode_check_charset(const char *valid_chars,
                                                  const char str_char)
{
    bool   retval = false;
    size_t i;

    for (i = 0; i < strlen(valid_chars); i++)
    {
        if (str_char == valid_chars[i])
        {
            retval = true;
            break;
        }
    }
    return retval;
}

/* cppcheck-suppress constParameterPointer*/
STATIC_INLINE_UINT8 note_wptt_decode_space_handler(char **str)
{
    /* cppcheck-suppress uselessAssignmentPtrArg*/
    /* cppcheck-suppress unreadVariable*/
    (*str)++;
    return NOTE_DEFS_DECODE_SUCCESS;
}

STATIC_INLINE_UINT8 note_wptt_decode_opn_p_handler(char **str)
{
    uint8_t retval = NOTE_DEFS_DECODE_SUCCESS;

    retval |= note_wptt_decode_push_node();
    retval |= note_wptt_decode_add_child();
    (*str)++;
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_decode_opn_b_handler(char **str)
{
    uint8_t retval = NOTE_DEFS_DECODE_SUCCESS;
    int8_t  weights[UTIL_TANG_DEFS_MAX_CROSSINGNUM] = { 0 };
    size_t  num_of_weights = 0;

    (*str)++;
    while ((']' != (*str)[0]) && ('\0' != (*str)[0]) &&
           (NOTE_DEFS_DECODE_SUCCESS == retval))
    {
        if ((('0' <= (*str)[0]) && ((*str)[0] <= '9')) || ((*str)[0] == '-'))
        {
            weights[num_of_weights] = strtol(*str, str, NOTE_WPTT_INT_BASE);
            num_of_weights++;
            if (' ' == (*str)[0])
            {
                (*str)++;
            }
        }
        else
        {
            retval |= NOTE_STATUS_BLDR(
                NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_BAD_STR);
        }
    }

    if ((']' == (*str)[0]) && (NOTE_DEFS_DECODE_SUCCESS == retval))
    {
        size_t  i;
        uint8_t pre_stick_stack_len = wptt_stack_len;
        (*str)++;
        for (i = 1; i < num_of_weights; i++)
        {
            retval |= note_wptt_decode_push_node();
            retval |= note_wptt_decode_add_child();
            if (0 == i % 2)
            {
                weights[num_of_weights - i] *= -1;
            }
            wptt_node_stack[wptt_stack_len - 1]->weights[1u] =
                weights[num_of_weights - i];
        }
        if (0 == num_of_weights % 2)
        {
            weights[0] *= -1;
        }
        retval |= note_wptt_decode_push_node();
        retval |= note_wptt_decode_add_child();
        wptt_node_stack[wptt_stack_len - 1]->weights[0] = weights[0];
        wptt_stack_len = pre_stick_stack_len;
    }
    else
    {
        retval |= NOTE_STATUS_BLDR(
            NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_BAD_STR);
    }

    return retval;
}

STATIC_INLINE_UINT8 note_wptt_decode_opn_a_handler(char **str)
{
    uint8_t retval = NOTE_DEFS_DECODE_SUCCESS;

    retval |= note_wptt_decode_push_node();
    retval |= note_wptt_decode_add_child();
    (*str)++;

    if (NOTE_DEFS_ENCODE_SUCCESS == retval)
    {
        /*Check that the char looks like the start of an integer.*/
        if (!(('0' <= ((*str))[0]) && ((*str)[0] <= '9')) && ((*str)[0] != '-'))
        {
            retval |= NOTE_STATUS_BLDR(NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_BAD_STR);
        }
        else if (0 == wptt_stack_len)
        {
            retval |= NOTE_STATUS_BLDR(NOTE_DEFS_DECODE_FAIL, NOTE_WPTT_DECODE_OVRUNDR_ERROR);
        }
        else
        {
            note_wptt_node_t *active_node_p = wptt_node_stack[wptt_stack_len - 1];
            active_node_p->number_of_rings = strtol(*str, str, NOTE_WPTT_INT_BASE);
        }
    }
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_decode_cls_handler(char **str)
{
    uint8_t retval = NOTE_DEFS_DECODE_SUCCESS;

    wptt_stack_len--;
    (*str)++;
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_decode_weight_handler(char **str)
{
    uint8_t           retval        = NOTE_DEFS_DECODE_SUCCESS;
    note_wptt_node_t *active_node_p = wptt_node_stack[wptt_stack_len - 1];

    active_node_p->weights[active_node_p->number_of_children] = strtol(
        *str, str, NOTE_WPTT_INT_BASE);
    if (' ' == (*str)[0])
    {
        retval |= NOTE_STATUS_BLDR(NOTE_DEFS_DECODE_FAIL,
                                   NOTE_WPTT_DECODE_OVRUNDR_ERROR | NOTE_WPTT_DECODE_BAD_STR);
    }
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_decode_push_node()
{
    uint8_t retval = NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_DECODE_OVRUNDR_ERROR);

    /* Check that we don't have a buffer overflow*/
    if ((decode_buffer->idx) + 1 < (decode_buffer->size) &&
        (wptt_stack_len + 1 < NOTE_WPTT_STACK_SIZE))
    {
        size_t            i;
        note_wptt_node_t *new_node = &decode_buffer->buffer[decode_buffer->idx];
        retval = NOTE_DEFS_DECODE_SUCCESS;
        /*Clear out new node*/
        for (i = 0; i < NOTE_WPTT_DECODE_MAX_WEIGHTS; i++)
        {
            new_node->weights[i] = 0;
        }

        for (i = 0; i < NOTE_WPTT_DECODE_MAX_CHILDREN; i++)
        {
            new_node->children[i] = NULL;
        }
        new_node->number_of_children = 0;
        new_node->number_of_rings    = 0;
        new_node->order = NOTE_WPTT_ORDER_FORWARD;

        /*Push new node to stack*/
        wptt_node_stack[wptt_stack_len] = new_node;

        /*Move buffer position to clean block*/
        decode_buffer->idx++;
        /* Move stack pointer up*/
        wptt_stack_len++;
    }
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_decode_add_child()
{
    uint8_t retval = NOTE_STATUS_BLDR(
        NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_DECODE_OVRUNDR_ERROR);

    /*Check if there is open space on the stack*/
    if ((0 < wptt_stack_len) && (wptt_stack_len < NOTE_WPTT_STACK_SIZE))
    {
        retval = NOTE_DEFS_DECODE_SUCCESS;

        /*Check if the active node is the root*/
        if (1 < wptt_stack_len)
        {
            note_wptt_node_t *active_node_p = wptt_node_stack[wptt_stack_len - 2];

            /*Add child to active node*/
            active_node_p->children[active_node_p->number_of_children] =
                wptt_node_stack[wptt_stack_len - 1];
            active_node_p->number_of_children++;
        }
    }
    return retval;
}

/************************** Encode Path Functions   **************************/

STATIC_INLINE bool note_wptt_encode_stick_check(note_wptt_node_t *active_node_p)
{
    bool retval = false;
    note_wptt_node_t *child_node = active_node_p;

    while ((child_node->number_of_children < 2) &&
           (0 == child_node->number_of_rings) &&
           ((0 == child_node->weights[0]) ||
            (0 == child_node->number_of_children)))
    {
        if (0 == child_node->number_of_children)
        {
            retval = true;
            break;
        }
        child_node = child_node->children[0];
    }

    return retval;
}

STATIC_INLINE void note_wptt_encode_normalize_node_order(
    note_wptt_node_t *active_node_p)
{
    if (NOTE_WPTT_ORDER_REVERSE == active_node_p->order)
    {
        size_t i = 0;
        for (i = 0; 2 * i < active_node_p->number_of_children; i++)
        {
            size_t            back_child_pos  = (active_node_p->number_of_children - 1) - i;
            size_t            back_weight_pos = active_node_p->number_of_children - i;
            note_wptt_node_t *child           = active_node_p->children[i];
            uint8_t           weight          = active_node_p->weights[i];

            active_node_p->children[i] = active_node_p->children[back_child_pos];
            active_node_p->children[back_child_pos] = child;

            active_node_p->weights[i] = active_node_p->weights[back_weight_pos];
            active_node_p->weights[back_weight_pos] = weight;
        }
        active_node_p->order = NOTE_WPTT_ORDER_FORWARD;
    }
}

STATIC_INLINE_UINT8 note_wptt_encode_insert_stick(note_wptt_node_t *active_node_p,
                                                  char **str_p,
                                                  const char *buffer_end_p)
{
    uint8_t           retval = NOTE_DEFS_ENCODE_FAIL;
    int8_t            weights[UTIL_TANG_DEFS_MAX_CROSSINGNUM] = { 0 };
    uint8_t           weight_idx = 0;
    note_wptt_node_t *child_node = active_node_p;
    size_t            i          = 0;

    retval = note_wptt_encode_insert_char('[', str_p, buffer_end_p);

    /*Collect interior weights*/
    while (0 < child_node->number_of_children)
    {
        weights[weight_idx] = child_node->weights[1];
        if (1 == weight_idx % 2)
        {
            weights[weight_idx] *= -1;
        }
        weight_idx++;
        child_node = child_node->children[0];
    }
    /*Collect leaf weight*/
    weights[weight_idx] = child_node->weights[0];
    if (1 == weight_idx % 2)
    {
        weights[weight_idx] *= -1;
    }
    /*Stringify weights*/
    for (i = 0; i < weight_idx; i++)
    {
        retval |= note_wptt_encode_insert_int(weights[weight_idx - i], str_p, buffer_end_p);
        retval |= note_wptt_encode_insert_char(' ', str_p, buffer_end_p);
    }
    retval |= note_wptt_encode_insert_int(weights[0], str_p, buffer_end_p);
    retval |= note_wptt_encode_insert_char(']', str_p, buffer_end_p);
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_encode_insert_label(note_wptt_V4_label_e label,
                                                  char **str_p,
                                                  const char *buffer_end_p)
{
    uint8_t retval = NOTE_DEFS_ENCODE_SUCCESS;

    switch (label)
    {
    case NOTE_WPTT_V4_LABEL_NONE:
    {
        break;
    }

    case NOTE_WPTT_V4_LABEL_I:
    {
        retval |= note_wptt_encode_insert_char('i', str_p, buffer_end_p);
        break;
    }

    case NOTE_WPTT_V4_LABEL_X:
    {
        retval |= note_wptt_encode_insert_char('x', str_p, buffer_end_p);
        break;
    }

    case NOTE_WPTT_V4_LABEL_Y:
    {
        retval |= note_wptt_encode_insert_char('y', str_p, buffer_end_p);
        break;
    }

    case NOTE_WPTT_V4_LABEL_Z:
    {
        retval |= note_wptt_encode_insert_char('z', str_p, buffer_end_p);
        break;
    }

    default:
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_MALFORMED);
    }
    }

    return retval;
}

STATIC_INLINE_UINT8 note_wptt_encode_insert_space(char **str_p,
                                                  const char *buffer_start_p,
                                                  const char *buffer_end_p)
{
    uint8_t retval = NOTE_DEFS_ENCODE_FAIL;

    /*Check if there is room in string buffer*/
    if (((*str_p + 1) < buffer_end_p) && (buffer_start_p < (*str_p)))
    {
        retval = NOTE_DEFS_ENCODE_SUCCESS;
        /*Look backward for an integer*/
        if (((*str_p - 1)[0] >= '0') && ((*str_p - 1)[0] <= '9'))
        {
            (*str_p)[0] = ' ';
            (*str_p)++;
        }
    }
    else
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_STR_BUF);
    }
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_encode_insert_char(char new_char,
                                                 char **str_p,
                                                 const char *buffer_end_p)
{
    uint8_t retval = NOTE_DEFS_ENCODE_FAIL;

    if ((*str_p + 1) < buffer_end_p)
    {
        (*str_p)[0] = new_char;
        (*str_p)++;
        retval = NOTE_DEFS_ENCODE_SUCCESS;
    }
    else
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_STR_BUF);
    }
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_encode_insert_int(int8_t new_int,
                                                char **str_p,
                                                const char *buffer_end_p)
{
    uint8_t retval       = NOTE_DEFS_ENCODE_FAIL;
    size_t  local_offset = 0;
    char    local_str[UTIL_TANG_DEFS_MAX_CROSSINGNUM];

    sprintf(local_str, "%d", new_int);
    local_offset = strlen(local_str);

    if ((*str_p + local_offset) < buffer_end_p)
    {
        strcpy(*str_p, local_str);
        (*str_p) += local_offset;
        retval    = NOTE_DEFS_ENCODE_SUCCESS;
    }
    else
    {
        retval = NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_STR_BUF);
    }
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_encode_complete_active_node(
    const note_wptt_node_t *active_node_p,
    char **str_p,
    size_t ordered_child_idx,
    const char *buffer_start_p,
    const char *buffer_end_p)
{
    uint8_t retval = NOTE_DEFS_ENCODE_SUCCESS;

    /*Insert final weight*/
    if (0 != active_node_p->weights[ordered_child_idx])
    {
        retval |= note_wptt_encode_insert_space(str_p,
                                                buffer_start_p,
                                                buffer_end_p);
        retval |= note_wptt_encode_insert_int(active_node_p->weights[ordered_child_idx],
                                              str_p,
                                              buffer_end_p);
    }

    /*Close node*/
    if (0 < active_node_p->number_of_rings)
    {
        retval |= note_wptt_encode_insert_char('>', str_p, buffer_end_p);
    }
    else
    {
        retval |= note_wptt_encode_insert_char(')', str_p, buffer_end_p);
    }
    return retval;
}

STATIC_INLINE_UINT8 note_wptt_encode_process_active_node(
    note_wptt_node_t *active_node,
    char **str_p,
    size_t ordered_child_idx,
    const char *buffer_start_p,
    const char *buffer_end_p)
{
    uint8_t retval      = NOTE_DEFS_ENCODE_SUCCESS;
    bool    found_stick = note_wptt_encode_stick_check(active_node);

    /*Check if node has more children and start new node*/
    /* cppcheck-suppress negativeIndex */
    if (0 == child_idx_stack[wptt_stack_len - 1])
    {
        if (0 < active_node->number_of_rings)
        {
            retval |= note_wptt_encode_insert_char('<', str_p, buffer_end_p);
            retval |= note_wptt_encode_insert_int(active_node->number_of_rings, str_p,
                                                  buffer_end_p);
        }
        else if (true == found_stick)
        {
            retval |= note_wptt_encode_insert_stick(active_node, str_p, buffer_end_p);
            /*pop stack*/
            if (0 < wptt_stack_len)
            {
                wptt_stack_len--;
            }
            else
            {
                retval |= NOTE_STATUS_BLDR(NOTE_DEFS_ENCODE_FAIL, NOTE_WPTT_ENCODE_OVRUNDR_ERROR);
            }
        }
        else
        {
            retval |= note_wptt_encode_insert_char('(', str_p, buffer_end_p);
        }
    }

    if (false == found_stick)
    {
        /*Stringify weight*/
        if ((0 != active_node->weights[ordered_child_idx]) &&
            (false == found_stick))
        {
            retval |= note_wptt_encode_insert_space(str_p, buffer_start_p, buffer_end_p);
            retval |= note_wptt_encode_insert_int(active_node->weights[ordered_child_idx],
                                                  str_p,
                                                  buffer_end_p);
        }

        /*Push child to stack*/
        child_idx_stack[wptt_stack_len - 1]++;
        if (child_idx_stack[wptt_stack_len - 1] <= active_node->number_of_children)
        {
            wptt_stack_len++;
            wptt_node_stack[wptt_stack_len - 1] = active_node->children[ordered_child_idx];
            child_idx_stack[wptt_stack_len - 1] = 0;
        }
    }
    return retval;
}