Commits

Fuzhou Chen committed 595a277

[Fix] Optimize logic again to avoid if-result check.

Comments (0)

Files changed (5)

 #include "esch_value.h"
 #include "esch_debug.h"
 
-static void
-esch_value_do_nothing(esch_value* to, esch_value* from)
+static esch_error
+esch_value_type_error(esch_value* to, esch_value* from)
 {
     ESCH_CHECK_PARAM_INTERNAL(to != NULL);
     ESCH_CHECK_PARAM_INTERNAL(from != NULL);
+    return ESCH_ERROR_BAD_VALUE_TYPE;
 }
-static void
+static esch_error
 esch_value_do_assign(esch_value* to, esch_value* from)
 {
     ESCH_CHECK_PARAM_INTERNAL(to != NULL);
 
     to->type = from->type;
     to->val = from->val;
+    return ESCH_OK;
 }
 
 #define ESCH_VALUE_DEFINE_GET(suffix, vt, ot, field) \
 
 esch_value_assign_f esch_value_assign[2] = {
     esch_value_do_assign, /* status: ESCH_OK */
-    esch_value_do_nothing, /* status: ESCH_ERROR_BAD_VALUE_TYPE */
+    esch_value_type_error, /* status: ESCH_ERROR_BAD_VALUE_TYPE */
 };
 
 esch_value_check_f esch_value_check[8] = {
     esch_value_fail, /* expect: ESCH_VALUE_TYPE_END */
 };
 
-esch_error esch_value_type_check[8][8] = {
+int esch_value_type_check[8][8] = {
     /* expect: ESCH_VALUE_TYPE_UNKNOWN */ {
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
+        1, 1, 1, 1, 1, 1, 1, 1
     },
     /* expect: ESCH_VALUE_TYPE_BYTE */ {
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_OK,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
+        1, 0, 1, 1, 1, 1, 1, 1
     },
     /* expect: ESCH_VALUE_TYPE_UNICODE */ {
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_OK,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
+        1, 1, 0, 1, 1, 1, 1, 1
     },
     /* expect: ESCH_VALUE_TYPE_INTEGER */ {
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_OK,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
+        1, 1, 1, 0, 1, 1, 1, 1
     },
     /* expect: ESCH_VALUE_TYPE_FLOAT */ {
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_OK,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
+        1, 1, 1, 1, 0, 1, 1, 1
     },
     /* expect: ESCH_VALUE_TYPE_OBJECT */ {
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_OK,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
+        1, 1, 1, 1, 1, 0, 1, 1
     },
     /* expect: ESCH_VALUE_TYPE_NIL */ {
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_ERROR_BAD_VALUE_TYPE,
-        ESCH_OK,
-        ESCH_ERROR_BAD_VALUE_TYPE,
+        1, 1, 1, 1, 1, 1, 0, 1
     },
     /* expect: ESCH_VALUE_TYPE_END */ {
-        ESCH_OK,
-        ESCH_OK,
-        ESCH_OK,
-        ESCH_OK,
-        ESCH_OK,
-        ESCH_OK,
-        ESCH_OK, /* Always ignore type check if user passes END */
+        0, 0, 0, 0, 0, 0, 0, 0
+        /* Always ignore type check if user passes END */
     }
 };
 
 extern "C" {
 #endif /* __cplusplus */
 
-typedef void (*esch_value_assign_f)(esch_value*, esch_value*);
+typedef esch_error (*esch_value_assign_f)(esch_value*, esch_value*);
 typedef esch_error (*esch_value_check_f)(esch_value*);
 
-extern esch_error esch_value_type_check[8][8]; /* match every value */
+extern int esch_value_type_check[8][8]; /* match every value */
 extern esch_value_check_f esch_value_check[8];
 extern esch_value_assign_f esch_value_assign[2];
 

src/esch_vector.c

     ESCH_CHECK_PARAM_INTERNAL(ESCH_IS_VALID_LOG(log));
 
     initial_length = ESCH_CONFIG_GET_VECOTR_LENGTH(config);
-    if (initial_length < ESCH_VECTOR_MINIMAL_INITIAL_LENGTH) {
+    if (initial_length < 0 ||
+            (size_t)initial_length < ESCH_VECTOR_MINIMAL_INITIAL_LENGTH)
+    {
         initial_length = ESCH_VECTOR_MINIMAL_INITIAL_LENGTH;
     }
 
     }
     slot = vec->next;
     vec->next += 1;
-    ret = esch_value_check[value->type](value);
-    esch_value_assign[ret == ESCH_OK? 0: 1](slot, value);
+    /* NOTE: Use function table instead of if-type check to avoid
+     * runtime cost.
+     */
+    ret = esch_value_assign[
+                 esch_value_check[value->type](value)
+                 ](slot, value);
 Exit:
     return ret;
 }
     }
     if (real_index >= 0 && vec->next - vec->begin > real_index) {
         esch_value_type real_type = vec->begin[real_index].type;
-        ret = esch_value_type_check[expected_type][real_type];
-        esch_value_assign[ret == ESCH_OK? 0: 1](value,
-                                             &(vec->begin[real_index]));
+        /* NOTE: Use function table instead of if-type check to avoid
+         * runtime cost. */
+        ret = esch_value_assign[
+                esch_value_type_check[expected_type][real_type]
+            ](value, &(vec->begin[real_index]));
     } else {
         esch_log_info(log, "vec:obj = 0x%x, idx = %d", vec, index);
         ret = ESCH_ERROR_OUT_OF_BOUND;
         esch_value_type real_type = vec->begin[real_index].type;
         ESCH_CHECK_PARAM_INTERNAL(real_type > ESCH_VALUE_TYPE_UNKNOWN);
         ESCH_CHECK_PARAM_INTERNAL(real_type < ESCH_VALUE_TYPE_END);
-        ret = esch_value_check[real_type](value);
-        esch_value_assign[ret == ESCH_OK? 0: 1](&(vec->begin[real_index]),
-                                             value);
+        /* NOTE: Use function table instead of if-type check to avoid
+         * runtime cost.  */
+        ret = esch_value_assign[
+                esch_value_type_check[ESCH_VALUE_TYPE_END][real_type]
+            ](&(vec->begin[real_index]), value);
     } else {
         esch_log_info(log, "vec:obj = 0x%x, idx = %d", vec, index);
         ret = ESCH_ERROR_OUT_OF_BOUND;

src/utest/esch_t_vector.c

         ret = esch_vector_get_value(vec, i,
                                     ESCH_VALUE_TYPE_OBJECT, &value);
         ESCH_TEST_CHECK(ret == ESCH_ERROR_BAD_VALUE_TYPE,
-                        "Query with bad type should be rejected", ret);
+                        "Query with bad type should be rejected",
+                        ESCH_ERROR_INVALID_STATE);
     }
     for (i = 0; i < 5; ++i) {
         ret = esch_vector_get_value(vec, i, vt[i], &value);

src/utest/esch_utest.c

     ESCH_TEST_CHECK(ret == ESCH_OK, "test_vectorResizeFlag() failed", ret);
     esch_log_info(testLog, "[PASSED] test_vectorResizeFlag()");
 
-    esch_log_info(testLog, "Start: test_vectorDifferentValues()");
-    ret = test_vectorDifferentValues(config);
-    ESCH_TEST_CHECK(ret == ESCH_OK, "test_vectorDifferentValues() failed",
-                    ret);
-    esch_log_info(testLog, "[PASSED] test_vectorDifferentValues()");
-
-
     esch_log_info(testLog, "Start: test_gcCreateDelete()");
     ret = test_gcCreateDelete(config);
     ESCH_TEST_CHECK(ret == ESCH_OK, "test_gcCreateDelete() failed", ret);
     ESCH_TEST_CHECK(ret == ESCH_OK, "test_gcExpand() failed", ret);
     esch_log_info(testLog, "[PASSED]: test_gcExpand()");
 
+    /* Put it here for catching a bug in vector.c, that it does not
+     * handle default size correctly. */
+    esch_log_info(testLog, "Start: test_vectorDifferentValues()");
+    ret = test_vectorDifferentValues(config);
+    ESCH_TEST_CHECK(ret == ESCH_OK, "test_vectorDifferentValues() failed",
+                    ret);
+    esch_log_info(testLog, "[PASSED] test_vectorDifferentValues()");
+
     /*
     ret = test_config();
     ESCH_TEST_CHECK(ret == ESCH_OK, "test_config() failed", ret);