shithub: choc

Download patch

ref: e22d6a0d26b08e2e7c69972fed1cb96f300ef523
parent: b786d601aeaaa20167f408be56f7e8d13ecc2f8c
author: Simon Howard <fraggle@gmail.com>
date: Sat Feb 6 21:59:25 EST 2010

Refactor dehacked structure mapping code to support string fields in
addition to integer fields.

Subversion-branch: /branches/raven-branch
Subversion-revision: 1856

--- a/src/deh_mapping.c
+++ b/src/deh_mapping.c
@@ -34,12 +34,9 @@
 #include "i_system.h"
 #include "deh_mapping.h"
 
-//
-// Set the value of a particular field in a structure by name
-//
-
-boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, 
-                       void *structptr, char *name, int value)
+static deh_mapping_entry_t *GetMappingEntryByName(deh_context_t *context,
+                                                  deh_mapping_t *mapping,
+                                                  char *name)
 {
     int i;
 
@@ -49,44 +46,121 @@
 
         if (!strcasecmp(entry->name, name))
         {
-            void *location;
-
             if (entry->location == NULL)
             {
                 DEH_Warning(context, "Field '%s' is unsupported", name);
-                return false;
+                return NULL;
             }
 
-            location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base);
+            return entry;
+        }
+    }
 
-     //       printf("Setting %p::%s to %i (%i bytes)\n",
-     //               structptr, name, value, entry->size);
-                
-            switch (entry->size)
-            {
-                case 1:
-                    * ((uint8_t *) location) = value;
-                    break;
-                case 2:
-                    * ((uint16_t *) location) = value;
-                    break;
-                case 4:
-                    * ((uint32_t *) location) = value;
-                    break;
-                default:
-                    DEH_Error(context, "Unknown field type for '%s' (BUG)", name);
-                    return false;
-            }
+    // Not found.
+
+    DEH_Warning(context, "Field named '%s' not found", name);
 
-            return true;
-        }
+    return NULL;
+}
+
+//
+// Get the location of the specified field in the specified structure.
+//
+
+static void *GetStructField(void *structptr,
+                            deh_mapping_t *mapping,
+                            deh_mapping_entry_t *entry)
+{
+    unsigned int offset;
+
+    offset = (uint8_t *)entry->location - (uint8_t *)mapping->base;
+
+    return (uint8_t *)structptr + offset;
+}
+
+//
+// Set the value of a particular field in a structure by name
+//
+
+boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
+                       void *structptr, char *name, int value)
+{
+    deh_mapping_entry_t *entry;
+    void *location;
+
+    entry = GetMappingEntryByName(context, mapping, name);
+
+    if (entry == NULL)
+    {
+        return false;
     }
 
-    // field with this name not found
+    // Sanity check:
 
-    DEH_Warning(context, "Field named '%s' not found", name);
+    if (entry->is_string)
+    {
+        DEH_Error(context, "Tried to set '%s' as integer (BUG)", name);
+        return false;
+    }
 
-    return false;
+    location = GetStructField(structptr, mapping, entry);
+
+    //       printf("Setting %p::%s to %i (%i bytes)\n",
+    //               structptr, name, value, entry->size);
+
+    // Set field content based on its type:
+
+    switch (entry->size)
+    {
+        case 1:
+            * ((uint8_t *) location) = value;
+            break;
+        case 2:
+            * ((uint16_t *) location) = value;
+            break;
+        case 4:
+            * ((uint32_t *) location) = value;
+            break;
+        default:
+            DEH_Error(context, "Unknown field type for '%s' (BUG)", name);
+            return false;
+    }
+
+    return true;
+}
+
+//
+// Set the value of a string field in a structure by name
+//
+
+boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping,
+                             void *structptr, char *name, char *value)
+{
+    deh_mapping_entry_t *entry;
+    void *location;
+
+    entry = GetMappingEntryByName(context, mapping, name);
+
+    if (entry == NULL)
+    {
+        return false;
+    }
+
+    // Sanity check:
+
+    if (!entry->is_string)
+    {
+        DEH_Error(context, "Tried to set '%s' as string (BUG)", name);
+        return false;
+    }
+
+    location = GetStructField(structptr, mapping, entry);
+
+    // Copy value into field:
+
+    strncpy(location, value, entry->size);
+
+    return true;
 }
 
 void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
--- a/src/deh_mapping.h
+++ b/src/deh_mapping.h
@@ -42,18 +42,24 @@
 
 #define DEH_MAPPING(deh_name, fieldname)                      \
              {deh_name, &deh_mapping_base.fieldname,          \
-                 sizeof(deh_mapping_base.fieldname)},
+                 sizeof(deh_mapping_base.fieldname),          \
+                 false},
 
+#define DEH_MAPPING_STRING(deh_name, fieldname)               \
+             {deh_name, &deh_mapping_base.fieldname,          \
+                 sizeof(deh_mapping_base.fieldname),          \
+                 true},
+
 #define DEH_UNSUPPORTED_MAPPING(deh_name)                     \
-             {deh_name, NULL, -1},
-            
+             {deh_name, NULL, -1, false},
+
 #define DEH_END_MAPPING                                       \
              {NULL, NULL, -1}                                 \
         }                                                     \
     };
 
-    
 
+
 #define MAX_MAPPING_ENTRIES 32
 
 typedef struct deh_mapping_s deh_mapping_t;
@@ -73,6 +79,10 @@
     // field size
 
     int size;
+
+    // if true, this is a string value.
+
+    boolean is_string;
 };
 
 struct deh_mapping_s
@@ -81,8 +91,10 @@
     deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES];
 };
 
-boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, 
+boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
                        void *structptr, char *name, int value);
+boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping,
+                             void *structptr, char *name, char *value);
 void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
                       void *structptr);