int StringToken_Split()

in src/string_token.c [297:393]


int StringToken_Split(const char* source, size_t length, const char** delimiters, size_t n_delims, bool include_empty, char*** tokens, size_t* token_count)
{
    int result;

    // Codes_SRS_STRING_TOKENIZER_09_022: [ If source, delimiters, token or token_count are NULL, or n_delims is zero the function shall return a non-zero value ]
    if (source == NULL || delimiters == NULL || n_delims == 0 || tokens == NULL || token_count == NULL)
    {
        LogError("Invalid argument (source=%p, delimiters=%p, n_delims=%lu, tokens=%p, token_count=%p)", source, delimiters, (unsigned long)n_delims, tokens, token_count);
        result = MU_FAILURE;
    }
    else
    {
        STRING_TOKEN_HANDLE tokenizer;

        // Codes_SRS_STRING_TOKENIZER_09_023: [ source (up to length) shall be split into individual tokens separated by any of delimiters ]
        tokenizer = StringToken_GetFirst(source, length, delimiters, n_delims);

        *token_count = 0;
        *tokens = NULL;
        // Codes_SRS_STRING_TOKENIZER_09_027: [ If no failures occur the function shall return zero ]
        result = 0;

        if (tokenizer != NULL)
        {
            do
            {
                const char* tokenValue;
                size_t tokenLength;

                tokenValue = StringToken_GetValue(tokenizer);
                tokenLength = StringToken_GetLength(tokenizer);

                if ((tokenValue != NULL && tokenLength == 0) || (tokenValue == NULL && tokenLength > 0))
                {
                    LogError("Unexpected token value (%p) or length (%lu)", tokenValue, (unsigned long)tokenLength);
                    result = MU_FAILURE;
                    break;
                }
                // Codes_SRS_STRING_TOKENIZER_09_024: [ All NULL tokens shall be ommited if include_empty is not TRUE ]
                else if (tokenValue != NULL || include_empty)
                {
                    char** temp_token;
                    // Codes_SRS_STRING_TOKENIZER_09_025: [ The tokens shall be stored in tokens, and their count stored in token_count ]
                    *token_count = (*token_count) + 1;

                    size_t realloc_size = safe_multiply_size_t(sizeof(char*), (*token_count));
                    if (realloc_size == SIZE_MAX ||
                        (temp_token = (char**)realloc(*tokens, realloc_size)) == NULL)
                    {
                        // Codes_SRS_STRING_TOKENIZER_09_026: [ If any failures splitting or storing the tokens occur the function shall return a non-zero value ]
                        LogError("Failed re-allocating the token array, size=%zu", realloc_size);
                        (*token_count)--;
                        result = MU_FAILURE;
                        break;
                    }
                    else
                    {
                        *tokens = temp_token;
                        size_t malloc_size;
                        if (tokenLength == 0)
                        {
                            (*tokens)[(*token_count) - 1] = NULL;
                        }
                        else if ((malloc_size = safe_multiply_size_t(safe_add_size_t(tokenLength, 1), sizeof(char))) == SIZE_MAX ||
                            ((*tokens)[(*token_count) - 1] = (char*)malloc(malloc_size)) == NULL)
                        {
                            // Codes_SRS_STRING_TOKENIZER_09_026: [ If any failures splitting or storing the tokens occur the function shall return a non-zero value ]
                            LogError("Failed copying token into array, size=%zu", malloc_size);
                            *token_count = (*token_count) - 1;
                            result = MU_FAILURE;
                            break;
                        }
                        else
                        {
                            (void)memcpy((*tokens)[(*token_count) - 1], tokenValue, tokenLength);
                            (*tokens)[(*token_count) - 1][tokenLength] = '\0';
                        }
                    }
                }
            } while (StringToken_GetNext(tokenizer, delimiters, n_delims));

            StringToken_Destroy(tokenizer);

            if (result != 0)
            {
                while ((*token_count) > 0 && *tokens != NULL)
                {
                    *token_count = (*token_count) - 1;
                    free((*tokens)[*token_count]);
                }
                free(*tokens);
            }
        }
    }

    return result;
}