示例#1
0
文件: streader.c 项目: kagu/kunquat
END_TEST


START_TEST(Whitespace_terminates_decimal_number)
{
    Streader* sr = init_with_cstr("- 1");
    double num = NAN;
    fail_if(Streader_read_float(sr, &num),
            "Streader accepted \"- 1\" as a float");

    sr = init_with_cstr("-1 .5");
    num = NAN;
    fail_if(!Streader_read_float(sr, &num),
            "Could not read float from \"-1 .5\": %s",
            Streader_get_error_desc(sr));
    fail_if(num != -1, "Streader read %f instead of -1 from \"-1 .5\"", num);

    sr = init_with_cstr("-1. 5");
    num = NAN;
    fail_if(Streader_read_float(sr, &num),
            "Streader accepted \"-1.\" as a float");

    sr = init_with_cstr("-1 e5");
    num = NAN;
    fail_if(!Streader_read_float(sr, &num),
            "Could not read float from \"-1 e5\": %s",
            Streader_get_error_desc(sr));
    fail_if(num != -1, "Streader read %f instead of -1 from \"-1 e5\"", num);

    sr = init_with_cstr("-1e 5");
    num = NAN;
    fail_if(Streader_read_float(sr, &num),
            "Streader accepted \"-1e\" as a float");
}
示例#2
0
文件: streader.c 项目: kagu/kunquat
END_TEST


START_TEST(Read_zero_float)
{
    const char* zeros[] =
    {
        "0 x",
        "0.0 x",
        "0e0 x",
        "0.0e0 x",
        "0.0e+0 x",
        "0.0e-0 x",
    };

    for (size_t i = 0; i < arr_size(zeros); ++i)
    {
        Streader* sr = init_with_cstr(zeros[i]);
        double num = NAN;
        fail_if(!Streader_read_float(sr, &num),
                "Could not read 0 from \"%s\": %s",
                zeros[i], Streader_get_error_desc(sr));
        fail_if(num != 0,
                "Streader stored %f instead of 0 from \"%s\"",
                num, zeros[i]);
        fail_if(!Streader_match_char(sr, 'x'),
                "Streader did not consume 0 from \"%s\" correctly: %s",
                zeros[i], Streader_get_error_desc(sr));
    }

    // TODO: The code below does not test the sign of negative zero
    //       as C99 doesn't guarantee it.
    //       Revisit when migrating to emulated floats.

    const char* neg_zeros[] =
    {
        "-0 x",
        "-0.0 x",
        "-0e0 x",
        "-0.0e0 x",
        "-0.0e+0 x",
        "-0.0e-0 x",
    };

    for (size_t i = 0; i < arr_size(neg_zeros); ++i)
    {
        Streader* sr = init_with_cstr(neg_zeros[i]);
        double num = NAN;
        fail_if(!Streader_read_float(sr, &num),
                "Could not read -0 from \"%s\": %s",
                neg_zeros[i], Streader_get_error_desc(sr));
        fail_if(num != 0,
                "Streader stored %f instead of -0 from \"%s\"",
                num, neg_zeros[i]);
        fail_if(!Streader_match_char(sr, 'x'),
                "Streader did not consume -0 from \"%s\" correctly",
                neg_zeros[i]);
    }
}
示例#3
0
文件: Module.c 项目: kagu/kunquat
bool Module_read_force_shift(Module* module, Streader* sr)
{
    rassert(module != NULL);
    rassert(sr != NULL);

    if (Streader_is_error_set(sr))
        return false;

    double shift = 0;

    if (Streader_has_data(sr))
    {
        if (!Streader_read_float(sr, &shift))
            return false;

        if (!isfinite(shift) || (shift < -60) || (shift > 0))
        {
            Streader_set_error(sr, "Invalid force shift: %.4f", shift);
            return false;
        }
    }

    module->force_shift = shift;

    return true;
}
示例#4
0
文件: Module.c 项目: kagu/kunquat
bool Module_read_mixing_volume(Module* module, Streader* sr)
{
    rassert(module != NULL);
    rassert(sr != NULL);

    if (Streader_is_error_set(sr))
        return false;

    double mix_vol = COMP_DEFAULT_MIX_VOL;

    if (Streader_has_data(sr))
    {
        if (!Streader_read_float(sr, &mix_vol))
            return false;

        if (!isfinite(mix_vol) && mix_vol != -INFINITY)
        {
            Streader_set_error(sr, "Invalid mixing volume: %.4f", mix_vol);
            return false;
        }
    }

    module->mix_vol_dB = mix_vol;
    module->mix_vol = exp2(module->mix_vol_dB / 6);

    return true;
}
示例#5
0
bool Streader_read_finite_rt(Streader* sr, Value* dest)
{
    rassert(sr != NULL);

    if (Streader_is_error_set(sr))
        return false;

    Streader_skip_whitespace(sr);
    const int64_t start_pos = sr->pos;

    Value* value = VALUE_AUTO;

    if (Streader_read_bool(sr, &value->value.bool_type))
        value->type = VALUE_TYPE_BOOL;
    else if ((recover(sr, start_pos), Streader_read_int(sr, &value->value.int_type)) &&
            (CUR_CH != '.') && (CUR_CH != 'e') && (CUR_CH != 'E'))
        value->type = VALUE_TYPE_INT;
    else if (recover(sr, start_pos),
            (Streader_read_float(sr, &value->value.float_type) &&
             isfinite(value->value.float_type)))
        value->type = VALUE_TYPE_FLOAT;
    else if (recover(sr, start_pos), Streader_read_tstamp(sr, &value->value.Tstamp_type))
        value->type = VALUE_TYPE_TSTAMP;

    if (value->type == VALUE_TYPE_NONE)
        return false;

    if (dest != NULL)
        Value_copy(dest, value);

    return true;
}
示例#6
0
文件: streader.c 项目: kagu/kunquat
END_TEST


START_TEST(Read_nonzero_float)
{
    const double nums[] = { 0.5, 1.0, 1.5, -0.5, -1.0, -1.5, 0.0625, 10.0, };
    const char* formats[] =
    {
        "%.4f x",
        "%f x",
        "%e x",
    };

    for (size_t i = 0; i < arr_size(nums); ++i)
    {
        for (size_t k = 0; k < arr_size(formats); ++k)
        {
            char data[128] = "";
            sprintf(data, formats[k], nums[i]);

            Streader* sr = init_with_cstr(data);
            double num = NAN;
            fail_if(!Streader_read_float(sr, &num),
                    "Could not read float from \"%s\": %s",
                    data, Streader_get_error_desc(sr));
            fail_if(num != nums[i],
                    "Streader stored %f instead of %.6f from \"%s\"",
                    num, nums[i]);
            fail_if(!Streader_match_char(sr, 'x'),
                    "Streader did not consume float from \"%s\" correctly",
                    data);
        }
    }
}
示例#7
0
static bool Streader_read_tuning(Streader* sr, double* cents)
{
    rassert(sr != NULL);
    rassert(cents != NULL);

    if (Streader_is_error_set(sr))
        return false;

    if (Streader_try_match_char(sr, '['))
    {
        int64_t num = 0;
        int64_t den = 0;
        if (!Streader_readf(sr, "%i,%i]", &num, &den))
            return false;

        if (num <= 0)
        {
            Streader_set_error(sr, "Numerator must be positive");
            return false;
        }
        if (den <= 0)
        {
            Streader_set_error(sr, "Denominator must be positive");
            return false;
        }

        *cents = log2((double)num / (double)den) * 1200;
    }
    else
    {
        if (!Streader_read_float(sr, cents))
            return false;

        if (!isfinite(*cents))
        {
            Streader_set_error(sr, "Cents value must be finite");
            return false;
        }
    }

    return true;
}
示例#8
0
文件: streader.c 项目: kagu/kunquat
END_TEST


static bool fail_at_key_2(Streader* sr, const char* key, void* userdata)
{
    (void)sr;
    (void)userdata;

    fail_if(strcmp(key, "2") > 0,
            "Dictionary processing continued after failure");

    if (strcmp(key, "2") == 0)
        return false;

    fail_if(!Streader_read_float(sr, NULL),
            "Could not read a float from dictionary: %s",
            Streader_get_error_desc(sr));

    return true;
}
示例#9
0
文件: Num_list.c 项目: kagu/kunquat
static bool read_num(Streader* sr, int32_t index, void* userdata)
{
    rassert(sr != NULL);
    ignore(index);
    rassert(userdata != NULL);

    Num_list* nl = userdata;

    double num = NAN;
    if (!Streader_read_float(sr, &num))
        return false;

    if (!Num_list_append(nl, num))
    {
        del_Num_list(nl);
        Streader_set_memory_error(
            sr, "Could not allocate memory for number list");
        return false;
    }

    return true;
}
示例#10
0
static bool read_tuning_table_item(Streader* sr, const char* key, void* userdata)
{
    rassert(sr != NULL);
    rassert(key != NULL);
    rassert(userdata != NULL);

    Tuning_table* tt = userdata;

    if (string_eq(key, "ref_note"))
    {
        int64_t num = 0;
        if (!Streader_read_int(sr, &num))
            return false;

        if (num < 0 || num >= KQT_TUNING_TABLE_NOTES_MAX)
        {
            Streader_set_error(
                     sr, "Invalid reference note number: %" PRId64, num);
            return false;
        }

        tt->ref_note = (int)num;
    }
    else if (string_eq(key, "ref_pitch"))
    {
        double num = NAN;
        if (!Streader_read_float(sr, &num))
            return false;

        if (!isfinite(num))
        {
            Streader_set_error(sr, "Invalid reference pitch: %f", num);
            return false;
        }

        tt->ref_pitch = num;
    }
    else if (string_eq(key, "pitch_offset"))
    {
        double cents = NAN;
        if (!Streader_read_float(sr, &cents))
            return false;

        if (!isfinite(cents))
        {
            Streader_set_error(sr, "Pitch offset is not finite");
            return false;
        }

        tt->global_offset = cents;
    }
    else if (string_eq(key, "octave_width"))
    {
        double cents = NAN;
        if (!Streader_read_tuning(sr, &cents))
            return false;

        if (cents <= 0)
        {
            Streader_set_error(sr, "Octave width must be positive");
            return false;
        }

        Tuning_table_set_octave_width(tt, cents);
    }
    else if (string_eq(key, "centre_octave"))
    {
        int64_t octave = -1;
        if (!Streader_read_int(sr, &octave))
            return false;

        if (octave < 0 || octave >= KQT_TUNING_TABLE_OCTAVES)
        {
            Streader_set_error(sr, "Invalid centre octave: %" PRId64, octave);
            return false;
        }

        tt->centre_octave = (int)octave;
        Tuning_table_set_octave_width(tt, tt->octave_width);
    }
    else if (string_eq(key, "notes"))
    {
        for (int i = 0; i < KQT_TUNING_TABLE_NOTES_MAX; ++i)
            tt->note_offsets[i] = NAN;

        if (!Streader_read_list(sr, read_note, tt))
            return false;
    }
    else
    {
        Streader_set_error(sr, "Unrecognised key in tuning table: %s", key);
        return false;
    }

    return true;
}
示例#11
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))
示例#12
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;
}