pytest.ini: declare minimum version requirement
[metze/wireshark/wip.git] / epan / uat.c
index 3c1a0ec7dce817018e7af3638de1bd55e5532b2b..ab3b0e99e7081478789a9100728277d3e9b089c6 100644 (file)
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 2001 Gerald Combs
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 #include "config.h"
 
@@ -225,6 +213,20 @@ void uat_remove_record_idx(uat_t* uat, guint idx) {
     g_array_remove_index(uat->valid_data, idx);
 }
 
+void uat_move_index(uat_t * uat, guint old_idx, guint new_idx)
+{
+    guint dir = 1;
+    guint start = old_idx;
+    if ( old_idx > new_idx )
+        dir = -1;
+
+    while ( start != new_idx )
+    {
+        uat_swap(uat, start, start + dir);
+        start += dir;
+    }
+}
+
 /* The returned filename was g_malloc()'d so the caller must free it */
 gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
     gchar *pers_fname = NULL;
@@ -273,8 +275,12 @@ char *uat_fld_tostr(void *rec, uat_field_t *f) {
         case PT_TXTMOD_NONE:
         case PT_TXTMOD_STRING:
         case PT_TXTMOD_ENUM:
+        case PT_TXTMOD_BOOL:
         case PT_TXTMOD_FILENAME:
         case PT_TXTMOD_DIRECTORYNAME:
+        case PT_TXTMOD_DISPLAY_FILTER:
+        case PT_TXTMOD_COLOR:
+        case PT_TXTMOD_PROTO_FIELD:
             out = g_strndup(ptr, len);
             break;
         case PT_TXTMOD_HEXBYTES: {
@@ -309,6 +315,9 @@ static void putfld(FILE* fp, void* rec, uat_field_t* f) {
         case PT_TXTMOD_ENUM:
         case PT_TXTMOD_FILENAME:
         case PT_TXTMOD_DIRECTORYNAME:
+        case PT_TXTMOD_DISPLAY_FILTER:
+        case PT_TXTMOD_PROTO_FIELD:
+        case PT_TXTMOD_COLOR:
         case PT_TXTMOD_STRING: {
             guint i;
 
@@ -336,6 +345,10 @@ static void putfld(FILE* fp, void* rec, uat_field_t* f) {
 
             break;
         }
+        case PT_TXTMOD_BOOL: {
+            fprintf(fp,"\"%s\"", fld_ptr);
+            break;
+        }
         default:
             g_assert_not_reached();
     }
@@ -516,7 +529,7 @@ void uat_load_all(void) {
 
         if (!u->loaded) {
             err = NULL;
-            if (!uat_load(u, &err)) {
+            if (!uat_load(u, NULL, &err)) {
                 report_failure("Error loading table '%s': %s",u->name,err);
                 g_free(err);
             }
@@ -593,32 +606,36 @@ gboolean uat_fld_chk_proto(void* u1 _U_, const char* strptr, guint len, const vo
 
 static gboolean uat_fld_chk_num(int base, const char* strptr, guint len, char** err) {
     if (len > 0) {
-        char* str = g_strndup(strptr,len);
-        char* strn;
-        long i;
+        char* str = g_strndup(strptr, len);
+        const char* strn;
+        gboolean result;
+        guint32 value;
+
+        result = ws_basestrtou32(str, &strn, &value, base);
+        if (result && ((*strn != '\0') && (*strn != ' '))) {
+            /* string valid, but followed by something other than a space */
+            result = FALSE;
+            errno = EINVAL;
+        }
+        if (!result) {
+            switch (errno) {
 
-        errno = 0;
-        i = strtol(str,&strn,base);
+            case EINVAL:
+                *err = g_strdup("Invalid value");
+                break;
 
-        if (((i == G_MAXLONG || i == G_MINLONG) && errno == ERANGE)
-            || (errno != 0 && i == 0)) {
-            *err = g_strdup(g_strerror(errno));
-            g_free(str);
-            return FALSE;
-        }
-        if ((*strn != '\0') && (*strn != ' ')) {
-            *err = g_strdup("Invalid value");
-            g_free(str);
-            return FALSE;
-        }
-        /* Allow only 32bit values */
-        if ((sizeof(long) > 4) && ((i < G_MININT) || (i > G_MAXINT))) {
-            *err = g_strdup("Value too large");
-            g_free(str);
-            return FALSE;
-        }
+            case ERANGE:
+                *err = g_strdup("Value too large");
+                break;
 
+            default:
+                *err = g_strdup(g_strerror(errno));
+                break;
+            }
+        }
         g_free(str);
+
+        return result;
     }
 
     *err = NULL;
@@ -633,13 +650,68 @@ gboolean uat_fld_chk_num_hex(void* u1 _U_, const char* strptr, guint len, const
     return uat_fld_chk_num(16, strptr, len, err);
 }
 
+gboolean uat_fld_chk_num_signed_dec(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
+    if (len > 0) {
+        char* str = g_strndup(strptr,len);
+        const char* strn;
+        gboolean result;
+        gint32 value;
+
+        result = ws_strtoi32(str, &strn, &value);
+        if (result && ((*strn != '\0') && (*strn != ' '))) {
+            /* string valid, but followed by something other than a space */
+            result = FALSE;
+            errno = EINVAL;
+        }
+        if (!result) {
+            switch (errno) {
+
+            case EINVAL:
+                *err = g_strdup("Invalid value");
+                break;
+
+            case ERANGE:
+                *err = g_strdup("Value too large");
+                break;
+
+            default:
+                *err = g_strdup(g_strerror(errno));
+                break;
+            }
+        }
+        g_free(str);
+
+        return result;
+    }
+
+    *err = NULL;
+    return TRUE;
+}
+
+gboolean uat_fld_chk_bool(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err)
+{
+    char* str = g_strndup(strptr,len);
+
+    if ((g_strcmp0(str, "TRUE") == 0) ||
+        (g_strcmp0(str, "FALSE") == 0)) {
+        *err = NULL;
+        g_free(str);
+        return TRUE;
+    }
+
+    *err = g_strdup_printf("invalid value: %s (must be TRUE or FALSE)", str);
+    g_free(str);
+    return FALSE;
+}
+
+
 gboolean uat_fld_chk_enum(void* u1 _U_, const char* strptr, guint len, const void* v, const void* u3 _U_, char** err) {
     char* str = g_strndup(strptr,len);
     guint i;
     const value_string* vs = (const value_string *)v;
 
     for(i=0;vs[i].strptr;i++) {
-        if (g_str_equal(vs[i].strptr,str)) {
+        if (g_strcmp0(vs[i].strptr,str) == 0) {
             *err = NULL;
             g_free(str);
             return TRUE;
@@ -681,6 +753,17 @@ gboolean uat_fld_chk_range(void* u1 _U_, const char* strptr, guint len, const vo
     return ret_value;
 }
 
+gboolean uat_fld_chk_color(void* u1 _U_, const char* strptr, guint len, const void* v _U_, const void* u3 _U_, char** err) {
+
+    if ((len != 7) || (*strptr != '#')) {
+        *err = g_strdup("Color must be of the format #RRGGBB");
+        return FALSE;
+    }
+
+    /* Color is just # followed by hex string, so use hex verification */
+    return uat_fld_chk_num(16, strptr + 1, len - 1, err);
+}
+
 char* uat_unbinstring(const char* si, guint in_len, guint* len_p) {
     guint8* buf;
     guint len = in_len/2;
@@ -713,7 +796,7 @@ char* uat_unesc(const char* si, guint in_len, guint* len_p) {
     const char* s;
     const char* in_end = si+in_len;
 
-    for (s = (const char *)si; s < in_end; s++) {
+    for (s = si; s < in_end; s++) {
         switch(*s) {
             case '\\':
                 switch(*(++s)) {