efl/src/lib/eolian/database_expr_api.c

272 lines
8.1 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include "eolian_database.h"
EAPI Eolian_Value
eolian_expression_eval(const Eolian_Expression *expr, Eolian_Expression_Mask m)
{
Eolian_Value err;
err.type = EOLIAN_EXPR_UNKNOWN;
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, err);
return database_expr_eval(NULL, (Eolian_Expression *)expr, m, NULL, NULL);
}
static void
_append_char_escaped(Eina_Strbuf *buf, char c)
{
switch (c)
{
case '\'': eina_strbuf_append(buf, "\\\'"); break;
case '\"': eina_strbuf_append(buf, "\\\""); break;
case '\?': eina_strbuf_append(buf, "\\\?"); break;
case '\\': eina_strbuf_append(buf, "\\\\"); break;
case '\a': eina_strbuf_append(buf, "\\a"); break;
case '\b': eina_strbuf_append(buf, "\\b"); break;
case '\f': eina_strbuf_append(buf, "\\f"); break;
case '\n': eina_strbuf_append(buf, "\\n"); break;
case '\r': eina_strbuf_append(buf, "\\r"); break;
case '\t': eina_strbuf_append(buf, "\\t"); break;
case '\v': eina_strbuf_append(buf, "\\v"); break;
default:
if ((c < 32) || (c > 126))
eina_strbuf_append_printf(buf, "\\x%X", (unsigned char)c);
else
eina_strbuf_append_char(buf, c);
break;
}
}
static void
_number_to_str(const Eolian_Value *v, Eina_Strbuf *buf)
{
switch (v->type)
{
case EOLIAN_EXPR_INT:
eina_strbuf_append_printf(buf, "%d", v->value.i); break;
case EOLIAN_EXPR_UINT:
eina_strbuf_append_printf(buf, "%uU", v->value.u); break;
case EOLIAN_EXPR_LONG:
eina_strbuf_append_printf(buf, "%ldL", v->value.l); break;
case EOLIAN_EXPR_ULONG:
eina_strbuf_append_printf(buf, "%luUL", v->value.ul); break;
case EOLIAN_EXPR_LLONG:
eina_strbuf_append_printf(buf, "%ldLL", (long)v->value.ll); break;
case EOLIAN_EXPR_ULLONG:
eina_strbuf_append_printf(buf, "%luULL", (unsigned long)v->value.ull);
break;
case EOLIAN_EXPR_FLOAT:
eina_strbuf_append_printf(buf, "%ff", v->value.f); break;
case EOLIAN_EXPR_DOUBLE:
eina_strbuf_append_printf(buf, "%f", v->value.d); break;
default:
break;
}
}
EAPI Eina_Stringshare *
eolian_expression_value_to_literal(const Eolian_Value *val)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(val, NULL);
switch (val->type)
{
case EOLIAN_EXPR_BOOL:
return eina_stringshare_add(val->value.b ? "EINA_TRUE"
: "EINA_FALSE");
case EOLIAN_EXPR_NULL:
return eina_stringshare_add("NULL");
case EOLIAN_EXPR_CHAR:
{
char c = val->value.c;
Eina_Strbuf *buf = eina_strbuf_new();
const char *ret;
eina_strbuf_append_char(buf, '\'');
_append_char_escaped(buf, c);
eina_strbuf_append_char(buf, '\'');
ret = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
return ret;
}
case EOLIAN_EXPR_STRING:
{
const char *ret;
char *c = (char*)val->value.s;
Eina_Strbuf *buf = eina_strbuf_new();
eina_strbuf_append_char(buf, '\"');
while (*c) _append_char_escaped(buf, *(c++));
eina_strbuf_append_char(buf, '\"');
ret = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
return ret;
}
case EOLIAN_EXPR_INT:
case EOLIAN_EXPR_UINT:
case EOLIAN_EXPR_LONG:
case EOLIAN_EXPR_ULONG:
case EOLIAN_EXPR_LLONG:
case EOLIAN_EXPR_ULLONG:
case EOLIAN_EXPR_FLOAT:
case EOLIAN_EXPR_DOUBLE:
{
const char *ret;
Eina_Strbuf *buf = eina_strbuf_new();
_number_to_str(val, buf);
ret = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
return ret;
}
default:
return NULL;
}
}
static const char *_binops[] = {
"+", "-", "*", "/", "%",
"==", "!=", ">", "<", ">=", "<=",
"&&", "||",
"&", "|", "^", "<<", ">>"
};
static const char *_unops[] = {
"-", "+", "!", "~"
};
static Eina_Bool
_expr_serialize(const Eolian_Expression *expr, Eina_Strbuf *buf, Eina_Bool outer)
{
switch (expr->type)
{
case EOLIAN_EXPR_UNKNOWN:
return EINA_FALSE;
case EOLIAN_EXPR_INT:
case EOLIAN_EXPR_UINT:
case EOLIAN_EXPR_LONG:
case EOLIAN_EXPR_ULONG:
case EOLIAN_EXPR_LLONG:
case EOLIAN_EXPR_ULLONG:
case EOLIAN_EXPR_FLOAT:
case EOLIAN_EXPR_DOUBLE:
case EOLIAN_EXPR_STRING:
case EOLIAN_EXPR_CHAR:
{
Eolian_Value v;
v.type = expr->type;
v.value = expr->value;
const char *x = eolian_expression_value_to_literal(&v);
if (!x)
return EINA_FALSE;
eina_strbuf_append(buf, x);
eina_stringshare_del(x);
break;
}
case EOLIAN_EXPR_NULL:
eina_strbuf_append(buf, "null");
break;
case EOLIAN_EXPR_BOOL:
eina_strbuf_append(buf, expr->value.b ? "true" : "false");
break;
case EOLIAN_EXPR_NAME:
{
eina_strbuf_append(buf, expr->value.s);
break;
}
case EOLIAN_EXPR_UNARY:
eina_strbuf_append(buf, _unops[expr->unop]);
_expr_serialize(expr->expr, buf, EINA_FALSE);
break;
case EOLIAN_EXPR_BINARY:
if (!outer)
eina_strbuf_append_char(buf, '(');
_expr_serialize(expr->lhs, buf, EINA_FALSE);
eina_strbuf_append_printf(buf, " %s ", _binops[expr->binop]);
_expr_serialize(expr->rhs, buf, EINA_FALSE);
if (!outer)
eina_strbuf_append_char(buf, ')');
break;
default:
return EINA_FALSE;
}
return EINA_TRUE;
}
EAPI Eina_Stringshare *
eolian_expression_serialize(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, NULL);
Eina_Strbuf *buf = eina_strbuf_new();
if (!_expr_serialize(expr, buf, EINA_TRUE))
{
eina_strbuf_free(buf);
return NULL;
}
const char *ret = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
return ret;
}
EAPI Eolian_Expression_Type
eolian_expression_type_get(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, EOLIAN_EXPR_UNKNOWN);
return expr->type;
}
EAPI Eolian_Binary_Operator
eolian_expression_binary_operator_get(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, EOLIAN_BINOP_INVALID);
EINA_SAFETY_ON_FALSE_RETURN_VAL(expr->type == EOLIAN_EXPR_BINARY,
EOLIAN_BINOP_INVALID);
return expr->binop;
}
EAPI const Eolian_Expression *
eolian_expression_binary_lhs_get(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(expr->type == EOLIAN_EXPR_BINARY, NULL);
return expr->lhs;
}
EAPI const Eolian_Expression *
eolian_expression_binary_rhs_get(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(expr->type == EOLIAN_EXPR_BINARY, NULL);
return expr->rhs;
}
EAPI Eolian_Unary_Operator
eolian_expression_unary_operator_get(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, EOLIAN_UNOP_INVALID);
EINA_SAFETY_ON_FALSE_RETURN_VAL(expr->type == EOLIAN_EXPR_UNARY,
EOLIAN_UNOP_INVALID);
return expr->unop;
}
EAPI const Eolian_Expression *
eolian_expression_unary_expression_get(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(expr->type == EOLIAN_EXPR_UNARY, NULL);
return expr->expr;
}
EAPI Eolian_Value
eolian_expression_value_get(const Eolian_Expression *expr)
{
Eolian_Value v;
v.type = EOLIAN_EXPR_UNKNOWN;
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, v);
EINA_SAFETY_ON_FALSE_RETURN_VAL(expr->type != EOLIAN_EXPR_UNKNOWN
&& expr->type != EOLIAN_EXPR_BINARY
&& expr->type != EOLIAN_EXPR_UNARY, v);
v.type = expr->type;
v.value = expr->value;
return v;
}