Merge branch 'master' into browser
[projects/chimara/chimara.git] / babel / treaty_builder.h
diff --git a/babel/treaty_builder.h b/babel/treaty_builder.h
new file mode 100644 (file)
index 0000000..d52ae3e
--- /dev/null
@@ -0,0 +1,180 @@
+/* treaty_builder.h common macros to build a treaty module\r
+ *\r
+ * 2006 By L. Ross Raszewski\r
+ *\r
+ * This file is public domain, but be aware that any changes to it may\r
+ * cause it to cease to be compliant with the Treaty of Babel.\r
+ *\r
+ * This file depends on treaty.h\r
+ *\r
+ * The purpose of this file is to simplify the building of a treaty\r
+ * module.  It automatically generates a generic treaty function.\r
+ *\r
+ * Usage:\r
+ *\r
+ * #define the following values:\r
+ *  FORMAT              The treaty name of the format\r
+ *  HOME_PAGE           A string containing the URL of the format home page\r
+ *  FORMAT_EXT          A string containing a comma separated list of common\r
+ *                       extensions for game files in this format\r
+ *  NO_METADATA         If the format does not support metadata\r
+ *  NO_COVER            If the format does not support cover art\r
+ *  CUSTOM_EXTENSION    If game files should not always use the first listed extension\r
+ *\r
+ * (Note: Formats which support metadata and cover art via a container should\r
+ * define NO_METADATA and NO_COVER as container support is handled separately)\r
+ *\r
+ * #include "treaty_builder.h"\r
+ * Define the following functions:\r
+ *   static int32 get_story_file_IFID(void *, int32, char *, int32);\r
+ *   static int32 claim_story_file(void *, int32);\r
+ * Define the following functions if NO_METADATA is not defined:\r
+ *   static int32 get_story_file_metadata_extent(void *, int32);\r
+ *   static int32 get_story_file_metadata(void *, int32, char *, int32);\r
+ * Define the following functions if NO_COVER is not defined\r
+ *   static int32 get_story_file_cover_extent(void *, int32);\r
+ *   static int32 get_story_file_cover_format(void *, int32);\r
+ *   static int32 get_story_file_cover(void *, int32, void *, int32);\r
+ * Define the following if CUSTOM_EXTENSION is defined\r
+ *   static int32 get_story_file_extension(void *, int32, char *, int32);\r
+ *\r
+ * The two-parameter functions take the story file and story file extent\r
+ * as parameters.  The four-parameter ones also take the output\r
+ * buffer and its extent.  They perform the corresponding task to the\r
+ * similarly-named selector.\r
+ *\r
+ * This file also defines the macro ASSERT_OUTPUT_SIZE(x) which\r
+ * returns INVALID_USAGE_RV if output_extent is less than x.\r
+ *\r
+ * #define CONTAINER_FORMAT  before inclusion to generate a container\r
+ * module.  A container module should define three additional functions:\r
+ *    static int32 get_story_format(void *, int32, char *, int32);\r
+ *    static int32 get_story_extent(void *, int32);\r
+ *    static int32 get_story_file(void *, int32, void *, int32);\r
+ *\r
+ */\r
+\r
+#ifndef TREATY_BUILDER\r
+#define TREATY_BUILDER\r
+\r
+#include "treaty.h"\r
+#include <string.h>\r
+\r
+#define ASSERT_OUTPUT_SIZE(x) do { if (output_extent < (x)) return INVALID_USAGE_RV; } while (0)\r
+\r
+#ifndef NO_METADATA\r
+static int32 get_story_file_metadata_extent(void *, int32);\r
+static int32 get_story_file_metadata(void *, int32, char *, int32);\r
+#endif\r
+#ifndef NO_COVER\r
+static int32 get_story_file_cover_extent(void *, int32);\r
+static int32 get_story_file_cover_format(void *, int32);\r
+static int32 get_story_file_cover(void *, int32, void *, int32);\r
+#endif\r
+static int32 get_story_file_IFID(void *, int32, char *, int32);\r
+static int32 claim_story_file(void *, int32);\r
+#ifdef CONTAINER_FORMAT\r
+static int32 get_story_file(void *, int32, void *, int32);\r
+static int32 get_story_format(void *, int32, char *, int32);\r
+static int32 get_story_extent(void *, int32);\r
+#endif\r
+#ifdef CUSTOM_EXTENSION\r
+static int32 get_story_file_extension(void *, int32, char *, int32);\r
+#else\r
+#include <stdio.h>\r
+static int32 get_story_file_extension(void *sf, int32 extent, char *out, int32 output_extent)\r
+{\r
+ int i;\r
+\r
+ if (!sf || !extent) return INVALID_STORY_FILE_RV;\r
+\r
+ for(i=0;FORMAT_EXT[i] && FORMAT_EXT[i]!=',';i++);\r
+ ASSERT_OUTPUT_SIZE(i+1);\r
+ memcpy(out,FORMAT_EXT,i);\r
+ out[i]=0;\r
+ return strlen(out);\r
+}\r
+\r
+#endif\r
+\r
+#define TREATY_FUNCTION(X)  DEEP_TREATY_FUNCTION(X)\r
+#define DEEP_TREATY_FUNCTION(X) X ## _treaty\r
+#define dSTRFRY(X) #X\r
+#define STRFRY(X) dSTRFRY(X)\r
+\r
+int32 TREATY_FUNCTION(FORMAT)(int32 selector,\r
+                   void *story_file, int32 extent,\r
+                   void *output, int32 output_extent)\r
+{\r
+ int32 ll, csf;\r
+ if ((TREATY_SELECTOR_INPUT & selector) &&\r
+     (csf=claim_story_file(story_file, extent))<NO_REPLY_RV)\r
+         return INVALID_STORY_FILE_RV;\r
\r
+\r
+ if ((TREATY_SELECTOR_OUTPUT & selector) &&\r
+     (output_extent ==0 ||\r
+     output==NULL))\r
+        return INVALID_USAGE_RV;\r
+ switch(selector)\r
+ {\r
+  case GET_HOME_PAGE_SEL:\r
+                ASSERT_OUTPUT_SIZE((signed) strlen(HOME_PAGE)+1);\r
+                strcpy((char *) output,HOME_PAGE);\r
+                return NO_REPLY_RV;\r
+  case GET_FORMAT_NAME_SEL:\r
+                ASSERT_OUTPUT_SIZE(512);\r
+                strncpy((char *) output,STRFRY(FORMAT),output_extent-1);\r
+                return NO_REPLY_RV;\r
+  case GET_FILE_EXTENSIONS_SEL:\r
+                ll=(strlen(FORMAT_EXT)+1) < 512 ? (strlen(FORMAT_EXT)+1):512;\r
+                ASSERT_OUTPUT_SIZE(ll);\r
+                strncpy((char *) output, FORMAT_EXT, output_extent);\r
+                return NO_REPLY_RV;\r
+  case CLAIM_STORY_FILE_SEL:\r
+                return csf;\r
+  case GET_STORY_FILE_METADATA_EXTENT_SEL:\r
+#ifndef NO_METADATA\r
+                return get_story_file_metadata_extent(story_file, extent);\r
+#endif\r
+  case GET_STORY_FILE_METADATA_SEL:\r
+#ifndef NO_METADATA\r
+                return get_story_file_metadata(story_file, extent, (char *)output, output_extent);\r
+#else\r
+                return NO_REPLY_RV;\r
+#endif\r
+  case GET_STORY_FILE_COVER_EXTENT_SEL:\r
+#ifndef NO_COVER\r
+                return get_story_file_cover_extent(story_file, extent);\r
+#endif\r
+  case GET_STORY_FILE_COVER_FORMAT_SEL:\r
+#ifndef NO_COVER\r
+                return get_story_file_cover_format(story_file, extent);\r
+#endif\r
+  case GET_STORY_FILE_COVER_SEL:\r
+#ifndef NO_COVER\r
+                return get_story_file_cover(story_file, extent, output, output_extent);\r
+#else\r
+                return NO_REPLY_RV;\r
+#endif\r
+  case GET_STORY_FILE_IFID_SEL:\r
+                return get_story_file_IFID(story_file, extent, (char *)output, output_extent);\r
+  case GET_STORY_FILE_EXTENSION_SEL:\r
+                return get_story_file_extension(story_file, extent, (char *)output, output_extent);\r
+#ifdef CONTAINER_FORMAT\r
+  case CONTAINER_GET_STORY_FORMAT_SEL:\r
+                return get_story_format(story_file, extent, (char *)output, output_extent);\r
+  case CONTAINER_GET_STORY_EXTENT_SEL:\r
+                return get_story_extent(story_file, extent);\r
+  case CONTAINER_GET_STORY_FILE_SEL:\r
+                return get_story_file(story_file, extent, output, output_extent);\r
+#endif\r
+\r
+ }\r
+ return UNAVAILABLE_RV;\r
+}\r
+\r
+\r
+#else\r
+#error "treaty_builder should be used as most once in any source file";\r
+#endif\r