コード例 #1
0
ファイル: streader.c プロジェクト: cyberixae/kunquat
END_TEST


START_TEST(Read_valid_string)
{
    static const struct
    {
        const char* data;
        const char* expected;
    }
    strings[] =
    {
        { "\"\"", "" },
        { "\" \"", " " },
        { "\"  \"", "  " },
        { "\"\\\"\"", "\"" },
        { "\"\\\\\"", "\\" },
        { "\"\\/\"", "/" },
        { "\"/\"", "/" },
        /*
        { "\"\\b\"", "\b" },
        { "\"\\f\"", "\f" },
        { "\"\\n\"", "\n" },
        { "\"\\r\"", "\r" },
        { "\"\\t\"", "\t" },
        */
        { "\"abc def\"", "abc def" },
    };

    for (size_t i = 0; i < arr_size(strings); ++i)
    {
        char data[128] = "";
        sprintf(data, "%s x", strings[i].data);

        Streader* sr = init_with_cstr(data);
        char result[128] = "zzz";

        fail_if(!Streader_read_string(sr, 128, result),
                "Could not read string `%s`: %s",
                data, Streader_get_error_desc(sr));
        fail_if(strcmp(result, strings[i].expected) != 0,
                "Streader stored `%s` instead of `%s`",
                result, strings[i].expected);
        fail_if(!Streader_match_char(sr, 'x'),
                "Streader did not consume string `%s` correctly");
    }
}
コード例 #2
0
ファイル: streader.c プロジェクト: kagu/kunquat
END_TEST


START_TEST(Read_valid_tstamp)
{
    static const struct
    {
        const char* data;
        const Tstamp expected;
    }
    tstamps[] =
    {
        { "[0, 0]", { 0, 0 } },
        { "[2,5]",  { 2, 5 } },
        { " [2,5]", { 2, 5 } },
        { "[ 2,5]", { 2, 5 } },
        { "[2 ,5]", { 2, 5 } },
        { "[2, 5]", { 2, 5 } },
        { "[2,5 ]", { 2, 5 } },
        { "[-1, 3]", { -1, 3 } },
        { "[0, 882161279]", { 0, KQT_TSTAMP_BEAT - 1 } },
    };

    for (size_t i = 0; i < arr_size(tstamps); ++i)
    {
        char data[128] = "";
        sprintf(data, "%s x", tstamps[i].data);

        Streader* sr = init_with_cstr(data);
        Tstamp* result = Tstamp_set(TSTAMP_AUTO, 99, 99);

        fail_if(!Streader_read_tstamp(sr, result),
                "Could not read timestamp " PRIts " from `%s`: %s",
                PRIVALts(tstamps[i].expected),
                data,
                Streader_get_error_desc(sr));
        fail_if(Tstamp_cmp(result, &tstamps[i].expected) != 0,
                "Streader stored " PRIts " instead of " PRIts
                    " when reading `%s`",
                PRIVALts(*result),
                PRIVALts(tstamps[i].expected),
                data);
        fail_if(!Streader_match_char(sr, 'x'),
                "Streader did not consume timestamp from `%s` correctly", data);
    }
}
コード例 #3
0
bool read_received_events_bind(Streader* sr, int32_t index, void* userdata)
{
    assert(sr != NULL);
    (void)index;
    assert(userdata != NULL);

    int32_t* expected = userdata;
    double actual = NAN;

    if (index == 0 && *expected == 0)
    {
        return Streader_readf(sr, "[0, [") &&
            Streader_match_string(sr, "#") &&
            Streader_match_char(sr, ',') &&
            Streader_read_string(sr, 0, NULL) &&
            Streader_readf(sr, "]]");
    }

    if (!(Streader_readf(sr, "[0, [") &&
                Streader_match_string(sr, "n+") &&
                Streader_readf(sr, ", %f]]", &actual))
       )
        return false;

    if ((int)round(actual) != *expected)
    {
        Streader_set_error(
                sr,
                "Received argument %.0f instead of %" PRId32,
                actual, *expected);
        return false;
    }

    *expected = (int)round(actual) + 1;

    return true;
}
コード例 #4
0
ファイル: streader.c プロジェクト: kagu/kunquat
END_TEST


START_TEST(Read_empty_dict)
{
    static const char* dicts[] =
    {
        "{} x",
        "{ }x",
        "{ } x",
    };

    for (size_t i = 0; i < arr_size(dicts); ++i)
    {
        Streader* sr = init_with_cstr(dicts[i]);
        fail_if(!Streader_read_dict(sr, NULL, NULL),
                "Could not read empty dictionary from `%s`: %s",
                dicts[i],
                Streader_get_error_desc(sr));
        fail_if(!Streader_match_char(sr, 'x'),
                "Streader did not consume empty dictionary from `%s` correctly",
                dicts[i]);
    }
}
コード例 #5
0
bool Streader_readf(Streader* sr, const char* format, ...)
{
    rassert(sr != NULL);
    rassert(format != NULL);

    va_list args;
    va_start(args, format);

    while (!Streader_is_error_set(sr) && *format != '\0')
    {
        if (*format == '%')
        {
            // Conversion characters
            ++format;

            switch (*format)
            {
                case 'n':
                {
                    Streader_read_null(sr);
                }
                break;

                case 'b':
                {
                    bool* dest = va_arg(args, bool*);
                    Streader_read_bool(sr, dest);
                }
                break;

                case 'i':
                {
                    int64_t* dest = va_arg(args, int64_t*);
                    Streader_read_int(sr, dest);
                }
                break;

                case 'f':
                {
                    double* dest = va_arg(args, double*);
                    Streader_read_float(sr, dest);
                }
                break;

                case 's':
                {
                    Streader_readf_str_info info =
                        va_arg(args, Streader_readf_str_info);
                    rassert(info.guard == Streader_readf_str_guard);

                    const int64_t max_bytes = info.max_bytes;
                    char* dest = info.dest;
                    Streader_read_string(sr, max_bytes, dest);
                }
                break;

                case 't':
                {
                    Tstamp* dest = va_arg(args, Tstamp*);
                    Streader_read_tstamp(sr, dest);
                }
                break;

                case 'p':
                {
                    Pat_inst_ref* dest = va_arg(args, Pat_inst_ref*);
                    Streader_read_piref(sr, dest);
                }
                break;

                case 'l':
                {
                    List_item_reader* ir = va_arg(args, List_item_reader*);
                    void* userdata = va_arg(args, void*);
                    Streader_read_list(sr, ir, userdata);
                }
                break;

                case 'd':
                {
                    Dict_item_reader* ir = va_arg(args, Dict_item_reader*);
                    void* userdata = va_arg(args, void*);
                    Streader_read_dict(sr, ir, userdata);
                }
                break;

                case '%':
                {
                    Streader_match_char(sr, '%');
                }
                break;

                default:
                    rassert(false);
            }
        }
        else
        {
            // Characters to be matched
            if (!isspace(*format))
コード例 #6
0
Env_var* new_Env_var_from_string(Streader* sr)
{
    rassert(sr != NULL);

    if (Streader_is_error_set(sr))
        return NULL;

    char type_name[16] = "";
    char name[KQT_VAR_NAME_MAX] = "";

    if (!Streader_readf(
                sr,
                "[%s,%s,",
                READF_STR(16, type_name),
                READF_STR(KQT_VAR_NAME_MAX, name)))
        return NULL;

    if (!is_valid_var_name(name))
    {
        Streader_set_error(
                sr,
                "Illegal variable name %s"
                    " (Variable names may only contain"
                    " lower-case letters and underscores"
                    " (and digits as other than first characters))",
                name);
        return NULL;
    }

    Value* value = VALUE_AUTO;

    if (string_eq(type_name, "bool"))
    {
        value->type = VALUE_TYPE_BOOL;
        Streader_read_bool(sr, &value->value.bool_type);
    }
    else if (string_eq(type_name, "int"))
    {
        value->type = VALUE_TYPE_INT;
        Streader_read_int(sr, &value->value.int_type);
    }
    else if (string_eq(type_name, "float"))
    {
        value->type = VALUE_TYPE_FLOAT;
        Streader_read_float(sr, &value->value.float_type);
    }
    else if (string_eq(type_name, "timestamp"))
    {
        value->type = VALUE_TYPE_TSTAMP;
        Streader_read_tstamp(sr, &value->value.Tstamp_type);
    }
    else
    {
        Streader_set_error(
                sr,
                "Invalid type of environment variable %s: %s",
                name,
                type_name);
        return NULL;
    }

    if (!Streader_match_char(sr, ']'))
        return NULL;

    Env_var* var = new_Env_var(value->type, name);
    if (var == NULL)
    {
        Streader_set_memory_error(
                sr, "Could not allocate memory for environment variable");
        return NULL;
    }

    Env_var_set_value(var, value);

    return var;
}
コード例 #7
0
ファイル: Note_map.c プロジェクト: cyberixae/kunquat
static bool read_mapping(Streader* sr, int32_t index, void* userdata)
{
    assert(sr != NULL);
    (void)index;
    assert(userdata != NULL);

    Note_map* map = userdata;

    Random_list* list = memory_alloc_item(Random_list);
    if (list == NULL)
    {
        Streader_set_memory_error(
                sr, "Could not allocate memory for note map entry");
        return false;
    }

    double cents = NAN;
    double force = NAN;

    if (!Streader_readf(sr, "[[%f,%f],", &cents, &force))
    {
        memory_free(list);
        return false;
    }

    if (!isfinite(cents))
    {
        Streader_set_error(sr, "Mapping cents is not finite");
        memory_free(list);
        return false;
    }

    if (!isfinite(force))
    {
        Streader_set_error(sr, "Mapping force is not finite");
        memory_free(list);
        return false;
    }

    list->freq = exp2(cents / 1200) * 440;
    list->cents = cents;
    list->force = force;
    list->entry_count = 0;
    if (!AAtree_ins(map->map, list))
    {
        Streader_set_memory_error(
                sr, "Couldn't allocate memory for note map entry");
        memory_free(list);
        return false;
    }

    if (!Streader_read_list(sr, read_random_list_entry, list))
        return false;

    if (list->entry_count == 0)
    {
        Streader_set_error(sr, "Empty note mapping random list");
        return false;
    }

    return Streader_match_char(sr, ']');
}
コード例 #8
0
static bool read_mapping(Streader* sr, int32_t index, void* userdata)
{
    rassert(sr != NULL);
    ignore(index);
    rassert(userdata != NULL);

    Hit_map* map = userdata;

    Random_list* list = memory_alloc_item(Random_list);
    if (list == NULL)
    {
        del_Hit_map(map);
        Streader_set_memory_error(
                sr, "Could not allocate memory for hit map random list");
        return false;
    }

    int64_t hit_index = -1;
    double force = NAN;

    if (!Streader_readf(sr, "[[%i,%f],", &hit_index, &force))
    {
        memory_free(list);
        return false;
    }

    if (hit_index < 0 || hit_index >= KQT_HITS_MAX)
    {
        Streader_set_error(
                sr,
                "Mapping hit index is outside range [0, %d)",
                KQT_HITS_MAX);
        memory_free(list);
        return false;
    }

    if (!isfinite(force))
    {
        Streader_set_error(
                sr,
                "Mapping force is not finite",
                KQT_HITS_MAX);
        memory_free(list);
        return false;
    }

    if (map->hits[hit_index] == NULL)
    {
        map->hits[hit_index] = new_AAtree(
                (AAtree_item_cmp*)Random_list_cmp, (AAtree_item_destroy*)memory_free);
        if (map->hits[hit_index] == NULL)
        {
            Streader_set_memory_error(
                    sr, "Could not allocate memory for hit map");
            memory_free(list);
            return false;
        }
    }

    list->force = force;
    list->entry_count = 0;
    if (AAtree_contains(map->hits[hit_index], list))
    {
        Streader_set_error(
                sr,
                "Duplicate hit map entry with hit index %" PRId64 ", force %.2f",
                hit_index,
                force);
        memory_free(list);
        return false;
    }
    if (!AAtree_ins(map->hits[hit_index], list))
    {
        Streader_set_memory_error(
                sr, "Could not allocate memory for hit map random list");
        memory_free(list);
        return false;
    }

    if (!Streader_read_list(sr, read_random_list_entry, list))
        return false;

    return Streader_match_char(sr, ']');
}