src/server/util/object.c

changeset 423
bb7cff720dd0
parent 421
437562f5681d
child 424
3df9258cd3cc
--- a/src/server/util/object.c	Wed Nov 09 11:51:19 2022 +0100
+++ b/src/server/util/object.c	Sat Nov 12 11:01:11 2022 +0100
@@ -27,11 +27,13 @@
  */
 
 #include <cx/string.h>
+#include <cx/linked_list.h>
+#include <cx/compare.h>
 
 #include "../public/nsapi.h"
 
 #include "object.h"
-
+#include "util.h"
 #include "pool.h"
 #include "../daemon/func.h"
 
@@ -106,6 +108,281 @@
     context->last_req_code = REQ_NOACTION;
 }
 
+
+/* ------------------------------ Expression ------------------------------ */
+
+Expression* condition_create(pool_handle_t *pool, CxList *tokens) {
+    
+    
+    
+    return NULL;
+}
+
+
+typedef struct {
+  pool_handle_t *pool;
+  CxList *op_stack;
+  CxList *ex_stack;
+  CxList *tokens;
+  size_t *pos;
+  int    expect_value;
+} ExprParser;
+
+typedef struct {
+    NSAPIExpressionOperator operator;
+    int expect_value;
+    int open_parenthesis;
+} ExprOpStackItem;
+
+static void expr_free(pool_handle_t *pool, NSAPIExpression *expr) {
+    if(expr->left) {
+        expr_free(pool, expr->left);
+    }
+    if(expr->right) {
+        expr_free(pool, expr->right);
+    }
+    if(expr->type == NSAPI_EXPRESSION_STRING && expr->value.str.ptr) {
+        pool_free(pool, (char*)expr->value.str.ptr);
+    } else if(expr->type == NSAPI_EXPRESSION_VARIABLE && expr->value.var.ptr) {
+        pool_free(pool, (char*)expr->value.var.ptr);
+    }
+    pool_free(pool, expr);
+}
+
+static NSAPIExpressionOperator expr_operator(cxstring token) {
+    if(!cx_strcmp(token, cx_str("+"))) {
+        return NSAPI_EXPRESSION_ADD;
+    } else if(!cx_strcmp(token, cx_str("-"))) {
+        return NSAPI_EXPRESSION_SUB;
+    } else if(!cx_strcmp(token, cx_str("*"))) {
+        return NSAPI_EXPRESSION_MUL;
+    } else if(!cx_strcmp(token, cx_str("/"))) {
+        return NSAPI_EXPRESSION_DIV;
+    } else if(!cx_strcmp(token, cx_str("%"))) {
+        return NSAPI_EXPRESSION_MOD;
+    } else if(!cx_strcmp(token, cx_str("not"))) {
+        return NSAPI_EXPRESSION_NOT;
+    } else if(!cx_strcmp(token, cx_str("and"))) {
+        return NSAPI_EXPRESSION_AND;
+    } else if(!cx_strcmp(token, cx_str("or"))) {
+        return NSAPI_EXPRESSION_OR;
+    } else if(!cx_strcmp(token, cx_str("xor"))) {
+        return NSAPI_EXPRESSION_XOR;
+    } else if(!cx_strcmp(token, cx_str("=="))) {
+        return NSAPI_EXPRESSION_EQ;
+    } else if(!cx_strcmp(token, cx_str("!="))) {
+        return NSAPI_EXPRESSION_NEQ;
+    } else if(!cx_strcmp(token, cx_str(">"))) {
+        return NSAPI_EXPRESSION_GT;
+    } else if(!cx_strcmp(token, cx_str("<"))) {
+        return NSAPI_EXPRESSION_LT;
+    } else if(!cx_strcmp(token, cx_str(">="))) {
+        return NSAPI_EXPRESSION_GE;
+    } else if(!cx_strcmp(token, cx_str("<="))) {
+        return NSAPI_EXPRESSION_LE;
+    }
+    return NSAPI_EXPRESSION_NOOP;
+}
+
+static int token_is_int(cxstring token) {
+    for(size_t i=0;i<token.length;i++) {
+        if(!isdigit(token.ptr[i])) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+static int expr_set_value(pool_handle_t *pool, NSAPIExpression *expr, cxstring token) {
+    if(token.length >= 2 && token.ptr[0] == '\"' && token.ptr[token.length-1] == '\"') {
+        expr->value.str = cx_strcast(cx_strdup_a(pool_allocator(pool), cx_strsubsl(token, 1, token.length-2)));
+        expr->type = NSAPI_EXPRESSION_STRING;
+    } else if(token.length >= 2 && token.ptr[0] == '$' && isalpha(token.ptr[1])) {
+        expr->value.var = cx_strcast(cx_strdup_a(pool_allocator(pool), cx_strsubs(token, 1)));
+        expr->type = NSAPI_EXPRESSION_VARIABLE;
+    } else if(token_is_int(token)) {
+        if(!util_strtoint(token.ptr, &expr->value.i)) {
+            return 1;
+        }
+        expr->type = NSAPI_EXPRESSION_INT;
+    } else if(!strcmp(token.ptr, "true")) {
+        expr->type = NSAPI_EXPRESSION_BOOL;
+        expr->value.b = 1;
+    } else if(!strcmp(token.ptr, "false")) {
+        expr->type = NSAPI_EXPRESSION_BOOL;
+        expr->value.b = 0;
+    } else {
+        return 1;
+    }
+    // TODO: double
+    return 0;
+}
+
+cxstring expr_next_token(CxList *tokens, size_t *pos) {
+    cxstring *token = cxListAt(tokens, *pos);
+    if(token) {
+        (*pos)++;
+        return *token;
+    }
+    return (cxstring){NULL, 0};
+}
+
+NSAPIExpression* expr_parser_pop(ExprParser *parser) {
+    CxList *stack = parser->ex_stack;
+    if(stack->size == 0) {
+        return NULL;
+    }
+    NSAPIExpression *ret = cxListAt(stack, stack->size-1);
+    cxListRemove(stack, stack->size-1);
+    return ret;
+}
+
+// takes items from ex_stack and adds a new operator expression to ex_stack
+static int expr_add_operator(ExprParser *parser, ExprOpStackItem *op) {
+    NSAPIExpression *exp = pool_malloc(parser->pool, sizeof(NSAPIExpression));
+    exp->operator = op->operator;
+    // op->expect_value == TRUE means, that the operator was found in a case
+    // a value was expected.
+    // For example: 1 + - 2
+    // After + a value is expected, but there is the - operator
+    // in that case, the - operator is a unary expression
+    if(op->expect_value) {
+        // We expected a value but got an operator? This must be an unary operator
+        exp->type = NSAPI_EXPRESSION_UNARY;
+        exp->left = expr_parser_pop(parser);
+        exp->right = NULL;
+    } else {
+        // binary operator
+        exp->type = NSAPI_EXPRESSION_BINARY;
+        exp->right = expr_parser_pop(parser);
+        exp->left = expr_parser_pop(parser);
+    }
+    
+    if(!exp->left && !exp->right) {
+        return 1; // error
+    }
+    
+    cxListAdd(parser->ex_stack, exp);
+    
+    parser->expect_value = TRUE;
+    return 0;
+}
+
+// converts the token to a value expression (int, bool, str, ...)
+// and adds it to parser->ex_stack
+// sets parser->expect_value to false
+static int expr_add_value(ExprParser *parser, cxstring token) {
+    NSAPIExpression *exp = pool_malloc(parser->pool, sizeof(NSAPIExpression));
+    ZERO(exp, sizeof(NSAPIExpression));
+    if(expr_set_value(parser->pool, exp, token)) {
+        return 1;
+    }
+    cxListAdd(parser->ex_stack, exp);
+    parser->expect_value = FALSE;
+    return 0;
+}
+
+
+static NSAPIExpression* expr_parse_expr(ExprParser *parser) {
+    CxList *op_stack = parser->op_stack;
+    CxList *ex_stack = parser->ex_stack;
+    
+    // Shunting yard algorithm
+    cxstring token = expr_next_token(parser->tokens, parser->pos);
+    for(;token.ptr;token=expr_next_token(parser->tokens, parser->pos)) {
+        NSAPIExpressionOperator op = expr_operator(token);
+        if(op != NSAPI_EXPRESSION_NOOP) {
+            ExprOpStackItem new_op;
+            new_op.operator = op;
+            new_op.expect_value = parser->expect_value;
+            new_op.open_parenthesis = FALSE;
+            while(op_stack->size > 0) {
+                ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1);
+                if(stack_item->operator == NSAPI_EXPRESSION_NOOP) {
+                    break;
+                }
+                // check presedence
+                if(op >= stack_item->operator) {
+                    break;
+                }
+                if(expr_add_operator(parser, stack_item)) {
+                    return NULL;
+                }
+                cxListRemove(op_stack, op_stack->size-1);
+            }
+            cxListAdd(op_stack, &new_op);
+            parser->expect_value = TRUE;
+        } else if(token.length == 1 && token.ptr[0] == '(') {
+            ExprOpStackItem new_op;
+            new_op.operator = NSAPI_EXPRESSION_NOOP;
+            new_op.expect_value = 0;
+            new_op.open_parenthesis = 1;
+            cxListAdd(op_stack, &new_op);
+            parser->expect_value = TRUE;
+        } else if(token.length == 1 && token.ptr[0] == ')') {
+            int found_open_bracket = FALSE;
+            while(op_stack->size > 0) {
+                ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1);
+                cxListRemove(op_stack, op_stack->size-1);
+                if(stack_item->open_parenthesis) {
+                    found_open_bracket = TRUE;
+                    break;
+                } else {
+                    if(expr_add_operator(parser, stack_item)) {
+                        return NULL;
+                    }
+                }
+            }
+            if(!found_open_bracket) {
+                return NULL;
+            }
+            parser->expect_value = FALSE;
+        } else {
+            if(expr_add_value(parser, token)) {
+                return NULL;
+            }
+        }
+    }
+    
+    while(op_stack->size > 0) {
+        ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1);
+        if(stack_item->open_parenthesis) {
+            return NULL;
+        }
+        if(expr_add_operator(parser, stack_item)) {
+            return NULL;
+        }
+        cxListRemove(op_stack, op_stack->size-1);
+    }
+    
+    if(ex_stack->size != 1) {
+        return NULL;
+    }
+    
+    return cxListAt(ex_stack, 0);
+}
+
+NSAPIExpression* expr_parse_logical_expr(pool_handle_t *pool, CxList *tokens, size_t *pos) {  
+    CxList *op_stack = cxLinkedListCreate(pool_allocator(pool), cx_cmp_ptr, sizeof(ExprOpStackItem));
+    CxList *ex_stack = cxPointerLinkedListCreate(pool_allocator(pool), cx_cmp_ptr);
+    
+    ExprParser parser;
+    parser.pool = pool;
+    parser.op_stack = op_stack;
+    parser.ex_stack = ex_stack;
+    parser.tokens = tokens;
+    parser.pos = pos;
+    parser.expect_value = TRUE;
+    
+    NSAPIExpression *ret = expr_parse_expr(&parser);
+    cxListDestroy(op_stack);
+    cxListDestroy(ex_stack);
+    
+    return ret;
+}
+
+
+
 int condition_evaluate(Condition *condition, Session *sn, Request *rq) {
     return 1;
 }

mercurial