Răsfoiți Sursa

ncd: modules: basic_functions: Add tolower, toupper.

Ambroz Bizjak 11 ani în urmă
părinte
comite
7440004eac
3 a modificat fișierele cu 98 adăugiri și 0 ștergeri
  1. 43 0
      misc/ascii_utils.h
  2. 44 0
      ncd/modules/basic_functions.c
  3. 11 0
      ncd/tests/basic_functions.ncd

+ 43 - 0
misc/ascii_utils.h

@@ -0,0 +1,43 @@
+/**
+ * @file ascii_utils.h
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BADVPN_ASCII_UTILS_H
+#define BADVPN_ASCII_UTILS_H
+
+static char b_ascii_tolower (char c)
+{
+    return (c >= 'A' && c <= 'Z') ? (c + 32) : c;
+}
+
+static char b_ascii_toupper (char c)
+{
+    return (c >= 'a' && c <= 'z') ? (c - 32) : c;
+}
+
+#endif

+ 44 - 0
ncd/modules/basic_functions.c

@@ -31,6 +31,7 @@
 
 #include <misc/expstring.h>
 #include <misc/bsize.h>
+#include <misc/ascii_utils.h>
 #include <ncd/NCDValGenerator.h>
 #include <ncd/NCDValParser.h>
 
@@ -387,6 +388,43 @@ static void decode_value_eval (NCDCall call)
     NCDCall_SetResult(&call, value);
 }
 
+
+// ASCII case conversion
+
+typedef char (*perchar_func) (char ch);
+
+static void perchar_eval (NCDCall call, perchar_func func)
+{
+    if (NCDCall_ArgCount(&call) != 1) {
+        return FunctionLog(&call, BLOG_ERROR, "tolower: need one argument");
+    }
+    NCDValRef arg = NCDCall_EvalArg(&call, 0, NCDCall_ResMem(&call));
+    if (NCDVal_IsInvalid(arg)) {
+        return;
+    }
+    if (!NCDVal_IsString(arg)) {
+        return FunctionLog(&call, BLOG_ERROR, "tolower: argument not a string");
+    }
+    NCDValRef value = NCDVal_NewStringUninitialized(NCDCall_ResMem(&call), NCDVal_StringLength(arg));
+    if (NCDVal_IsInvalid(value)) {
+        return;
+    }
+    char *out_data = (char *)NCDVal_StringData(value);
+    b_cstring arg_cstr = NCDVal_StringCstring(arg);
+    B_CSTRING_LOOP_CHARS(arg_cstr, i, ch, {
+        out_data[i] = func(ch);
+    })
+    NCDCall_SetResult(&call, value);
+}
+
+#define DEFINE_PERCHAR(name, expr) \
+static char perchar_##name##_func (char ch) { return expr; } \
+static void perchar_##name##_eval (NCDCall call) { return perchar_eval(call, perchar_##name##_func); }
+
+DEFINE_PERCHAR(tolower, b_ascii_tolower(ch))
+DEFINE_PERCHAR(toupper, b_ascii_toupper(ch))
+
+
 static struct NCDModuleFunction const functions[] = {
     {
         .func_name = "__error__",
@@ -475,6 +513,12 @@ static struct NCDModuleFunction const functions[] = {
     }, {
         .func_name = "__decode_value__",
         .func_eval = decode_value_eval
+    }, {
+        .func_name = "__tolower__",
+        .func_eval = perchar_tolower_eval
+    }, {
+        .func_name = "__toupper__",
+        .func_eval = perchar_toupper_eval
     }, {
         .func_name = NULL
     }

+ 11 - 0
ncd/tests/basic_functions.ncd

@@ -242,5 +242,16 @@ process main {
     val_equal(x, "foo") a;
     assert(a);
     
+    
+    var(@tolower("09@AZ[`az{")) x;
+    val_equal(x, "09@az[`az{") a;
+    assert(a);
+    
+    
+    var(@toupper("09@AZ[`az{")) x;
+    val_equal(x, "09@AZ[`AZ{") a;
+    assert(a);
+    
+    
     exit("0");
 }