Esempio n. 1
0
int string_extract_index(
        const char* path, const char* prefix, int digits, const char* after)
{
    rassert(path != NULL);
    rassert(digits > 0);

    if (!string_has_prefix(path, prefix))
        return -1;

    static const char hex_digits[] = "0123456789abcdef";
    int prefix_len = 0;
    if (prefix != NULL)
    {
        prefix_len = (int)strlen(prefix);
    }
    else
    {
        prefix_len = (int)strcspn(path, hex_digits);
        if (path[prefix_len] == '\0')
            return -1;
    }

    const char* num_s = path + prefix_len;
    int index = 0;
    for (int i = 0; i < digits; ++i, ++num_s)
    {
        index *= 0x10;

        if (*num_s == '\0')
            return -1;

        char* pos = strchr(hex_digits, *num_s);
        if (pos == NULL)
            return -1;

        index += (int)(pos - hex_digits);
    }

    if (string_has_prefix(after, ".") && !string_eq(num_s, after))
        return -1;
    else if ((after != NULL) && string_eq(after, "") && !string_eq(num_s, ""))
        return -1;
    else if (!string_has_prefix(num_s, after))
        return -1;

    return index;
}
Esempio n. 2
0
bool Device_set_state_key(
        const Device* device,
        Device_states* dstates,
        const char* key)
{
    assert(device != NULL);
    assert(dstates != NULL);
    assert(key != NULL);
    assert(string_has_prefix(key, "i/") || string_has_prefix(key, "c/"));

    if (device->dimpl != NULL)
    {
        Device_state* dstate = Device_states_get_state(
                dstates, Device_get_id(device));
        return Device_impl_set_state_key(device->dimpl, dstate, key + 2);
    }

    return true;
}
Esempio n. 3
0
bool Device_set_key(Device* device, const char* key, Streader* sr)
{
    assert(device != NULL);
    assert(key != NULL);
    assert(string_has_prefix(key, "i/") || string_has_prefix(key, "c/"));
    assert(sr != NULL);

    if (Streader_is_error_set(sr))
        return false;

    if (!Device_params_parse_value(device->dparams, key, sr))
        return false;

    if (device->dimpl != NULL && !Device_impl_set_key(device->dimpl, key + 2))
    {
        Streader_set_memory_error(
                sr, "Could not allocate memory for device key %s", key);
        return false;
    }

    return true;
}
Esempio n. 4
0
static int validate_connection_path(
        Streader* sr, char* str, Connection_level level, Device_port_type type)
{
    rassert(sr != NULL);
    rassert(str != NULL);
    rassert(type < DEVICE_PORT_TYPES);

    if (Streader_is_error_set(sr))
        return -1;

    bool root = true;
    char* path = str;
    char* trim_point = str;

    // Device
    if (string_has_prefix(str, "au_"))
    {
        // TODO: disallow audio unit in more than 2 levels
        if ((level != CONNECTION_LEVEL_GLOBAL) && (level != CONNECTION_LEVEL_AU))
        {
            Streader_set_error(
                    sr,
                    "Audio unit directory in a deep-level connection: \"%s\"",
                    path);
            return -1;
        }

        root = false;
        str += strlen("au_");
        if (read_index(str) >= KQT_AUDIO_UNITS_MAX)
        {
            Streader_set_error(
                    sr,
                    "Invalid audio unit number in the connection: \"%s\"",
                    path);
            return -1;
        }

        str += 2;
        if (!string_has_prefix(str, "/"))
        {
            Streader_set_error(
                    sr,
                    "Missing trailing '/' after the audio unit number"
                        " in the connection: \"%s\"",
                    path);
            return -1;
        }

        ++str;
        trim_point = str - 1;
    }
    else if (string_has_prefix(str, "proc_"))
    {
        if (level != CONNECTION_LEVEL_AU)
        {
            Streader_set_error(
                    sr,
                    "Processor directory in a root-level connection: \"%s\"",
                    path);
            return -1;
        }

        root = false;
        str += strlen("proc_");
        if (read_index(str) >= KQT_PROCESSORS_MAX)
        {
            Streader_set_error(
                    sr,
                    "Invalid processor number in the connection: \"%s\"",
                    path);
            return -1;
        }

        str += 2;
        if (!string_has_prefix(str, "/"))
        {
            Streader_set_error(
                    sr,
                    "Missing trailing '/' after the processor number"
                        " in the connection: \"%s\"",
                    path);
            return -1;
        }

        ++str;
        if (!string_has_prefix(str, "C/"))
        {
            Streader_set_error(
                    sr,
                    "Invalid processor parameter directory"
                        " in the connection: \"%s\"",
                    path);
            return -1;
        }

        str += strlen("C/");
        trim_point = str - 1;
    }

    // Port
    if (string_has_prefix(str, "in_") || string_has_prefix(str, "out_"))
    {
        if (string_has_prefix(str, "in_") &&
                root &&
                (level != CONNECTION_LEVEL_AU))
        {
            Streader_set_error(
                    sr, "Input ports are not allowed for master: \"%s\"", path);
            return -1;
        }

        if (type == DEVICE_PORT_TYPE_RECV)
        {
            bool can_receive = (!root && string_has_prefix(str, "in_")) ||
                               (root && string_has_prefix(str, "out_"));
            if (!can_receive)
            {
                Streader_set_error(
                        sr,
                        "Destination port is not for receiving data: \"%s\"",
                        path);
                return -1;
            }
        }
        else
        {
            rassert(type == DEVICE_PORT_TYPE_SEND);
            bool can_send = (string_has_prefix(str, "out_") && !root) ||
                            (string_has_prefix(str, "in_") && root);
            if (!can_send)
            {
                Streader_set_error(
                        sr,
                        "Source port is not for sending data: \"%s\"",
                        path);
                return -1;
            }
        }

        str += strcspn(str, "_") + 1;
        int port = read_index(str);
        if (port >= KQT_DEVICE_PORTS_MAX)
        {
            Streader_set_error(sr, "Invalid port number: \"%s\"", path);
            return -1;
        }

        str += 2;
        if (str[0] != '/' && str[0] != '\0' && str[1] != '\0')
        {
            Streader_set_error(
                    sr,
                    "Connection path contains garbage"
                        " after the port specification: \"%s\"",
                    path);
            return -1;
        }

        *trim_point = '\0';
        return port;
    }

    Streader_set_error(sr, "Invalid connection: \"%s\"", path);

    return -1;
}