ソースを参照

ncd: modules: concat: optimize to return the result as an external string

ambrop7 13 年 前
コミット
139af24480
1 ファイル変更46 行追加26 行削除
  1. 46 26
      ncd/modules/concat.c

+ 46 - 26
ncd/modules/concat.c

@@ -35,60 +35,80 @@
  *   string (empty) - elem1, ..., elemN concatenated
  *   string (empty) - elem1, ..., elemN concatenated
  */
  */
 
 
-#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
 
 
-#include <misc/expstring.h>
+#include <misc/balloc.h>
+#include <misc/offset.h>
 #include <ncd/NCDModule.h>
 #include <ncd/NCDModule.h>
+#include <ncd/NCDRefTarget.h>
 #include <ncd/static_strings.h>
 #include <ncd/static_strings.h>
 
 
 #include <generated/blog_channel_ncd_concat.h>
 #include <generated/blog_channel_ncd_concat.h>
 
 
 #define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
 #define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
 
 
+struct result {
+    NCDRefTarget ref_target;
+    size_t length;
+    char data[];
+};
+
 struct instance {
 struct instance {
     NCDModuleInst *i;
     NCDModuleInst *i;
-    uint8_t *string;
-    size_t len;
+    struct result *result;
 };
 };
 
 
+static void result_ref_target_func_release (NCDRefTarget *ref_target)
+{
+    struct result *result = UPPER_OBJECT(ref_target, struct result, ref_target);
+    
+    BFree(result);
+}
+
 static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
 static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
 {
 {
     struct instance *o = vo;
     struct instance *o = vo;
     o->i = i;
     o->i = i;
     
     
-    // init string
-    ExpString s;
-    if (!ExpString_Init(&s)) {
-        ModuleLog(i, BLOG_ERROR, "ExpString_Init failed");
-        goto fail0;
-    }
-    
-    // append arguments
     size_t count = NCDVal_ListCount(params->args);
     size_t count = NCDVal_ListCount(params->args);
+    bsize_t result_size = bsize_fromsize(sizeof(struct result));
+    
+    // check arguments and compute result size
     for (size_t j = 0; j < count; j++) {
     for (size_t j = 0; j < count; j++) {
         NCDValRef arg = NCDVal_ListGet(params->args, j);
         NCDValRef arg = NCDVal_ListGet(params->args, j);
         
         
         if (!NCDVal_IsString(arg)) {
         if (!NCDVal_IsString(arg)) {
             ModuleLog(i, BLOG_ERROR, "wrong type");
             ModuleLog(i, BLOG_ERROR, "wrong type");
-            goto fail1;
+            goto fail0;
         }
         }
         
         
-        if (!ExpString_AppendBinary(&s, (const uint8_t *)NCDVal_StringData(arg), NCDVal_StringLength(arg))) {
-            ModuleLog(i, BLOG_ERROR, "ExpString_Append failed");
-            goto fail1;
-        }
+        result_size = bsize_add(result_size, bsize_fromsize(NCDVal_StringLength(arg)));
+    }
+    
+    // allocate result
+    o->result = BAllocSize(result_size);
+    if (!o->result) {
+        ModuleLog(i, BLOG_ERROR, "BAllocSize failed");
+        goto fail0;
     }
     }
     
     
-    // set string
-    o->string = (uint8_t *)ExpString_Get(&s);
-    o->len = ExpString_Length(&s);
+    // init ref target
+    NCDRefTarget_Init(&o->result->ref_target, result_ref_target_func_release);
+    
+    // copy data to result
+    o->result->length = 0;
+    for (size_t j = 0; j < count; j++) {
+        NCDValRef arg = NCDVal_ListGet(params->args, j);
+        size_t this_len = NCDVal_StringLength(arg);
+        memcpy(o->result->data + o->result->length, NCDVal_StringData(arg), this_len);
+        o->result->length += this_len;
+    }
     
     
     // signal up
     // signal up
     NCDModuleInst_Backend_Up(o->i);
     NCDModuleInst_Backend_Up(o->i);
     return;
     return;
     
     
-fail1:
-    ExpString_Free(&s);
 fail0:
 fail0:
     NCDModuleInst_Backend_SetError(i);
     NCDModuleInst_Backend_SetError(i);
     NCDModuleInst_Backend_Dead(i);
     NCDModuleInst_Backend_Dead(i);
@@ -98,8 +118,8 @@ static void func_die (void *vo)
 {
 {
     struct instance *o = vo;
     struct instance *o = vo;
     
     
-    // free string
-    free(o->string);
+    // release result reference
+    NCDRefTarget_Deref(&o->result->ref_target);
     
     
     NCDModuleInst_Backend_Dead(o->i);
     NCDModuleInst_Backend_Dead(o->i);
 }
 }
@@ -109,9 +129,9 @@ static int func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValR
     struct instance *o = vo;
     struct instance *o = vo;
     
     
     if (name == NCD_STRING_EMPTY) {
     if (name == NCD_STRING_EMPTY) {
-        *out = NCDVal_NewStringBin(mem, o->string, o->len);
+        *out = NCDVal_NewExternalString(mem, o->result->data, o->result->length, &o->result->ref_target);
         if (NCDVal_IsInvalid(*out)) {
         if (NCDVal_IsInvalid(*out)) {
-            ModuleLog(o->i, BLOG_ERROR, "NCDVal_NewStringBin failed");
+            ModuleLog(o->i, BLOG_ERROR, "NCDVal_NewExternalString failed");
         }
         }
         return 1;
         return 1;
     }
     }