<commit_before>#include "bignum_conversions.h"

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bignum_types.h"

/**
 * Returns an binary string representation of a uint32_t. The string returned is
 * of length BITS_PER_WORD.
 * @param  number uint32_t to be converted.
 * @return        String with the binary representation of number.
 */
char* uint32_t_to_string(uint32_t number)
{
    char* str = (char*) calloc(BITS_PER_WORD + 1, sizeof(char));
    str[BITS_PER_WORD] = '\0';

    for (uint32_t i = 0; i < BITS_PER_WORD; i++)
    {
        uint32_t masked_number = number & (1 << i);
        str[BITS_PER_WORD - 1 - i] = (masked_number != 0) ? '1' : '0';
    }

    return str;
}

/**
 * Converts a bignum to a binary string. The returned string will have a length
 * of TOTAL_BIT_LENGTH.
 * @param  number Number to be converted.
 * @return        Binary string representation of the bignum.
 */
char* bignum_to_string(bignum number)
{
    // make an array of strings which will each contain 1 of the
    // BIGNUM_NUMBER_OF_WORDS words in the bignum
    char** words = (char**) calloc(BIGNUM_NUMBER_OF_WORDS + 1, sizeof(char*));
    words[BIGNUM_NUMBER_OF_WORDS] = NULL;

    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        words[i] = (char*) calloc(BITS_PER_WORD + 1, sizeof(char));
        words[i][BITS_PER_WORD] = '\0';

        // convert each bignum element to a string
        words[i] = uint32_t_to_string(number[i]);
    }

    // concatenate the words together to form a TOTAL_BIT_LENGTH long string
    char* final_str = (char*) calloc(TOTAL_BIT_LENGTH + 1, sizeof(char));
    final_str[TOTAL_BIT_LENGTH] = '\0';

    char* src;
    char* dest = final_str;
    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        src = words[BIGNUM_NUMBER_OF_WORDS - i - 1];
        strncpy(dest, src, BITS_PER_WORD);

        dest += BITS_PER_WORD;
    }

    free_string_words(&words);

    // return concatenated string
    return final_str;
}

/**
 * Pads the binary string with zeros until it is TOTAL_BIT_LENGTH long.
 * @param old_str string to be padded with zeros
 */
void pad_string_with_zeros(char** old_str)
{
    char* new_str = (char*) calloc(TOTAL_BIT_LENGTH + 1, sizeof(char));
    new_str[TOTAL_BIT_LENGTH] = '\0';
    for (uint32_t i = 0; i < TOTAL_BIT_LENGTH; i++)
    {
        new_str[i] = '0';
    }

    uint32_t old_str_length = strlen(*old_str);

    for (uint32_t i = 0; i < old_str_length; i++)
    {
        new_str[(TOTAL_BIT_LENGTH - old_str_length) + i] = (*old_str)[i];
    }

    free(*old_str);
    *old_str = new_str;
}

/**
 * Separates a TOTAL_BIT_LENGTH long binary string into an array of binary
 * strings of length BITS_PER_WORD. The returned array contains the most
 * significant bits at its last index, and its least significant bits at its
 * first position. Ex: str_words[0] contains bits (BITS_PER_WORD downto 0)
 * @param  str String to be decomposed.
 * @return     Decomposed string.
 */
char** cut_string_to_multiple_words(char* str)
{
    // cut str into BIGNUM_NUMBER_OF_WORDS pieces, each of which is
    // BITS_PER_WORD long

    // array of BITS_PER_WORD length strings
    char** str_words = (char**) calloc(BIGNUM_NUMBER_OF_WORDS + 1,
                                       sizeof(char*));
    str_words[BIGNUM_NUMBER_OF_WORDS] = NULL;

    // allocate each one of the strings and fill them up
    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        str_words[i] = (char*) calloc(BITS_PER_WORD + 1, sizeof(char));
        str_words[i][BITS_PER_WORD] = '\0';

        for (uint32_t j = 0; j < BITS_PER_WORD; j++)
        {
            str_words[i][j] = str[i * BITS_PER_WORD + j];
        }
    }

    // until now, the strings have been cut in big-endian form, but we want
    // little endian for indexing, so we have to invert the array.
    char* tmp;
    uint32_t middle_of_array = ceil(BIGNUM_NUMBER_OF_WORDS / 2.0);
    for (uint32_t i = 0; i < middle_of_array; i++)
    {
        tmp = str_words[i];
        str_words[i] = str_words[BIGNUM_NUMBER_OF_WORDS - 1 - i];
        str_words[BIGNUM_NUMBER_OF_WORDS - 1 - i] = tmp;
    }

    return str_words;
}

/**
 * Frees an array containing BIGNUM_NUMBER_OF_WORDS strings.
 * @param words Pointer to the array of strings to be freed.
 */
void free_string_words(char*** words)
{
    if (*words != NULL)
    {
        for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
        {
            if ((*words)[i] != NULL)
            {
                free((*words)[i]);
                (*words)[i] = NULL;
            }
        }

        // free the char** pointing to the words
        free(*words);
        *words = NULL;
    }
}

/**
 * Returns a uint32_t representation of the binary string of length
 * BITS_PER_WORD passed as a parameter.
 * @param  str String to be converted.
 * @return     Converted value.
 */
uint32_t string_to_uint32_t(char* str)
{
    uint32_t number = 0;

    for (uint32_t i = 0; i < BITS_PER_WORD; i++)
    {
        uint32_t bit_value = str[BITS_PER_WORD - 1 - i] == '1' ? 1 : 0;
        number |= bit_value << i;
    }

    return number;
}

/**
 * Converts the "str" binary string of length TOTAL_BITS_LENGTH into a bignum.
 * @param str    String to be converted.
 * @param number Number which will be assigned the value of the binary string
 *               str.
 */
void string_to_bignum(char* str, bignum number)
{
    char** words = cut_string_to_multiple_words(str);

    // set the number
    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        number[i] = string_to_uint32_t(words[i]);
    }

    free_string_words(&words);
}

/**
 * Transforms an array of bignums to an array of coalesced_bignums. ATTENTION:
 * this function frees the memory pointed to by the bignum, and returns the
 * coalesced_bignum array.
 * @param  in bignum array to convert
 * @return    converted coalesced_bignum array
 */
coalesced_bignum* bignum_to_coalesced_bignum(bignum** in)
{
    coalesced_bignum* out = (coalesced_bignum*) calloc(BIGNUM_NUMBER_OF_WORDS,
                                                       sizeof(coalesced_bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < BIGNUM_NUMBER_OF_WORDS; j++)
        {
            out[i][j] = (*in)[j][i];
        }
    }

    free(*in);
    *in = NULL;

    return out;
}

/**
 * Transforms an array of coalesced_bignums to an array of bignums. ATTENTION:
 * this function frees the memory pointed to by the coalesced_bignum, and
 * returns the bignum array.
 * @param  in coalesced_bignum array to convert
 * @return    converted bignum array
 */
bignum* coalesced_bignum_to_bignum(coalesced_bignum** in)
{
    bignum* out = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < BIGNUM_NUMBER_OF_WORDS; j++)
        {
            out[i][j] = (*in)[j][i];
        }
    }

    free(*in);
    *in = NULL;

    return out;
}

/**
 * Transforms 2 arrays of bignums to an interleaved_bignum array. ATTENTION:
 * this function frees the memory pointed to by the 2 bignum arrays, and returns
 * the interleaved_bignum array.
 * @param  in_1 First array of data elements.
 * @param  in_2 Second array of data elements.
 * @return      converted interleaved_bignum array.
 */
interleaved_bignum* bignums_to_interleaved_bignum(bignum** in_1, bignum** in_2)
{
    interleaved_bignum* out = (interleaved_bignum*) calloc(TOTAL_NUMBER_OF_THREADS,
                                                           sizeof(interleaved_bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < 2 * BIGNUM_NUMBER_OF_WORDS; j++)
        {
            if (j % 2 == 0)
            {
                out[i][j] = (*in_1)[i][j / 2];
            }
            else
            {
                out[i][j] = (*in_2)[i][j / 2];
            }
        }
    }

    free(*in_1);
    free(*in_2);
    *in_1 = NULL;
    *in_2 = NULL;

    return out;
}

/**
 * Transforms an interleaved_bignum array to 2 bignum arrays. ATTENTION: this
 * function frees the memory pointed to by the interleaved_bignum, and allocates
 * memory to hold the 2 resulting bignums.
 * @param out_1 Address of a pointer which will contain the first array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param out_2 Address of a pointer which will contain the second array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param in    interleaved_bignum to convert.
 */
void interleaved_bignum_to_bignums(bignum** out_1, bignum** out_2,
                                   interleaved_bignum** in)
{
    bignum* out_1_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));
    bignum* out_2_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < 2 * BIGNUM_NUMBER_OF_WORDS; j++)
        {
            if (j % 2 == 0)
            {
                out_1_tmp[i][j / 2] = (*in)[i][j];
            }
            else
            {
                out_2_tmp[i][j / 2] = (*in)[i][j];
            }
        }
    }

    free(*in);
    *in = NULL;

    *out_1 = out_1_tmp;
    *out_2 = out_2_tmp;
}

/**
 * Transforms 2 arrays of bignums to a coalesced_interleaved_bignum array.
 * ATTENTION: this function frees the memory pointed to by the 2 bignum arrays,
 * and returns the coalesced_interleaved_bignum array.
 * @param  in_1 First array of data elements.
 * @param  in_2 Second array of data elements.
 * @return      converted coalesced_interleaved_bignum array.
 */
coalesced_interleaved_bignum* bignums_to_coalesced_interleaved_bignum(bignum** in_1,
                                                                      bignum** in_2)
{
    coalesced_interleaved_bignum* out =
        (coalesced_interleaved_bignum*) calloc(BIGNUM_NUMBER_OF_WORDS,
                                               sizeof(coalesced_interleaved_bignum));

    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        for (uint32_t j = 0; j < 2 * TOTAL_NUMBER_OF_THREADS; j += 2)
        {
            out[i][j]     = (*in_1)[j / 2][i];
            out[i][j + 1] = (*in_2)[j / 2][i];
        }
    }

    free(*in_1);
    free(*in_2);
    *in_1 = NULL;
    *in_2 = NULL;

    return out;
}

/**
 * Transforms a coalesced_interleaved_bignum array to 2 bignum arrays.
 * ATTENTION: this function frees the memory pointed to by the
 * coalesced_interleaved_bignum, and allocates memory to hold the 2 resulting
 * bignums.
 * @param out_1 Address of a pointer which will contain the first array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param out_2 Address of a pointer which will contain the second array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param in    coalesced_interleaved_bignum to convert.
 */
void coalesced_interleaved_bignum_to_bignums(bignum** out_1, bignum** out_2,
                                             coalesced_interleaved_bignum** in)
{
    bignum* out_1_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));
    bignum* out_2_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));

    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        for (uint32_t j = 0; j < 2 * TOTAL_NUMBER_OF_THREADS; j += 2)
        {
            (*out_1)[j / 2][i] = in[i][j];
            (*out_2)[j / 2][i] = in[i][j + 1];
        }
    }

    free(*in);
    *in = NULL;

    *out_1 = out_1_tmp;
    *out_2 = out_2_tmp;
}
<commit_msg>minor index fix<commit_after>#include "bignum_conversions.h"

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bignum_types.h"

/**
 * Returns an binary string representation of a uint32_t. The string returned is
 * of length BITS_PER_WORD.
 * @param  number uint32_t to be converted.
 * @return        String with the binary representation of number.
 */
char* uint32_t_to_string(uint32_t number)
{
    char* str = (char*) calloc(BITS_PER_WORD + 1, sizeof(char));
    str[BITS_PER_WORD] = '\0';

    for (uint32_t i = 0; i < BITS_PER_WORD; i++)
    {
        uint32_t masked_number = number & (1 << i);
        str[BITS_PER_WORD - 1 - i] = (masked_number != 0) ? '1' : '0';
    }

    return str;
}

/**
 * Converts a bignum to a binary string. The returned string will have a length
 * of TOTAL_BIT_LENGTH.
 * @param  number Number to be converted.
 * @return        Binary string representation of the bignum.
 */
char* bignum_to_string(bignum number)
{
    // make an array of strings which will each contain 1 of the
    // BIGNUM_NUMBER_OF_WORDS words in the bignum
    char** words = (char**) calloc(BIGNUM_NUMBER_OF_WORDS + 1, sizeof(char*));
    words[BIGNUM_NUMBER_OF_WORDS] = NULL;

    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        words[i] = (char*) calloc(BITS_PER_WORD + 1, sizeof(char));
        words[i][BITS_PER_WORD] = '\0';

        // convert each bignum element to a string
        words[i] = uint32_t_to_string(number[i]);
    }

    // concatenate the words together to form a TOTAL_BIT_LENGTH long string
    char* final_str = (char*) calloc(TOTAL_BIT_LENGTH + 1, sizeof(char));
    final_str[TOTAL_BIT_LENGTH] = '\0';

    char* src;
    char* dest = final_str;
    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        src = words[BIGNUM_NUMBER_OF_WORDS - i - 1];
        strncpy(dest, src, BITS_PER_WORD);

        dest += BITS_PER_WORD;
    }

    free_string_words(&words);

    // return concatenated string
    return final_str;
}

/**
 * Pads the binary string with zeros until it is TOTAL_BIT_LENGTH long.
 * @param old_str string to be padded with zeros
 */
void pad_string_with_zeros(char** old_str)
{
    char* new_str = (char*) calloc(TOTAL_BIT_LENGTH + 1, sizeof(char));
    new_str[TOTAL_BIT_LENGTH] = '\0';
    for (uint32_t i = 0; i < TOTAL_BIT_LENGTH; i++)
    {
        new_str[i] = '0';
    }

    uint32_t old_str_length = strlen(*old_str);

    for (uint32_t i = 0; i < old_str_length; i++)
    {
        new_str[(TOTAL_BIT_LENGTH - old_str_length) + i] = (*old_str)[i];
    }

    free(*old_str);
    *old_str = new_str;
}

/**
 * Separates a TOTAL_BIT_LENGTH long binary string into an array of binary
 * strings of length BITS_PER_WORD. The returned array contains the most
 * significant bits at its last index, and its least significant bits at its
 * first position. Ex: str_words[0] contains bits (BITS_PER_WORD downto 0)
 * @param  str String to be decomposed.
 * @return     Decomposed string.
 */
char** cut_string_to_multiple_words(char* str)
{
    // cut str into BIGNUM_NUMBER_OF_WORDS pieces, each of which is
    // BITS_PER_WORD long

    // array of BITS_PER_WORD length strings
    char** str_words = (char**) calloc(BIGNUM_NUMBER_OF_WORDS + 1,
                                       sizeof(char*));
    str_words[BIGNUM_NUMBER_OF_WORDS] = NULL;

    // allocate each one of the strings and fill them up
    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        str_words[i] = (char*) calloc(BITS_PER_WORD + 1, sizeof(char));
        str_words[i][BITS_PER_WORD] = '\0';

        for (uint32_t j = 0; j < BITS_PER_WORD; j++)
        {
            str_words[i][j] = str[i * BITS_PER_WORD + j];
        }
    }

    // until now, the strings have been cut in big-endian form, but we want
    // little endian for indexing, so we have to invert the array.
    char* tmp;
    uint32_t middle_of_array = ceil(BIGNUM_NUMBER_OF_WORDS / 2.0);
    for (uint32_t i = 0; i < middle_of_array; i++)
    {
        tmp = str_words[i];
        str_words[i] = str_words[BIGNUM_NUMBER_OF_WORDS - 1 - i];
        str_words[BIGNUM_NUMBER_OF_WORDS - 1 - i] = tmp;
    }

    return str_words;
}

/**
 * Frees an array containing BIGNUM_NUMBER_OF_WORDS strings.
 * @param words Pointer to the array of strings to be freed.
 */
void free_string_words(char*** words)
{
    if (*words != NULL)
    {
        for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
        {
            if ((*words)[i] != NULL)
            {
                free((*words)[i]);
                (*words)[i] = NULL;
            }
        }

        // free the char** pointing to the words
        free(*words);
        *words = NULL;
    }
}

/**
 * Returns a uint32_t representation of the binary string of length
 * BITS_PER_WORD passed as a parameter.
 * @param  str String to be converted.
 * @return     Converted value.
 */
uint32_t string_to_uint32_t(char* str)
{
    uint32_t number = 0;

    for (uint32_t i = 0; i < BITS_PER_WORD; i++)
    {
        uint32_t bit_value = str[BITS_PER_WORD - 1 - i] == '1' ? 1 : 0;
        number |= bit_value << i;
    }

    return number;
}

/**
 * Converts the "str" binary string of length TOTAL_BITS_LENGTH into a bignum.
 * @param str    String to be converted.
 * @param number Number which will be assigned the value of the binary string
 *               str.
 */
void string_to_bignum(char* str, bignum number)
{
    char** words = cut_string_to_multiple_words(str);

    // set the number
    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        number[i] = string_to_uint32_t(words[i]);
    }

    free_string_words(&words);
}

/**
 * Transforms an array of bignums to an array of coalesced_bignums. ATTENTION:
 * this function frees the memory pointed to by the bignum, and returns the
 * coalesced_bignum array.
 * @param  in bignum array to convert
 * @return    converted coalesced_bignum array
 */
coalesced_bignum* bignum_to_coalesced_bignum(bignum** in)
{
    coalesced_bignum* out = (coalesced_bignum*) calloc(BIGNUM_NUMBER_OF_WORDS,
                                                       sizeof(coalesced_bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < BIGNUM_NUMBER_OF_WORDS; j++)
        {
            out[j][i] = (*in)[i][j];
        }
    }

    free(*in);
    *in = NULL;

    return out;
}

/**
 * Transforms an array of coalesced_bignums to an array of bignums. ATTENTION:
 * this function frees the memory pointed to by the coalesced_bignum, and
 * returns the bignum array.
 * @param  in coalesced_bignum array to convert
 * @return    converted bignum array
 */
bignum* coalesced_bignum_to_bignum(coalesced_bignum** in)
{
    bignum* out = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < BIGNUM_NUMBER_OF_WORDS; j++)
        {
            out[i][j] = (*in)[j][i];
        }
    }

    free(*in);
    *in = NULL;

    return out;
}

/**
 * Transforms 2 arrays of bignums to an interleaved_bignum array. ATTENTION:
 * this function frees the memory pointed to by the 2 bignum arrays, and returns
 * the interleaved_bignum array.
 * @param  in_1 First array of data elements.
 * @param  in_2 Second array of data elements.
 * @return      converted interleaved_bignum array.
 */
interleaved_bignum* bignums_to_interleaved_bignum(bignum** in_1, bignum** in_2)
{
    interleaved_bignum* out = (interleaved_bignum*) calloc(TOTAL_NUMBER_OF_THREADS,
                                                           sizeof(interleaved_bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < 2 * BIGNUM_NUMBER_OF_WORDS; j++)
        {
            if (j % 2 == 0)
            {
                out[i][j] = (*in_1)[i][j / 2];
            }
            else
            {
                out[i][j] = (*in_2)[i][j / 2];
            }
        }
    }

    free(*in_1);
    free(*in_2);
    *in_1 = NULL;
    *in_2 = NULL;

    return out;
}

/**
 * Transforms an interleaved_bignum array to 2 bignum arrays. ATTENTION: this
 * function frees the memory pointed to by the interleaved_bignum, and allocates
 * memory to hold the 2 resulting bignums.
 * @param out_1 Address of a pointer which will contain the first array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param out_2 Address of a pointer which will contain the second array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param in    interleaved_bignum to convert.
 */
void interleaved_bignum_to_bignums(bignum** out_1, bignum** out_2,
                                   interleaved_bignum** in)
{
    bignum* out_1_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));
    bignum* out_2_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));

    for (uint32_t i = 0; i < TOTAL_NUMBER_OF_THREADS; i++)
    {
        for (uint32_t j = 0; j < 2 * BIGNUM_NUMBER_OF_WORDS; j++)
        {
            if (j % 2 == 0)
            {
                out_1_tmp[i][j / 2] = (*in)[i][j];
            }
            else
            {
                out_2_tmp[i][j / 2] = (*in)[i][j];
            }
        }
    }

    free(*in);
    *in = NULL;

    *out_1 = out_1_tmp;
    *out_2 = out_2_tmp;
}

/**
 * Transforms 2 arrays of bignums to a coalesced_interleaved_bignum array.
 * ATTENTION: this function frees the memory pointed to by the 2 bignum arrays,
 * and returns the coalesced_interleaved_bignum array.
 * @param  in_1 First array of data elements.
 * @param  in_2 Second array of data elements.
 * @return      converted coalesced_interleaved_bignum array.
 */
coalesced_interleaved_bignum* bignums_to_coalesced_interleaved_bignum(bignum** in_1,
                                                                      bignum** in_2)
{
    coalesced_interleaved_bignum* out =
        (coalesced_interleaved_bignum*) calloc(BIGNUM_NUMBER_OF_WORDS,
                                               sizeof(coalesced_interleaved_bignum));

    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        for (uint32_t j = 0; j < 2 * TOTAL_NUMBER_OF_THREADS; j += 2)
        {
            out[i][j]     = (*in_1)[j / 2][i];
            out[i][j + 1] = (*in_2)[j / 2][i];
        }
    }

    free(*in_1);
    free(*in_2);
    *in_1 = NULL;
    *in_2 = NULL;

    return out;
}

/**
 * Transforms a coalesced_interleaved_bignum array to 2 bignum arrays.
 * ATTENTION: this function frees the memory pointed to by the
 * coalesced_interleaved_bignum, and allocates memory to hold the 2 resulting
 * bignums.
 * @param out_1 Address of a pointer which will contain the first array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param out_2 Address of a pointer which will contain the second array of data
 *              elements. Memory is allocated by this function to hold the data.
 * @param in    coalesced_interleaved_bignum to convert.
 */
void coalesced_interleaved_bignum_to_bignums(bignum** out_1, bignum** out_2,
                                             coalesced_interleaved_bignum** in)
{
    bignum* out_1_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));
    bignum* out_2_tmp = (bignum*) calloc(TOTAL_NUMBER_OF_THREADS, sizeof(bignum));

    for (uint32_t i = 0; i < BIGNUM_NUMBER_OF_WORDS; i++)
    {
        for (uint32_t j = 0; j < 2 * TOTAL_NUMBER_OF_THREADS; j += 2)
        {
            (*out_1)[j / 2][i] = in[i][j];
            (*out_2)[j / 2][i] = in[i][j + 1];
        }
    }

    free(*in);
    *in = NULL;

    *out_1 = out_1_tmp;
    *out_2 = out_2_tmp;
}
<|endoftext|>


<commit_before>#include "xml.h"

namespace ospray {
  namespace xml {

    std::string toString(const float f)
    { std::stringstream ss; ss << f; return ss.str(); }

    std::string toString(const vec3f &v)
    { std::stringstream ss; ss << v.x << " " << v.y << " " << v.z; return ss.str(); }

    Node::~Node()
    {
      for (int i=0;i<prop.size();i++) delete prop[i];
      for (int i=0;i<child.size();i++) delete child[i];
    }

    inline bool isWhite(char s) {
      return
        s == ' ' ||
        s == '\t' ||
        s == '\n' ||
        s == '\r';
    }

    inline void expect(char *&s, const char w)
    {
      if (*s != w) {
        std::stringstream err;
        err << "error reading XML file: expecting '" << w << "', but found '" << *s << "'";
        throw std::runtime_error(err.str());
      }
    }
    inline void consume(char *&s, const char w)
    {
      expect(s,w);
      ++s;
    }
    inline void consume(char *&s, const char *word)
    {
      const char *in = word;
      while (*word) {
        try {
          consume(s,*word); ++word;
        } catch (...) {
          std::stringstream err;
          err << "error reading XML file: expecting '" << in << "', but could not find it";
          throw std::runtime_error(err.str());
        }
      }
    }

    inline std::string makeString(const char *begin, const char *end)
    {
      char mem[end-begin+1];
      mem[end-begin] = 0;
      memcpy(mem,begin,end-begin);
      return mem;
    }

    void parseString(char *&s, std::string &value)
    {
      consume(s,'"');
      char *begin = s;
      while (*s != '"') {
        if (*s == '\\') ++s;
        ++s;
      }
      char *end = s;
      value = makeString(begin,end);
      consume(s,'"');
    }

    bool parseIdentifier(char *&s, std::string &identifier)
    {
      if (isalpha(*s) || *s == '_') {
        char *begin = s;
        ++s;
        while (isalpha(*s) || isdigit(*s) || *s == '_') {
          ++s;
        }
        char *end = s;
        identifier = makeString(begin,end);
        return true;
      }
      return false;
    }

    inline void skipWhites(char *&s)
    {
      while (isWhite(*s)) ++s;
    }

    bool parseProp(char *&s, Prop &prop)
    {
      if (!parseIdentifier(s,prop.name))
        return false;
      skipWhites(s);
      consume(s,'=');
      skipWhites(s);
      expect(s,'"');
      parseString(s,prop.value);
      return true;
    }

    Node *parseNode(char *&s)
    {
      consume(s,'<');
      Node *node = new Node;
      try {
        if (!parseIdentifier(s,node->name))
          throw std::runtime_error("XML error: could not parse node name");

        skipWhites(s);

        Prop prop;
        while (parseProp(s,prop)) {
          node->prop.push_back(new Prop(prop));
          skipWhites(s);
        }

        if (*s == '/') {
          consume(s,"/>");
          return node;
        }

        consume(s,">");

        while (1) {
          skipWhites(s);
          if (*s == '<' && s[1] == '/') {
            consume(s,"</");
            std::string name = "";
            parseIdentifier(s,name);
            if (name != node->name)
              throw std::runtime_error("invalid XML node - started with '<"+node->name+"...'>, but ended with '</"+name+">");
            consume(s,">");
            break;
            // either end of current node
          } else if (*s == '<') {
            // child node
            Node *child = parseNode(s);
            node->child.push_back(child);
          } else {
            if (node->content != "")
              throw std::runtime_error("invalid XML node - two different contents!?");
            // content
            char *begin = s;
            while (*s != '<' && *s != 0) ++s;
            char *end = s;
            while (isspace(end[-1])) --end;
            node->content = makeString(begin,end);
          }
        }
        return node;
      } catch (std::runtime_error e) {
        delete node;
        throw e;
      }
    }

    bool parseHeader(char *&s)
    {
      consume(s,"<?xml");
      if (*s == '?' && s[1] == '>') {
        consume(s,"?>");
        return true;
      }

      if (!isWhite(*s)) return false; ++s;

      skipWhites(s);

      Prop headerProp;
      while (parseProp(s,headerProp)) {
        // ignore header prop
        skipWhites(s);
      }

      consume(s,"?>");

      return true;
    }

    bool parseXML(XMLDoc *xml, char *s)
    {
      if (!parseHeader(s))
        throw std::runtime_error("could not parse XML header");

      skipWhites(s);
      while (*s != 0) {
        Node *node = parseNode(s);
        if (node)xml->child.push_back(node);
        skipWhites(s);
      }

      if (*s != 0) throw std::runtime_error("un-parsed junk at end of file"); ++s;
      return xml;
    }

    void Writer::spaces()
    {
      for (int i=0;i<state.size();i++)
        fprintf(xml,"  ");
    }

    void Writer::writeProperty(const std::string &name, const std::string &value)
    {
      assert(xml);
      assert(!state.empty());
      State *s = state.top();
      assert(s);
      assert(!s->hasContent); // content may not be written before properties
      fprintf(xml," %s=\"%s\"",name.c_str(),value.c_str());
    }

    void Writer::openNode(const std::string &type)
    {
      assert(xml);
      spaces(); fprintf(xml,"<%s",type.c_str());
      State *s = new State;
      s->type = type;
      state.push(s);
    }

    void Writer::closeNode()
    {
      assert(xml);
      assert(!state.empty());
      State *s = state.top();
      assert(s);
      if (s->hasContent)
        fprintf(xml,"</%s>",s->type.c_str());
      else
        fprintf(xml,"/>\n");
      delete s;
      state.pop();
    }

    XMLDoc *readXML(const std::string &fn)
    {
      FILE *file = fopen(fn.c_str(),"r");
      if (!file) {
        throw std::runtime_error("ospray::XML error: could not open file '"+fn+"'");
      }

      fseek(file,0,SEEK_END);
      long numBytes = ftell(file);
      fseek(file,0,SEEK_SET);
      char *mem = new char[numBytes+1];
      mem[numBytes] = 0;
      fread(mem,1,numBytes,file);
      XMLDoc *xml = new XMLDoc;
      bool valid = false;
      try {
        valid = parseXML(xml,mem);
      } catch (std::runtime_error e) {
        delete[] mem;
        fclose(file);
      }
      delete[] mem;
      fclose(file);

      if (!valid) {
        delete xml;
        return NULL;
      }
      return xml;
    }

    Writer::Writer(FILE *xml, FILE *bin)
      : xml(xml), bin(bin)
    {}

      /*! write document header, may only be called once */
    void Writer::writeHeader(const std::string &version)
    {
      assert(xml);
      fprintf(xml,"<?xml version=\"%s\"?>\n",version.c_str());
    }

    /*! write document footer. may only be called once, at end of write */
    void Writer::writeFooter()
    {
      assert(xml);
    }

  }
}
<commit_msg>'fix' for xml parser. can now handle partially written xml files that do not properly close all nodes (as seems to happen in vtk files)<commit_after>#include "xml.h"

namespace ospray {
  namespace xml {

    std::string toString(const float f)
    { std::stringstream ss; ss << f; return ss.str(); }

    std::string toString(const vec3f &v)
    { std::stringstream ss; ss << v.x << " " << v.y << " " << v.z; return ss.str(); }

    Node::~Node()
    {
      for (int i=0;i<prop.size();i++) delete prop[i];
      for (int i=0;i<child.size();i++) delete child[i];
    }

    inline bool isWhite(char s) {
      return
        s == ' ' ||
        s == '\t' ||
        s == '\n' ||
        s == '\r';
    }

    inline void expect(char *&s, const char w)
    {
      if (*s != w) {
        std::stringstream err;
        err << "error reading XML file: expecting '" << w << "', but found '" << *s << "'";
        throw std::runtime_error(err.str());
      }
    }
    inline void expect(char *&s, const char w0, const char w1)
    {
      if (*s != w0 && *s != w1) {
        std::stringstream err;
        err << "error reading XML file: expecting '" << w0 << "' or '" << w1 << "', but found '" << *s << "'";
        throw std::runtime_error(err.str());
      }
    }
    inline void consume(char *&s, const char w)
    {
      expect(s,w);
      ++s;
    }
    inline void consume(char *&s, const char *word)
    {
      const char *in = word;
      while (*word) {
        try {
          consume(s,*word); ++word;
        } catch (...) {
          std::stringstream err;
          err << "error reading XML file: expecting '" << in << "', but could not find it";
          throw std::runtime_error(err.str());
        }
      }
    }

    inline std::string makeString(const char *begin, const char *end)
    {
      if (!begin || !end)
        throw std::runtime_error("invalid substring in osp::xml::makeString");
      if (begin == end) return "";
      char mem[end-begin+1];
      mem[end-begin] = 0;
      memcpy(mem,begin,end-begin);
      return mem;
    }

    void parseString(char *&s, std::string &value)
    {
      if (*s == '"') {
        consume(s,'"');
        char *begin = s;
        while (*s != '"') {
          if (*s == '\\') ++s;
          ++s;
        }
        char *end = s;
        value = makeString(begin,end);
        consume(s,'"');
      } else {
        consume(s,'\'');
        char *begin = s;
        while (*s != '\'') {
          if (*s == '\\') ++s;
          ++s;
        }
        char *end = s;
        value = makeString(begin,end);
        consume(s,'\'');
      }
    }

    bool parseIdentifier(char *&s, std::string &identifier)
    {
      if (isalpha(*s) || *s == '_') {
        char *begin = s;
        ++s;
        while (isalpha(*s) || isdigit(*s) || *s == '_') {
          ++s;
        }
        char *end = s;
        identifier = makeString(begin,end);
        return true;
      }
      return false;
    }

    inline void skipWhites(char *&s)
    {
      while (isWhite(*s)) ++s;
    }

    bool parseProp(char *&s, Prop &prop)
    {
      if (!parseIdentifier(s,prop.name))
        return false;
      skipWhites(s);
      consume(s,'=');
      skipWhites(s);
      expect(s,'"','\'');
      parseString(s,prop.value);
      return true;
    }

    Node *parseNode(char *&s)
    {
      consume(s,'<');
      Node *node = new Node;
      try {
        if (!parseIdentifier(s,node->name))
          throw std::runtime_error("XML error: could not parse node name");

        skipWhites(s);

        Prop prop;
        while (parseProp(s,prop)) {
          node->prop.push_back(new Prop(prop));
          skipWhites(s);
        }

        if (*s == '/') {
          consume(s,"/>");
          return node;
        }

        consume(s,">");

        while (1) {
          skipWhites(s);
          if (*s == '<' && s[1] == '/') {
            consume(s,"</");
            std::string name = "";
            parseIdentifier(s,name);
            if (name != node->name)
              throw std::runtime_error("invalid XML node - started with '<"+node->name+"...'>, but ended with '</"+name+">");
            consume(s,">");
            break;
            // either end of current node
          } else if (*s == '<') {
            // child node
            Node *child = parseNode(s);
            node->child.push_back(child);
          } else if (*s == 0) {
            std::cout << "#osp:xml: warning: xml file ended with still-open nodes (this typically indicates a partial xml file)" << std::endl;
            return node;
          } else {
            if (node->content != "")
              throw std::runtime_error("invalid XML node - two different contents!?");
            // content
            char *begin = s;
            while (*s != '<' && *s != 0) ++s;
            char *end = s;
            while (isspace(end[-1])) --end;
            node->content = makeString(begin,end);
          }
        }
        return node;
      } catch (std::runtime_error e) {
        delete node;
        throw e;
      }
    }

    bool parseHeader(char *&s)
    {
      consume(s,"<?xml");
      if (*s == '?' && s[1] == '>') {
        consume(s,"?>");
        return true;
      }

      if (!isWhite(*s)) return false; ++s;

      skipWhites(s);

      Prop headerProp;
      while (parseProp(s,headerProp)) {
        // ignore header prop
        skipWhites(s);
      }

      consume(s,"?>");

      return true;
    }

    bool parseXML(XMLDoc *xml, char *s)
    {
      if (!parseHeader(s))
        throw std::runtime_error("could not parse XML header");

      skipWhites(s);
      while (*s != 0) {
        Node *node = parseNode(s);
        if (node)xml->child.push_back(node);
        skipWhites(s);
      }

      if (*s != 0) throw std::runtime_error("un-parsed junk at end of file"); ++s;
      return xml;
    }

    void Writer::spaces()
    {
      for (int i=0;i<state.size();i++)
        fprintf(xml,"  ");
    }

    void Writer::writeProperty(const std::string &name, const std::string &value)
    {
      assert(xml);
      assert(!state.empty());
      State *s = state.top();
      assert(s);
      assert(!s->hasContent); // content may not be written before properties
      fprintf(xml," %s=\"%s\"",name.c_str(),value.c_str());
    }

    void Writer::openNode(const std::string &type)
    {
      assert(xml);
      spaces(); fprintf(xml,"<%s",type.c_str());
      State *s = new State;
      s->type = type;
      state.push(s);
    }

    void Writer::closeNode()
    {
      assert(xml);
      assert(!state.empty());
      State *s = state.top();
      assert(s);
      if (s->hasContent)
        fprintf(xml,"</%s>",s->type.c_str());
      else
        fprintf(xml,"/>\n");
      delete s;
      state.pop();
    }

    XMLDoc *readXML(const std::string &fn)
    {
      FILE *file = fopen(fn.c_str(),"r");
      if (!file) {
        throw std::runtime_error("ospray::XML error: could not open file '"+fn+"'");
      }

      fseek(file,0,SEEK_END);
      long numBytes = ftell(file);
      fseek(file,0,SEEK_SET);
      char *mem = new char[numBytes+1];
      mem[numBytes] = 0;
      fread(mem,1,numBytes,file);
      XMLDoc *xml = new XMLDoc;
      bool valid = false;
      try {
        valid = parseXML(xml,mem);
      } catch (std::runtime_error e) {
        delete[] mem;
        fclose(file);
        throw e;
      }
      delete[] mem;
      fclose(file);

      if (!valid) {
        delete xml;
        return NULL;
      }
      return xml;
    }

    Writer::Writer(FILE *xml, FILE *bin)
      : xml(xml), bin(bin)
    {}

      /*! write document header, may only be called once */
    void Writer::writeHeader(const std::string &version)
    {
      assert(xml);
      fprintf(xml,"<?xml version=\"%s\"?>\n",version.c_str());
    }

    /*! write document footer. may only be called once, at end of write */
    void Writer::writeFooter()
    {
      assert(xml);
    }

  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: SlsBitmapCompressor.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 19:03:35 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "SlsBitmapCompressor.hxx"

#include <tools/stream.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/pngread.hxx>
#include <vcl/pngwrite.hxx>

namespace sd { namespace slidesorter { namespace cache {

//===== NoBitmapCompression ===================================================

/** This dummy replacement simply stores a shared pointer to the original
    preview bitmap.
*/
class NoBitmapCompression::DummyReplacement
    : public BitmapReplacement
{
public:
    ::boost::shared_ptr<BitmapEx> mpPreview;
    Size maOriginalSize;

    DummyReplacement (const ::boost::shared_ptr<BitmapEx>& rpPreview) : mpPreview(rpPreview)
    {
    }
    virtual sal_Int32 GetMemorySize (void) const
    {
        return mpPreview->GetSizeBytes();
    }
};

::boost::shared_ptr<BitmapReplacement> NoBitmapCompression::Compress (
    const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
{
    return ::boost::shared_ptr<BitmapReplacement>(new DummyReplacement(rpBitmap));
}

::boost::shared_ptr<BitmapEx> NoBitmapCompression::Decompress (
    const BitmapReplacement& rBitmapData) const
{
    return dynamic_cast<const DummyReplacement&>(rBitmapData).mpPreview;
}

bool NoBitmapCompression::IsLossless (void) const
{
    return true;
}

//===== CompressionByDeletion =================================================

::boost::shared_ptr<BitmapReplacement> CompressionByDeletion::Compress (
    const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
{
    return ::boost::shared_ptr<BitmapReplacement>();
}

::boost::shared_ptr<BitmapEx> CompressionByDeletion::Decompress (
    const BitmapReplacement& rBitmapData) const
{
    // Return a NULL pointer.  This will eventually lead to a request for
    // the creation of a new one.
    return ::boost::shared_ptr<BitmapEx>();
}

bool CompressionByDeletion::IsLossless (void) const
{
    return false;
}

//===== ResolutionReduction ===================================================

/** Store a scaled down bitmap together with the original size.
*/
class ResolutionReduction::ResolutionReducedReplacement : public BitmapReplacement
{
public:
    ::boost::shared_ptr<BitmapEx> mpPreview;
    Size maOriginalSize;

    virtual sal_Int32 GetMemorySize (void) const
    {
        if (mpPreview.get() != NULL)
            return mpPreview->GetSizeBytes();
        else
            return 0;
    }
};

::boost::shared_ptr<BitmapReplacement> ResolutionReduction::Compress (
    const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
{
    ResolutionReducedReplacement* pResult = new ResolutionReducedReplacement();
    pResult->mpPreview.reset(new BitmapEx(*rpBitmap));
    Size aSize (rpBitmap->GetSizePixel());
    pResult->maOriginalSize = aSize;
    if (aSize.Width()>0 && aSize.Width()<mnWidth)
    {
        int nHeight = aSize.Height() * mnWidth / aSize.Width() ;
        pResult->mpPreview->Scale(Size(mnWidth,nHeight));
    }

    return ::boost::shared_ptr<BitmapReplacement>(pResult);
}

::boost::shared_ptr<BitmapEx> ResolutionReduction::Decompress (
    const BitmapReplacement& rBitmapData) const
{
    ::boost::shared_ptr<BitmapEx> pResult;

    const ResolutionReducedReplacement* pData (
        dynamic_cast<const ResolutionReducedReplacement*>(&rBitmapData));

    if (pData->mpPreview.get() != NULL)
    {
        pResult.reset(new BitmapEx(*pData->mpPreview));
        if (pData->maOriginalSize.Width() > mnWidth)
            pResult->Scale(pData->maOriginalSize);
    }

    return pResult;
}

bool ResolutionReduction::IsLossless (void) const
{
    return false;
}

//===== PNGCompression ========================================================

class PngCompression::PngReplacement : public BitmapReplacement
{
public:
    void* mpData;
    sal_Int32 mnDataSize;
    Size maImageSize;
    PngReplacement (void)
        : mpData(NULL),
          mnDataSize(0),
          maImageSize(0,0)
    {}
    virtual ~PngReplacement (void)
    {
        delete [] mpData;
    }
    virtual sal_Int32 GetMemorySize (void) const
    {
        return mnDataSize;
    }
};

::boost::shared_ptr<BitmapReplacement> PngCompression::Compress (
    const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
{
    ::vcl::PNGWriter aWriter (*rpBitmap);
    SvMemoryStream aStream (32768, 32768);
    aWriter.Write(aStream);

    PngReplacement* pResult = new PngReplacement();
    pResult->maImageSize = rpBitmap->GetSizePixel();
    pResult->mnDataSize = aStream.Tell();
    pResult->mpData = new char[pResult->mnDataSize];
    memcpy(pResult->mpData, aStream.GetData(), pResult->mnDataSize);

    return ::boost::shared_ptr<BitmapReplacement>(pResult);
}

::boost::shared_ptr<BitmapEx> PngCompression::Decompress (
    const BitmapReplacement& rBitmapData) const
{
    BitmapEx* pResult = NULL;
    const PngReplacement* pData (dynamic_cast<const PngReplacement*>(&rBitmapData));
    if (pData != NULL)
    {
        SvMemoryStream aStream (pData->mpData, pData->mnDataSize, STREAM_READ);
        ::vcl::PNGReader aReader (aStream);
        pResult = new BitmapEx(aReader.Read());
    }

    sal_Int32 nRatio ((100L * (ULONG)pResult->GetSizeBytes()) / (ULONG)pData->mnDataSize);

    return ::boost::shared_ptr<BitmapEx>(pResult);
}

bool PngCompression::IsLossless (void) const
{
    return true;
}

} } } // end of namespace ::sd::slidesorter::cache
<commit_msg>INTEGRATION: CWS sdwarningsbegone (1.4.38); FILE MERGED 2006/11/27 16:30:59 cl 1.4.38.3: #i69285# warning free code changes for sd project 2006/11/27 15:15:02 cl 1.4.38.2: #i69285# warning free code changes for sd project 2006/11/22 12:42:10 cl 1.4.38.1: #i69285# warning free code changes for unxlngi6.pro<commit_after>/*************************************************************************
 *
 *  $RCSfile: SlsBitmapCompressor.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-12 18:12:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "SlsBitmapCompressor.hxx"

#include <tools/stream.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/pngread.hxx>
#include <vcl/pngwrite.hxx>

namespace sd { namespace slidesorter { namespace cache {

//===== NoBitmapCompression ===================================================

/** This dummy replacement simply stores a shared pointer to the original
    preview bitmap.
*/
class NoBitmapCompression::DummyReplacement
    : public BitmapReplacement
{
public:
    ::boost::shared_ptr<BitmapEx> mpPreview;
    Size maOriginalSize;

    DummyReplacement (const ::boost::shared_ptr<BitmapEx>& rpPreview) : mpPreview(rpPreview)
    {
    }

    virtual ~DummyReplacement();

    virtual sal_Int32 GetMemorySize (void) const;
};

NoBitmapCompression::DummyReplacement::~DummyReplacement()
{
}

sal_Int32 NoBitmapCompression::DummyReplacement::GetMemorySize (void) const
{
    return mpPreview->GetSizeBytes();
}

::boost::shared_ptr<BitmapReplacement> NoBitmapCompression::Compress (
    const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
{
    return ::boost::shared_ptr<BitmapReplacement>(new DummyReplacement(rpBitmap));
}

::boost::shared_ptr<BitmapEx> NoBitmapCompression::Decompress (
    const BitmapReplacement& rBitmapData) const
{
    return dynamic_cast<const DummyReplacement&>(rBitmapData).mpPreview;
}

bool NoBitmapCompression::IsLossless (void) const
{
    return true;
}

//===== CompressionByDeletion =================================================

::boost::shared_ptr<BitmapReplacement> CompressionByDeletion::Compress (
    const ::boost::shared_ptr<BitmapEx>& ) const
{
    return ::boost::shared_ptr<BitmapReplacement>();
}

::boost::shared_ptr<BitmapEx> CompressionByDeletion::Decompress (
    const BitmapReplacement& ) const
{
    // Return a NULL pointer.  This will eventually lead to a request for
    // the creation of a new one.
    return ::boost::shared_ptr<BitmapEx>();
}

bool CompressionByDeletion::IsLossless (void) const
{
    return false;
}

//===== ResolutionReduction ===================================================

/** Store a scaled down bitmap together with the original size.
*/
class ResolutionReduction::ResolutionReducedReplacement : public BitmapReplacement
{
public:
    ::boost::shared_ptr<BitmapEx> mpPreview;
    Size maOriginalSize;

    virtual ~ResolutionReducedReplacement();

    virtual sal_Int32 GetMemorySize (void) const;
};

ResolutionReduction::ResolutionReducedReplacement::~ResolutionReducedReplacement()
{
}

sal_Int32 ResolutionReduction::ResolutionReducedReplacement::GetMemorySize (void) const
{
    if (mpPreview.get() != NULL)
        return mpPreview->GetSizeBytes();
    else
        return 0;
}

::boost::shared_ptr<BitmapReplacement> ResolutionReduction::Compress (
    const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
{
    ResolutionReducedReplacement* pResult = new ResolutionReducedReplacement();
    pResult->mpPreview.reset(new BitmapEx(*rpBitmap));
    Size aSize (rpBitmap->GetSizePixel());
    pResult->maOriginalSize = aSize;
    if (aSize.Width()>0 && aSize.Width()<mnWidth)
    {
        int nHeight = aSize.Height() * mnWidth / aSize.Width() ;
        pResult->mpPreview->Scale(Size(mnWidth,nHeight));
    }

    return ::boost::shared_ptr<BitmapReplacement>(pResult);
}

::boost::shared_ptr<BitmapEx> ResolutionReduction::Decompress (
    const BitmapReplacement& rBitmapData) const
{
    ::boost::shared_ptr<BitmapEx> pResult;

    const ResolutionReducedReplacement* pData (
        dynamic_cast<const ResolutionReducedReplacement*>(&rBitmapData));

    if (pData->mpPreview.get() != NULL)
    {
        pResult.reset(new BitmapEx(*pData->mpPreview));
        if (pData->maOriginalSize.Width() > mnWidth)
            pResult->Scale(pData->maOriginalSize);
    }

    return pResult;
}

bool ResolutionReduction::IsLossless (void) const
{
    return false;
}

//===== PNGCompression ========================================================

class PngCompression::PngReplacement : public BitmapReplacement
{
public:
    void* mpData;
    sal_Int32 mnDataSize;
    Size maImageSize;
    PngReplacement (void)
        : mpData(NULL),
          mnDataSize(0),
          maImageSize(0,0)
    {}
    virtual ~PngReplacement (void)
    {
        delete [] (char*)mpData;
    }
    virtual sal_Int32 GetMemorySize (void) const
    {
        return mnDataSize;
    }
};

::boost::shared_ptr<BitmapReplacement> PngCompression::Compress (
    const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
{
    ::vcl::PNGWriter aWriter (*rpBitmap);
    SvMemoryStream aStream (32768, 32768);
    aWriter.Write(aStream);

    PngReplacement* pResult = new PngReplacement();
    pResult->maImageSize = rpBitmap->GetSizePixel();
    pResult->mnDataSize = aStream.Tell();
    pResult->mpData = new char[pResult->mnDataSize];
    memcpy(pResult->mpData, aStream.GetData(), pResult->mnDataSize);

    return ::boost::shared_ptr<BitmapReplacement>(pResult);
}

::boost::shared_ptr<BitmapEx> PngCompression::Decompress (
    const BitmapReplacement& rBitmapData) const
{
    BitmapEx* pResult = NULL;
    const PngReplacement* pData (dynamic_cast<const PngReplacement*>(&rBitmapData));
    if (pData != NULL)
    {
        SvMemoryStream aStream (pData->mpData, pData->mnDataSize, STREAM_READ);
        ::vcl::PNGReader aReader (aStream);
        pResult = new BitmapEx(aReader.Read());
    }

//    sal_Int32 nRatio ((100L * (ULONG)pResult->GetSizeBytes()) / (ULONG)pData->mnDataSize);

    return ::boost::shared_ptr<BitmapEx>(pResult);
}

bool PngCompression::IsLossless (void) const
{
    return true;
}

} } } // end of namespace ::sd::slidesorter::cache
<|endoftext|>


<commit_before>//
// Copyright (c) 2018 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

#include <nanoHAL.h>
#include <nanoHAL_v2.h>
#include <nanoWeak.h>
#include <Target_BlockStorage_STM32FlashDriver.h>

// initialization of configuration manager
// provided as weak so it can be replaced at target level, if required because of the target implementing the storage with a mechanism other then saving to flash
__nfweak void ConfigurationManager_Initialize()
{
    // enumerate the blocks
    ConfigurationManager_EnumerateConfigurationBlocks();
};

// Enumerates the configuration blocks from the configuration flash sector
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak void ConfigurationManager_EnumerateConfigurationBlocks()
{
    // find network configuration blocks
    HAL_CONFIGURATION_NETWORK* networkConfigs = ConfigurationManager_FindNetworkConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__);

    // find wireless 80211 network configuration blocks
    HAL_CONFIGURATION_NETWORK_WIRELESS80211* networkWirelessConfigs = ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__);

    // alloc memory for g_TargetConfiguration
    // because this is a struct of structs that use flexible members the memory has to be allocated from the heap
    // the malloc size for each struct is computed separately
    uint32_t sizeOfNetworkInterfaceConfigs = offsetof(HAL_CONFIGURATION_NETWORK, Configs) + networkConfigs->Count * sizeof(networkConfigs->Configs[0]);
    uint32_t sizeOfWireless80211Configs = offsetof(HAL_CONFIGURATION_NETWORK_WIRELESS80211, Configs) + networkWirelessConfigs->Count * sizeof(networkWirelessConfigs->Configs[0]);

    g_TargetConfiguration.NetworkInterfaceConfigs = (HAL_CONFIGURATION_NETWORK*)platform_malloc(sizeOfNetworkInterfaceConfigs);
    g_TargetConfiguration.Wireless80211Configs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211*)platform_malloc(sizeOfWireless80211Configs);

    // copy structs to g_TargetConfiguration
    memcpy((HAL_CONFIGURATION_NETWORK*)g_TargetConfiguration.NetworkInterfaceConfigs, networkConfigs, sizeOfNetworkInterfaceConfigs);
    memcpy((HAL_CONFIGURATION_NETWORK_WIRELESS80211*)g_TargetConfiguration.Wireless80211Configs, networkWirelessConfigs, sizeOfWireless80211Configs);

    // // now free the memory of the original structs
    platform_free(networkConfigs);
    platform_free(networkWirelessConfigs);
}

// Gets the network configuration block from the configuration flash sector
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex)
{
    int sizeOfBlock = 0;
    uint8_t* blockAddress;

    // validate if the requested block exists
    // Count has to be non zero
    // requested Index has to exist (array index starts at zero, so need to add one)
    if(configuration == DeviceConfigurationOption_Network)
    {
        if(g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count)
        {
            return FALSE;
        }

        // set block size
        sizeOfBlock = sizeof(HAL_Configuration_NetworkInterface);

        // get block address
        blockAddress = (uint8_t*)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex];
    }
    else if(configuration == DeviceConfigurationOption_Wireless80211Network)
    {
        if(g_TargetConfiguration.Wireless80211Configs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count)
        {
            return FALSE;
        }

        // set block size
        sizeOfBlock = sizeof(HAL_Configuration_Wireless80211);

        // get block address
        blockAddress = (uint8_t*)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex];
    }

    // copy the config block content to the pointer in the argument
    memcpy(configurationBlock, blockAddress, sizeOfBlock);

    return TRUE;
}

// Stores the configuration block to the configuration flash sector
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize)
{
    ByteAddress storageAddress;
    bool requiresEnumeration = FALSE;
    bool success = FALSE;

    if(configuration == DeviceConfigurationOption_Network)
    {
        if(g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count)
        {
            // this is a block that wasn't here before, so we need to enumerate the blocks again after storing it
            requiresEnumeration = TRUE;
        }

        // set storage address from block address
        storageAddress = (ByteAddress)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex];

        // set block size, in case it's not already set
        blockSize = sizeof(HAL_Configuration_NetworkInterface);
    }
    else if(configuration == DeviceConfigurationOption_Wireless80211Network)
    {
        if(g_TargetConfiguration.Wireless80211Configs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count)
        {
            // this is a block that wasn't here before, so we need to enumerate the blocks again after storing it
            requiresEnumeration = TRUE;
        }

        // set storage address from block address
        storageAddress = (ByteAddress)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex];

        // set block size, in case it's not already set
        blockSize = sizeof(HAL_Configuration_Wireless80211);
    }
    else if(configuration == DeviceConfigurationOption_All)
    {
        // particular situation where we are receiving the full configuration block

        // set storage address as the start of the flash configuration sector
        storageAddress = (ByteAddress)&__nanoConfig_start__;

        // always enumerate the blocks again after storing it
        requiresEnumeration = TRUE;

        // for save all the block size has to be provided, check it
        if(blockSize == 0)
        {
            return FALSE;
        }
    }

    // copy the config block content to the config block storage
    success = STM32FlashDriver_Write(NULL, storageAddress, blockSize, (unsigned char*)configurationBlock, true);

    if(success == TRUE && requiresEnumeration)
    {
        // free the current allocation(s)
        platform_free(g_TargetConfiguration.NetworkInterfaceConfigs);
        platform_free(g_TargetConfiguration.Wireless80211Configs);

        // perform enumeration of configuration blocks
        ConfigurationManager_EnumerateConfigurationBlocks();
    }

    return success;
}

// Updates a configuration block in the configuration flash sector
// The flash sector has to be erased before writing the updated block
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak bool ConfigurationManager_UpdateConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex)
{
    ByteAddress storageAddress;
    uint32_t blockOffset;
    uint8_t* blockAddressInCopy;
    uint32_t blockSize;
    bool success = FALSE;

    // config sector size
    int sizeOfConfigSector = (uint32_t)&__nanoConfig_end__ - (uint32_t)&__nanoConfig_start__;

    // allocate memory from CRT heap
    uint8_t* configSectorCopy = (uint8_t*)platform_malloc(sizeOfConfigSector);

    if(configSectorCopy != NULL)
    {
        // copy config sector from flash to RAM
        memcpy(configSectorCopy, &__nanoConfig_start__, sizeOfConfigSector);

        // find out the address for the config block to update in the configSectorCopy
        // because we are copying back the config block to flash and just replacing the config block content
        // the addresses in g_TargetConfiguration will remain the same
        // plus we can calculate the offset of the config block from g_TargetConfiguration
        if(configuration == DeviceConfigurationOption_Network)
        {
            // get storage address from block address
            storageAddress = (ByteAddress)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex];

            // set block size, in case it's not already set
            blockSize = sizeof(HAL_Configuration_NetworkInterface);
        }
        else if(configuration == DeviceConfigurationOption_Wireless80211Network)
        {
            // storage address from block address
            storageAddress = (ByteAddress)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex];

            // set block size, in case it's not already set
            blockSize = sizeof(HAL_Configuration_Wireless80211);
        }
        else
        {
            // this not a valid configuration option to update, quit
            // free memory first
            platform_free(configSectorCopy);

            return FALSE;
        }

        // erase config sector
        if(STM32FlashDriver_EraseBlock(NULL, (uint32_t)&__nanoConfig_start__) == TRUE)
        {
            // flash block is erased

            // subtract the start address of config sector to get the offset
            blockOffset = storageAddress - (uint32_t)&__nanoConfig_start__;

            // set pointer to block to udpate
            blockAddressInCopy = configSectorCopy + blockOffset;

            // replace config block with new content by replacing memory
            memcpy(blockAddressInCopy, configSectorCopy, blockSize);

            // copy the config block copy back to the config block storage
            success = STM32FlashDriver_Write(NULL, (uint32_t)&__nanoConfig_start__, sizeOfConfigSector, (unsigned char*)configSectorCopy, true);
        }

        // free memory
        platform_free(configSectorCopy);
    }

    return success;
}
<commit_msg>Update STM32 StoreConfigurationBlock<commit_after>//
// Copyright (c) 2018 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

#include <nanoHAL.h>
#include <nanoHAL_v2.h>
#include <nanoWeak.h>
#include <Target_BlockStorage_STM32FlashDriver.h>

// initialization of configuration manager
// provided as weak so it can be replaced at target level, if required because of the target implementing the storage with a mechanism other then saving to flash
__nfweak void ConfigurationManager_Initialize()
{
    // enumerate the blocks
    ConfigurationManager_EnumerateConfigurationBlocks();
};

// Enumerates the configuration blocks from the configuration flash sector
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak void ConfigurationManager_EnumerateConfigurationBlocks()
{
    // find network configuration blocks
    HAL_CONFIGURATION_NETWORK* networkConfigs = ConfigurationManager_FindNetworkConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__);

    // find wireless 80211 network configuration blocks
    HAL_CONFIGURATION_NETWORK_WIRELESS80211* networkWirelessConfigs = ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__);

    // alloc memory for g_TargetConfiguration
    // because this is a struct of structs that use flexible members the memory has to be allocated from the heap
    // the malloc size for each struct is computed separately
    uint32_t sizeOfNetworkInterfaceConfigs = offsetof(HAL_CONFIGURATION_NETWORK, Configs) + networkConfigs->Count * sizeof(networkConfigs->Configs[0]);
    uint32_t sizeOfWireless80211Configs = offsetof(HAL_CONFIGURATION_NETWORK_WIRELESS80211, Configs) + networkWirelessConfigs->Count * sizeof(networkWirelessConfigs->Configs[0]);

    g_TargetConfiguration.NetworkInterfaceConfigs = (HAL_CONFIGURATION_NETWORK*)platform_malloc(sizeOfNetworkInterfaceConfigs);
    g_TargetConfiguration.Wireless80211Configs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211*)platform_malloc(sizeOfWireless80211Configs);

    // copy structs to g_TargetConfiguration
    memcpy((HAL_CONFIGURATION_NETWORK*)g_TargetConfiguration.NetworkInterfaceConfigs, networkConfigs, sizeOfNetworkInterfaceConfigs);
    memcpy((HAL_CONFIGURATION_NETWORK_WIRELESS80211*)g_TargetConfiguration.Wireless80211Configs, networkWirelessConfigs, sizeOfWireless80211Configs);

    // // now free the memory of the original structs
    platform_free(networkConfigs);
    platform_free(networkWirelessConfigs);
}

// Gets the network configuration block from the configuration flash sector
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex)
{
    int sizeOfBlock = 0;
    uint8_t* blockAddress;

    // validate if the requested block exists
    // Count has to be non zero
    // requested Index has to exist (array index starts at zero, so need to add one)
    if(configuration == DeviceConfigurationOption_Network)
    {
        if(g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count)
        {
            return FALSE;
        }

        // set block size
        sizeOfBlock = sizeof(HAL_Configuration_NetworkInterface);

        // get block address
        blockAddress = (uint8_t*)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex];
    }
    else if(configuration == DeviceConfigurationOption_Wireless80211Network)
    {
        if(g_TargetConfiguration.Wireless80211Configs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count)
        {
            return FALSE;
        }

        // set block size
        sizeOfBlock = sizeof(HAL_Configuration_Wireless80211);

        // get block address
        blockAddress = (uint8_t*)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex];
    }

    // copy the config block content to the pointer in the argument
    memcpy(configurationBlock, blockAddress, sizeOfBlock);

    return TRUE;
}

// Stores the configuration block to the configuration flash sector
// NOTE: because inserting or removing a configuration block it's very 'RAM expensive' we choose not to support those operations
// the host debugger will have to be used to manage these operations on the device configuration collection
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize)
{
    ByteAddress storageAddress;
    bool requiresEnumeration = FALSE;
    bool success = FALSE;

    if(configuration == DeviceConfigurationOption_Network)
    {
        if(g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count)
        {
            // there is no room for this block, fail the operation
            return FALSE;
        }

        // set storage address from block address
        storageAddress = (ByteAddress)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex];

        // set block size, in case it's not already set
        blockSize = sizeof(HAL_Configuration_NetworkInterface);
    }
    else if(configuration == DeviceConfigurationOption_Wireless80211Network)
    {
        if(g_TargetConfiguration.Wireless80211Configs->Count == 0 ||
            (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count)
        {
            // there is no room for this block, fail the operation
            return FALSE;
        }

        // set storage address from block address
        storageAddress = (ByteAddress)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex];

        // set block size, in case it's not already set
        blockSize = sizeof(HAL_Configuration_Wireless80211);
    }
    else if(configuration == DeviceConfigurationOption_All)
    {
        // particular situation where we are receiving the full configuration block

        // set storage address as the start of the flash configuration sector
        storageAddress = (ByteAddress)&__nanoConfig_start__;

        // always enumerate the blocks again after storing it
        requiresEnumeration = TRUE;

        // for save all the block size has to be provided, check that
        if(blockSize == 0)
        {
            return FALSE;
        }
    }

    // copy the config block content to the config block storage
    success = STM32FlashDriver_Write(NULL, storageAddress, blockSize, (unsigned char*)configurationBlock, true);

    if(success == TRUE && requiresEnumeration)
    {
        // free the current allocation(s)
        platform_free(g_TargetConfiguration.NetworkInterfaceConfigs);
        platform_free(g_TargetConfiguration.Wireless80211Configs);

        // perform enumeration of configuration blocks
        ConfigurationManager_EnumerateConfigurationBlocks();
    }

    return success;
}

// Updates a configuration block in the configuration flash sector
// The flash sector has to be erased before writing the updated block
// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used
__nfweak bool ConfigurationManager_UpdateConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex)
{
    ByteAddress storageAddress;
    uint32_t blockOffset;
    uint8_t* blockAddressInCopy;
    uint32_t blockSize;
    bool success = FALSE;

    // config sector size
    int sizeOfConfigSector = (uint32_t)&__nanoConfig_end__ - (uint32_t)&__nanoConfig_start__;

    // allocate memory from CRT heap
    uint8_t* configSectorCopy = (uint8_t*)platform_malloc(sizeOfConfigSector);

    if(configSectorCopy != NULL)
    {
        // copy config sector from flash to RAM
        memcpy(configSectorCopy, &__nanoConfig_start__, sizeOfConfigSector);

        // find out the address for the config block to update in the configSectorCopy
        // because we are copying back the config block to flash and just replacing the config block content
        // the addresses in g_TargetConfiguration will remain the same
        // plus we can calculate the offset of the config block from g_TargetConfiguration
        if(configuration == DeviceConfigurationOption_Network)
        {
            // get storage address from block address
            storageAddress = (ByteAddress)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex];

            // set block size, in case it's not already set
            blockSize = sizeof(HAL_Configuration_NetworkInterface);
        }
        else if(configuration == DeviceConfigurationOption_Wireless80211Network)
        {
            // storage address from block address
            storageAddress = (ByteAddress)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex];

            // set block size, in case it's not already set
            blockSize = sizeof(HAL_Configuration_Wireless80211);
        }
        else
        {
            // this not a valid configuration option to update, quit
            // free memory first
            platform_free(configSectorCopy);

            return FALSE;
        }

        // erase config sector
        if(STM32FlashDriver_EraseBlock(NULL, (uint32_t)&__nanoConfig_start__) == TRUE)
        {
            // flash block is erased

            // subtract the start address of config sector to get the offset
            blockOffset = storageAddress - (uint32_t)&__nanoConfig_start__;

            // set pointer to block to udpate
            blockAddressInCopy = configSectorCopy + blockOffset;

            // replace config block with new content by replacing memory
            memcpy(blockAddressInCopy, configSectorCopy, blockSize);

            // copy the config block copy back to the config block storage
            success = STM32FlashDriver_Write(NULL, (uint32_t)&__nanoConfig_start__, sizeOfConfigSector, (unsigned char*)configSectorCopy, true);
        }

        // free memory
        platform_free(configSectorCopy);
    }

    return success;
}
<|endoftext|>


<commit_before><?hh //strict

/**
 * This file is part of hhpack\typesafety package.
 *
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace hhpack\typesafety;

use Exception;

final class ApplicationResult
{

    public function __construct(
        private ResultType $result = ResultType::Ok,
        private ?Exception $exception = null
    )
    {
    }

    public function isOk() : bool
    {
        return ResultType::Ok === $this->result;
    }

    public function isError() : bool
    {
        return ResultType::Error === $this->result;
    }

    public function displayError(Output $output) : void
    {
        if ($this->exception === null) {
            return;
        }
        $output->error($this->exception->getMessage());
        $output->error($this->exception->getTraceAsString());
    }

    public static function Ok() : this
    {
        return new static();
    }

    public static function Error(Exception $exception) : this
    {
        return new static(ResultType::Error, $exception);
    }

}
<commit_msg>fix nullable member error<commit_after><?hh //strict

/**
 * This file is part of hhpack\typesafety package.
 *
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace hhpack\typesafety;

use Exception;

final class ApplicationResult
{

    public function __construct(
        private ResultType $result = ResultType::Ok,
        private ?Exception $exception = null
    )
    {
    }

    public function isOk() : bool
    {
        return ResultType::Ok === $this->result;
    }

    public function isError() : bool
    {
        return ResultType::Error === $this->result;
    }

    public function displayError(Output $output) : void
    {
        if ($this->exception === null) {
            return;
        }
        $exception = $this->exception;
        $output->error($exception->getMessage());
        $output->error($exception->getTraceAsString());
    }

    public static function Ok() : this
    {
        return new static();
    }

    public static function Error(Exception $exception) : this
    {
        return new static(ResultType::Error, $exception);
    }

}
<|endoftext|>


<commit_before>//===--- Pattern.cpp - Swift Language Pattern-Matching ASTs ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Pattern class and subclasses.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Pattern.h"
#include "swift/AST/AST.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/TypeLoc.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;

/// Diagnostic printing of PatternKinds.
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS, PatternKind kind) {
  switch (kind) {
  case PatternKind::Paren:
    return OS << "parenthesized pattern";
  case PatternKind::Tuple:
    return OS << "tuple pattern";
  case PatternKind::Named:
    return OS << "pattern variable binding";
  case PatternKind::Any:
    return OS << "'_' pattern";
  case PatternKind::Typed:
    return OS << "pattern type annotation";
  case PatternKind::Is:
    return OS << "prefix 'is' pattern";
  case PatternKind::Expr:
    return OS << "expression pattern";
  case PatternKind::Var:
    return OS << "'var' binding pattern";
  case PatternKind::EnumElement:
    return OS << "enum case matching pattern";
  case PatternKind::OptionalSome:
    return OS << "optional .Some matching pattern";
  case PatternKind::Bool:
    return OS << "bool matching pattern";
  }
  llvm_unreachable("bad PatternKind");
}

StringRef Pattern::getKindName(PatternKind K) {
  switch (K) {
#define PATTERN(Id, Parent) case PatternKind::Id: return #Id;
#include "swift/AST/PatternNodes.def"
  }
  llvm_unreachable("bad PatternKind");
}

// Metaprogram to verify that every concrete class implements
// a 'static bool classof(const Pattern*)'.
template <bool fn(const Pattern*)> struct CheckClassOfPattern {
  static const bool IsImplemented = true;
};
template <> struct CheckClassOfPattern<Pattern::classof> {
  static const bool IsImplemented = false;
};

#define PATTERN(ID, PARENT) \
static_assert(CheckClassOfPattern<ID##Pattern::classof>::IsImplemented, \
              #ID "Pattern is missing classof(const Pattern*)");
#include "swift/AST/PatternNodes.def"

// Metaprogram to verify that every concrete class implements
// 'SourceRange getSourceRange()'.
typedef const char (&TwoChars)[2];
template<typename Class>
inline char checkSourceRangeType(SourceRange (Class::*)() const);
inline TwoChars checkSourceRangeType(SourceRange (Pattern::*)() const);

/// getSourceRange - Return the full source range of the pattern.
SourceRange Pattern::getSourceRange() const {
  switch (getKind()) {
#define PATTERN(ID, PARENT) \
case PatternKind::ID: \
static_assert(sizeof(checkSourceRangeType(&ID##Pattern::getSourceRange)) == 1, \
              #ID "Pattern is missing getSourceRange()"); \
return cast<ID##Pattern>(this)->getSourceRange();
#include "swift/AST/PatternNodes.def"
  }

  llvm_unreachable("pattern type not handled!");
}

/// getLoc - Return the caret location of the pattern.
SourceLoc Pattern::getLoc() const {
  switch (getKind()) {
#define PATTERN(ID, PARENT) \
  case PatternKind::ID: \
    if (&Pattern::getLoc != &ID##Pattern::getLoc) \
      return cast<ID##Pattern>(this)->getLoc(); \
    break;
#include "swift/AST/PatternNodes.def"
  }

  return getStartLoc();
}

void Pattern::collectVariables(SmallVectorImpl<VarDecl *> &variables) const {
  forEachVariable([&](VarDecl *VD) { variables.push_back(VD); });
}

VarDecl *Pattern::getSingleVar() const {
  auto pattern = getSemanticsProvidingPattern();
  if (auto named = dyn_cast<NamedPattern>(pattern))
    return named->getDecl();

  return nullptr;
}

namespace {
  class WalkToVarDecls : public ASTWalker {
    const std::function<void(VarDecl*)> &fn;
  public:

    WalkToVarDecls(const std::function<void(VarDecl*)> &fn)
    : fn(fn) {}

    Pattern *walkToPatternPost(Pattern *P) override {
      // Handle vars.
      if (auto *Named = dyn_cast<NamedPattern>(P))
        fn(Named->getDecl());
      return P;
    }
  };
}

/// \brief apply the specified function to all variables referenced in this
/// pattern.
void Pattern::forEachVariable(const std::function<void(VarDecl*)> &fn) const {
  switch (getKind()) {
  case PatternKind::Any:
  case PatternKind::Bool:
    return;

  case PatternKind::Is:
    if (auto SP = cast<IsPattern>(this)->getSubPattern())
      SP->forEachVariable(fn);
    return;

  case PatternKind::Named:
    fn(cast<NamedPattern>(this)->getDecl());
    return;

  case PatternKind::Paren:
  case PatternKind::Typed:
  case PatternKind::Var:
    return getSemanticsProvidingPattern()->forEachVariable(fn);

  case PatternKind::Tuple:
    for (auto elt : cast<TuplePattern>(this)->getElements())
      elt.getPattern()->forEachVariable(fn);
    return;

  case PatternKind::EnumElement:
    if (auto SP = cast<EnumElementPattern>(this)->getSubPattern())
      SP->forEachVariable(fn);
    return;

    case PatternKind::OptionalSome:
    cast<OptionalSomePattern>(this)->getSubPattern()->forEachVariable(fn);
    return;

  case PatternKind::Expr:
    // An ExprPattern only exists before sema has resolved a refutable pattern
    // into a concrete pattern.  We have to use an AST Walker to find the
    // VarDecls buried down inside of it.
    const_cast<Pattern*>(this)->walk(WalkToVarDecls(fn));
    return;
  }
}

/// \brief apply the specified function to all pattern nodes recursively in
/// this pattern.  This is a pre-order traversal.
void Pattern::forEachNode(const std::function<void(Pattern*)> &f) {
  f(this);

  switch (getKind()) {
  // Leaf patterns have no recursion.
  case PatternKind::Any:
  case PatternKind::Named:
  case PatternKind::Expr:// FIXME: expr nodes are not modeled right in general.
  case PatternKind::Bool:
    return;

  case PatternKind::Is:
    if (auto SP = cast<IsPattern>(this)->getSubPattern())
      SP->forEachNode(f);
    return;

  case PatternKind::Paren:
    return cast<ParenPattern>(this)->getSubPattern()->forEachNode(f);
  case PatternKind::Typed:
    return cast<TypedPattern>(this)->getSubPattern()->forEachNode(f);
  case PatternKind::Var:
    return cast<VarPattern>(this)->getSubPattern()->forEachNode(f);

  case PatternKind::Tuple:
    for (auto elt : cast<TuplePattern>(this)->getElements())
      elt.getPattern()->forEachNode(f);
    return;

  case PatternKind::EnumElement: {
    auto *OP = cast<EnumElementPattern>(this);
    if (OP->hasSubPattern())
      OP->getSubPattern()->forEachNode(f);
    return;
  }
  case PatternKind::OptionalSome:
    cast<OptionalSomePattern>(this)->getSubPattern()->forEachNode(f);
    return;
  }
}

bool Pattern::hasStorage() const {
  bool HasStorage = false;
  forEachVariable([&](VarDecl *VD) {
    if (VD->hasStorage())
      HasStorage = true;
  });

  return HasStorage;
}

/// Return true if this is a non-resolved ExprPattern which is syntactically
/// irrefutable.
static bool isIrrefutableExprPattern(const ExprPattern *EP) {
  // If the pattern has a registered match expression, it's
  // a type-checked ExprPattern.
  if (EP->getMatchExpr()) return false;

  auto expr = EP->getSubExpr();
  while (true) {
    // Drill into parens.
    if (auto parens = dyn_cast<ParenExpr>(expr)) {
      expr = parens->getSubExpr();
      continue;
    }

      // A '_' is an untranslated AnyPattern.
    if (isa<DiscardAssignmentExpr>(expr))
      return true;

    // Everything else is non-exhaustive.
    return false;
  }
}

/// Return true if this pattern (or a subpattern) is refutable.
bool Pattern::isRefutablePattern() const {
  bool foundRefutablePattern = false;
  const_cast<Pattern*>(this)->forEachNode([&](Pattern *Node) {

    // If this is an always matching 'is' pattern, then it isn't refutable.
    if (auto *is = dyn_cast<IsPattern>(Node))
      if (is->getCastKind() == CheckedCastKind::Coercion)
        return;

    // If this is an ExprPattern that isn't resolved yet, do some simple
    // syntactic checks.
    // FIXME: This is unsound, since type checking will turn other more
    // complicated patterns into non-refutable forms.
    if (auto *ep = dyn_cast<ExprPattern>(Node))
      if (isIrrefutableExprPattern(ep))
        return;

    switch (Node->getKind()) {
#define PATTERN(ID, PARENT) case PatternKind::ID: break;
#define REFUTABLE_PATTERN(ID, PARENT) \
case PatternKind::ID: foundRefutablePattern = true; break;
#include "swift/AST/PatternNodes.def"
    }
  });

  return foundRefutablePattern;
}

/// Standard allocator for Patterns.
void *Pattern::operator new(size_t numBytes, const ASTContext &C) {
  return C.Allocate(numBytes, alignof(Pattern));
}

/// Find the name directly bound by this pattern.  When used as a
/// tuple element in a function signature, such names become part of
/// the type.
Identifier Pattern::getBoundName() const {
  if (auto *NP = dyn_cast<NamedPattern>(getSemanticsProvidingPattern()))
    return NP->getBoundName();
  return Identifier();
}

Identifier NamedPattern::getBoundName() const {
  return Var->getName();
}

/// Allocate a new pattern that matches a tuple.
TuplePattern *TuplePattern::create(ASTContext &C, SourceLoc lp,
                                   ArrayRef<TuplePatternElt> elts, SourceLoc rp,
                                   Optional<bool> implicit) {
  if (!implicit.hasValue())
    implicit = !lp.isValid();

  unsigned n = elts.size();
  void *buffer = C.Allocate(totalSizeToAlloc<TuplePatternElt>(n),
                            alignof(TuplePattern));
  TuplePattern *pattern = ::new (buffer) TuplePattern(lp, n, rp, *implicit);
  std::uninitialized_copy(elts.begin(), elts.end(),
                          pattern->getTrailingObjects<TuplePatternElt>());
  return pattern;
}

Pattern *TuplePattern::createSimple(ASTContext &C, SourceLoc lp,
                                    ArrayRef<TuplePatternElt> elements,
                                    SourceLoc rp,
                                    Optional<bool> implicit) {
  assert(lp.isValid() == rp.isValid());

  if (elements.size() == 1 &&
      elements[0].getPattern()->getBoundName().empty()) {
    auto &first = const_cast<TuplePatternElt&>(elements.front());
    return new (C) ParenPattern(lp, first.getPattern(), rp, implicit);
  }

  return create(C, lp, elements, rp, implicit);
}

SourceRange TuplePattern::getSourceRange() const {
  if (LPLoc.isValid())
    return { LPLoc, RPLoc };
  auto Fields = getElements();
  if (Fields.empty())
    return {};
  return { Fields.front().getPattern()->getStartLoc(),
           Fields.back().getPattern()->getEndLoc() };
}

SourceRange TypedPattern::getSourceRange() const {
  if (isImplicit()) {
    // If a TypedPattern is implicit, then its type is definitely implicit, so
    // we should ignore its location.  On the other hand, the sub-pattern can
    // be explicit or implicit.
    return SubPattern->getSourceRange();
  }

  if (SubPattern->isImplicit())
    return PatType.getSourceRange();

  return { SubPattern->getSourceRange().Start, PatType.getSourceRange().End };
}

<commit_msg>[AST] Don’t include propagated type locations in the source range of a type pattern.<commit_after>//===--- Pattern.cpp - Swift Language Pattern-Matching ASTs ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Pattern class and subclasses.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Pattern.h"
#include "swift/AST/AST.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/TypeLoc.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;

/// Diagnostic printing of PatternKinds.
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS, PatternKind kind) {
  switch (kind) {
  case PatternKind::Paren:
    return OS << "parenthesized pattern";
  case PatternKind::Tuple:
    return OS << "tuple pattern";
  case PatternKind::Named:
    return OS << "pattern variable binding";
  case PatternKind::Any:
    return OS << "'_' pattern";
  case PatternKind::Typed:
    return OS << "pattern type annotation";
  case PatternKind::Is:
    return OS << "prefix 'is' pattern";
  case PatternKind::Expr:
    return OS << "expression pattern";
  case PatternKind::Var:
    return OS << "'var' binding pattern";
  case PatternKind::EnumElement:
    return OS << "enum case matching pattern";
  case PatternKind::OptionalSome:
    return OS << "optional .Some matching pattern";
  case PatternKind::Bool:
    return OS << "bool matching pattern";
  }
  llvm_unreachable("bad PatternKind");
}

StringRef Pattern::getKindName(PatternKind K) {
  switch (K) {
#define PATTERN(Id, Parent) case PatternKind::Id: return #Id;
#include "swift/AST/PatternNodes.def"
  }
  llvm_unreachable("bad PatternKind");
}

// Metaprogram to verify that every concrete class implements
// a 'static bool classof(const Pattern*)'.
template <bool fn(const Pattern*)> struct CheckClassOfPattern {
  static const bool IsImplemented = true;
};
template <> struct CheckClassOfPattern<Pattern::classof> {
  static const bool IsImplemented = false;
};

#define PATTERN(ID, PARENT) \
static_assert(CheckClassOfPattern<ID##Pattern::classof>::IsImplemented, \
              #ID "Pattern is missing classof(const Pattern*)");
#include "swift/AST/PatternNodes.def"

// Metaprogram to verify that every concrete class implements
// 'SourceRange getSourceRange()'.
typedef const char (&TwoChars)[2];
template<typename Class>
inline char checkSourceRangeType(SourceRange (Class::*)() const);
inline TwoChars checkSourceRangeType(SourceRange (Pattern::*)() const);

/// getSourceRange - Return the full source range of the pattern.
SourceRange Pattern::getSourceRange() const {
  switch (getKind()) {
#define PATTERN(ID, PARENT) \
case PatternKind::ID: \
static_assert(sizeof(checkSourceRangeType(&ID##Pattern::getSourceRange)) == 1, \
              #ID "Pattern is missing getSourceRange()"); \
return cast<ID##Pattern>(this)->getSourceRange();
#include "swift/AST/PatternNodes.def"
  }

  llvm_unreachable("pattern type not handled!");
}

/// getLoc - Return the caret location of the pattern.
SourceLoc Pattern::getLoc() const {
  switch (getKind()) {
#define PATTERN(ID, PARENT) \
  case PatternKind::ID: \
    if (&Pattern::getLoc != &ID##Pattern::getLoc) \
      return cast<ID##Pattern>(this)->getLoc(); \
    break;
#include "swift/AST/PatternNodes.def"
  }

  return getStartLoc();
}

void Pattern::collectVariables(SmallVectorImpl<VarDecl *> &variables) const {
  forEachVariable([&](VarDecl *VD) { variables.push_back(VD); });
}

VarDecl *Pattern::getSingleVar() const {
  auto pattern = getSemanticsProvidingPattern();
  if (auto named = dyn_cast<NamedPattern>(pattern))
    return named->getDecl();

  return nullptr;
}

namespace {
  class WalkToVarDecls : public ASTWalker {
    const std::function<void(VarDecl*)> &fn;
  public:

    WalkToVarDecls(const std::function<void(VarDecl*)> &fn)
    : fn(fn) {}

    Pattern *walkToPatternPost(Pattern *P) override {
      // Handle vars.
      if (auto *Named = dyn_cast<NamedPattern>(P))
        fn(Named->getDecl());
      return P;
    }
  };
}

/// \brief apply the specified function to all variables referenced in this
/// pattern.
void Pattern::forEachVariable(const std::function<void(VarDecl*)> &fn) const {
  switch (getKind()) {
  case PatternKind::Any:
  case PatternKind::Bool:
    return;

  case PatternKind::Is:
    if (auto SP = cast<IsPattern>(this)->getSubPattern())
      SP->forEachVariable(fn);
    return;

  case PatternKind::Named:
    fn(cast<NamedPattern>(this)->getDecl());
    return;

  case PatternKind::Paren:
  case PatternKind::Typed:
  case PatternKind::Var:
    return getSemanticsProvidingPattern()->forEachVariable(fn);

  case PatternKind::Tuple:
    for (auto elt : cast<TuplePattern>(this)->getElements())
      elt.getPattern()->forEachVariable(fn);
    return;

  case PatternKind::EnumElement:
    if (auto SP = cast<EnumElementPattern>(this)->getSubPattern())
      SP->forEachVariable(fn);
    return;

    case PatternKind::OptionalSome:
    cast<OptionalSomePattern>(this)->getSubPattern()->forEachVariable(fn);
    return;

  case PatternKind::Expr:
    // An ExprPattern only exists before sema has resolved a refutable pattern
    // into a concrete pattern.  We have to use an AST Walker to find the
    // VarDecls buried down inside of it.
    const_cast<Pattern*>(this)->walk(WalkToVarDecls(fn));
    return;
  }
}

/// \brief apply the specified function to all pattern nodes recursively in
/// this pattern.  This is a pre-order traversal.
void Pattern::forEachNode(const std::function<void(Pattern*)> &f) {
  f(this);

  switch (getKind()) {
  // Leaf patterns have no recursion.
  case PatternKind::Any:
  case PatternKind::Named:
  case PatternKind::Expr:// FIXME: expr nodes are not modeled right in general.
  case PatternKind::Bool:
    return;

  case PatternKind::Is:
    if (auto SP = cast<IsPattern>(this)->getSubPattern())
      SP->forEachNode(f);
    return;

  case PatternKind::Paren:
    return cast<ParenPattern>(this)->getSubPattern()->forEachNode(f);
  case PatternKind::Typed:
    return cast<TypedPattern>(this)->getSubPattern()->forEachNode(f);
  case PatternKind::Var:
    return cast<VarPattern>(this)->getSubPattern()->forEachNode(f);

  case PatternKind::Tuple:
    for (auto elt : cast<TuplePattern>(this)->getElements())
      elt.getPattern()->forEachNode(f);
    return;

  case PatternKind::EnumElement: {
    auto *OP = cast<EnumElementPattern>(this);
    if (OP->hasSubPattern())
      OP->getSubPattern()->forEachNode(f);
    return;
  }
  case PatternKind::OptionalSome:
    cast<OptionalSomePattern>(this)->getSubPattern()->forEachNode(f);
    return;
  }
}

bool Pattern::hasStorage() const {
  bool HasStorage = false;
  forEachVariable([&](VarDecl *VD) {
    if (VD->hasStorage())
      HasStorage = true;
  });

  return HasStorage;
}

/// Return true if this is a non-resolved ExprPattern which is syntactically
/// irrefutable.
static bool isIrrefutableExprPattern(const ExprPattern *EP) {
  // If the pattern has a registered match expression, it's
  // a type-checked ExprPattern.
  if (EP->getMatchExpr()) return false;

  auto expr = EP->getSubExpr();
  while (true) {
    // Drill into parens.
    if (auto parens = dyn_cast<ParenExpr>(expr)) {
      expr = parens->getSubExpr();
      continue;
    }

      // A '_' is an untranslated AnyPattern.
    if (isa<DiscardAssignmentExpr>(expr))
      return true;

    // Everything else is non-exhaustive.
    return false;
  }
}

/// Return true if this pattern (or a subpattern) is refutable.
bool Pattern::isRefutablePattern() const {
  bool foundRefutablePattern = false;
  const_cast<Pattern*>(this)->forEachNode([&](Pattern *Node) {

    // If this is an always matching 'is' pattern, then it isn't refutable.
    if (auto *is = dyn_cast<IsPattern>(Node))
      if (is->getCastKind() == CheckedCastKind::Coercion)
        return;

    // If this is an ExprPattern that isn't resolved yet, do some simple
    // syntactic checks.
    // FIXME: This is unsound, since type checking will turn other more
    // complicated patterns into non-refutable forms.
    if (auto *ep = dyn_cast<ExprPattern>(Node))
      if (isIrrefutableExprPattern(ep))
        return;

    switch (Node->getKind()) {
#define PATTERN(ID, PARENT) case PatternKind::ID: break;
#define REFUTABLE_PATTERN(ID, PARENT) \
case PatternKind::ID: foundRefutablePattern = true; break;
#include "swift/AST/PatternNodes.def"
    }
  });

  return foundRefutablePattern;
}

/// Standard allocator for Patterns.
void *Pattern::operator new(size_t numBytes, const ASTContext &C) {
  return C.Allocate(numBytes, alignof(Pattern));
}

/// Find the name directly bound by this pattern.  When used as a
/// tuple element in a function signature, such names become part of
/// the type.
Identifier Pattern::getBoundName() const {
  if (auto *NP = dyn_cast<NamedPattern>(getSemanticsProvidingPattern()))
    return NP->getBoundName();
  return Identifier();
}

Identifier NamedPattern::getBoundName() const {
  return Var->getName();
}

/// Allocate a new pattern that matches a tuple.
TuplePattern *TuplePattern::create(ASTContext &C, SourceLoc lp,
                                   ArrayRef<TuplePatternElt> elts, SourceLoc rp,
                                   Optional<bool> implicit) {
  if (!implicit.hasValue())
    implicit = !lp.isValid();

  unsigned n = elts.size();
  void *buffer = C.Allocate(totalSizeToAlloc<TuplePatternElt>(n),
                            alignof(TuplePattern));
  TuplePattern *pattern = ::new (buffer) TuplePattern(lp, n, rp, *implicit);
  std::uninitialized_copy(elts.begin(), elts.end(),
                          pattern->getTrailingObjects<TuplePatternElt>());
  return pattern;
}

Pattern *TuplePattern::createSimple(ASTContext &C, SourceLoc lp,
                                    ArrayRef<TuplePatternElt> elements,
                                    SourceLoc rp,
                                    Optional<bool> implicit) {
  assert(lp.isValid() == rp.isValid());

  if (elements.size() == 1 &&
      elements[0].getPattern()->getBoundName().empty()) {
    auto &first = const_cast<TuplePatternElt&>(elements.front());
    return new (C) ParenPattern(lp, first.getPattern(), rp, implicit);
  }

  return create(C, lp, elements, rp, implicit);
}

SourceRange TuplePattern::getSourceRange() const {
  if (LPLoc.isValid())
    return { LPLoc, RPLoc };
  auto Fields = getElements();
  if (Fields.empty())
    return {};
  return { Fields.front().getPattern()->getStartLoc(),
           Fields.back().getPattern()->getEndLoc() };
}

SourceRange TypedPattern::getSourceRange() const {
  if (isImplicit() || isPropagatedType()) {
    // If a TypedPattern is implicit, then its type is definitely implicit, so
    // we should ignore its location.  On the other hand, the sub-pattern can
    // be explicit or implicit.
    return SubPattern->getSourceRange();
  }

  if (SubPattern->isImplicit())
    return PatType.getSourceRange();

  return { SubPattern->getSourceRange().Start, PatType.getSourceRange().End };
}

<|endoftext|>