예제 #1
0
파일: object.c 프로젝트: xiaq/hlwm
int hsattribute_assign(HSAttribute* attr, char* new_value_str, GString* output) {
    if (attr->on_change == ATTR_READ_ONLY) {
        g_string_append_printf(output,
            "Can not write read-only attribute \"%s\"\n",
            attr->name);
        return HERBST_FORBIDDEN;
    }

    bool error = false;
    union {
        bool        b;
        int         i;
        unsigned int u;
        GString*    str;
    } new_value, old_value;
    bool nothing_to_do = false;

#define ATTR_DO_ASSIGN_COMPARE(NAME,MEM) \
        do { \
            if (error) { \
                g_string_append_printf(output, \
                                       "Can not parse "NAME" from \"%s\"", \
                                       new_value_str); \
            } \
            old_value.MEM = *attr->value.MEM; \
            if (old_value.MEM == new_value.MEM) { \
                nothing_to_do = true; \
            } else { \
                *attr->value.MEM = new_value.MEM; \
            } \
        } while (0);

    // change the value and backup the old value
    switch (attr->type) {
        case HSATTR_TYPE_BOOL:
            new_value.b = string_to_bool_error(new_value_str,
                                             *attr->value.b,
                                             &error);
            ATTR_DO_ASSIGN_COMPARE("boolean", b);
            break;

        case HSATTR_TYPE_INT:
            error = (1 != sscanf(new_value_str, "%d", &new_value.i));
            ATTR_DO_ASSIGN_COMPARE("integer", i);
            break;

        case HSATTR_TYPE_UINT:
            error = (1 != sscanf(new_value_str, "%u", &new_value.u));
            ATTR_DO_ASSIGN_COMPARE("unsigned integer", u);
            break;


        case HSATTR_TYPE_STRING:
            if (!strcmp(new_value_str, (*attr->value.str)->str)) {
                nothing_to_do = true;
            } else {
                old_value.str = g_string_new((*attr->value.str)->str);
                g_string_assign(*attr->value.str, new_value_str);
            }
            break;
        case HSATTR_TYPE_CUSTOM: break;
        case HSATTR_TYPE_CUSTOM_INT: break;
    }
    if (nothing_to_do) {
        return 0;
    }

    // ask the attribute about the change
    GString* errormsg = attr->on_change(attr);
    int exit_status = 0;
    if (errormsg && errormsg->len > 0) {
        exit_status = HERBST_INVALID_ARGUMENT;
        // print the message
        if (errormsg->str[errormsg->len - 1] == '\n') {
            g_string_truncate(errormsg, errormsg->len - 1);
        }
        g_string_append_printf(output,
            "Can not write attribute \"%s\": %s\n",
            attr->name,
            errormsg->str);
        g_string_free(errormsg, true);
        // restore old value
        switch (attr->type) {
            case HSATTR_TYPE_BOOL: *attr->value.b = old_value.b; break;
            case HSATTR_TYPE_INT:  *attr->value.i = old_value.i; break;
            case HSATTR_TYPE_UINT: *attr->value.u = old_value.u; break;
            case HSATTR_TYPE_STRING:
                g_string_assign(*attr->value.str, old_value.str->str);
                break;
            case HSATTR_TYPE_CUSTOM: break;
            case HSATTR_TYPE_CUSTOM_INT: break;
        }
    }
    // free old_value
    switch (attr->type) {
        case HSATTR_TYPE_BOOL: break;
        case HSATTR_TYPE_INT:  break;
        case HSATTR_TYPE_UINT:  break;
        case HSATTR_TYPE_STRING:
            g_string_free(old_value.str, true);
            break;
        case HSATTR_TYPE_CUSTOM: break;
        case HSATTR_TYPE_CUSTOM_INT: break;
    }
    return exit_status;
}
예제 #2
0
파일: object.c 프로젝트: xiaq/hlwm
int compare_command(int argc, char* argv[], GString* output) {
    // usage: compare attribute operator constant
    if (argc < 4) {
        return HERBST_NEED_MORE_ARGS;
    }
    HSAttribute* attr = hsattribute_parse_path_verbose(argv[1], output);
    if (!attr) {
        return HERBST_INVALID_ARGUMENT;
    }
    char* op = argv[2];
    char* rvalue = argv[3];
    if (attr->type == HSATTR_TYPE_INT
        || attr->type == HSATTR_TYPE_UINT
        || attr->type == HSATTR_TYPE_CUSTOM_INT)
    {
        long long l;
        long long r;
        if (1 != sscanf(rvalue, "%lld", &r)) {
            g_string_append_printf(output,
                                   "Can not parse integer from \"%s\"\n",
                                   rvalue);
            return HERBST_INVALID_ARGUMENT;
        }
        switch (attr->type) {
            case HSATTR_TYPE_INT:  l = *attr->value.i; break;
            case HSATTR_TYPE_UINT: l = *attr->value.u; break;
            case HSATTR_TYPE_CUSTOM_INT:
                l = attr->value.custom_int(attr->object->data);
                break;
            default: break;
        }
        struct {
            char* name;
            bool  result;
        } eval[] = {
            { "=",  l == r  },
            { "!=", l != r  },
            { "le", l <= r  },
            { "lt", l <  r  },
            { "ge", l >= r  },
            { "gt", l >  r  },
        };
        int result = -1;
        for (int i = 0; i < LENGTH(eval); i++) {
            if (!strcmp(eval[i].name, op)) {
                result = !eval[i].result; // make false -> 1, true -> 0
            }
        }
        if (result == -1) {
            g_string_append_printf(output, "Invalid operator \"%s\"", op);
            result = HERBST_INVALID_ARGUMENT;
        }
        return result;
    } else if (attr->type == HSATTR_TYPE_BOOL) {
        bool l = *attr->value.b;
        bool error = false;
        bool r = string_to_bool_error(rvalue, l, &error);
        if (error) {
            g_string_append_printf(output, "Can not parse boolean from \"%s\"\n", rvalue);
            return HERBST_INVALID_ARGUMENT;
        }
        if (!strcmp("=", op)) return !(l == r);
        if (!strcmp("!=", op)) return !(l != r);
        g_string_append_printf(output, "Invalid boolean operator \"%s\"", op);
        return HERBST_INVALID_ARGUMENT;
    } else { // STRING or CUSTOM
        GString* l;
        bool free_l = false;
        if (attr->type == HSATTR_TYPE_STRING) {
            l = *attr->value.str;
        } else { // TYPE == CUSTOM
            l = g_string_new("");
            attr->value.custom(attr->object->data, l);
            free_l = true;
        }
        bool equals = !strcmp(l->str, rvalue);
        int status;
        if (!strcmp("=", op)) status = !equals;
        else if (!strcmp("!=", op)) status = equals;
        else status = -1;
        if (free_l) {
            g_string_free(l, true);
        }
        if (status == -1) {
            g_string_append_printf(output, "Invalid string operator \"%s\"", op);
            return HERBST_INVALID_ARGUMENT;
        }
        return status;
    }
}
예제 #3
0
bool string_to_bool(const char* string, bool oldvalue) {
    return string_to_bool_error(string, oldvalue, NULL);
}