Make sure PLUGINDIR is defined
[projects/chimara/chimara.git] / babel / treaty_builder.h
1 /* treaty_builder.h common macros to build a treaty module\r
2  *\r
3  * 2006 By L. Ross Raszewski\r
4  *\r
5  * This file is public domain, but be aware that any changes to it may\r
6  * cause it to cease to be compliant with the Treaty of Babel.\r
7  *\r
8  * This file depends on treaty.h\r
9  *\r
10  * The purpose of this file is to simplify the building of a treaty\r
11  * module.  It automatically generates a generic treaty function.\r
12  *\r
13  * Usage:\r
14  *\r
15  * #define the following values:\r
16  *  FORMAT              The treaty name of the format\r
17  *  HOME_PAGE           A string containing the URL of the format home page\r
18  *  FORMAT_EXT          A string containing a comma separated list of common\r
19  *                       extensions for game files in this format\r
20  *  NO_METADATA         If the format does not support metadata\r
21  *  NO_COVER            If the format does not support cover art\r
22  *  CUSTOM_EXTENSION    If game files should not always use the first listed extension\r
23  *\r
24  * (Note: Formats which support metadata and cover art via a container should\r
25  * define NO_METADATA and NO_COVER as container support is handled separately)\r
26  *\r
27  * #include "treaty_builder.h"\r
28  * Define the following functions:\r
29  *   static int32 get_story_file_IFID(void *, int32, char *, int32);\r
30  *   static int32 claim_story_file(void *, int32);\r
31  * Define the following functions if NO_METADATA is not defined:\r
32  *   static int32 get_story_file_metadata_extent(void *, int32);\r
33  *   static int32 get_story_file_metadata(void *, int32, char *, int32);\r
34  * Define the following functions if NO_COVER is not defined\r
35  *   static int32 get_story_file_cover_extent(void *, int32);\r
36  *   static int32 get_story_file_cover_format(void *, int32);\r
37  *   static int32 get_story_file_cover(void *, int32, void *, int32);\r
38  * Define the following if CUSTOM_EXTENSION is defined\r
39  *   static int32 get_story_file_extension(void *, int32, char *, int32);\r
40  *\r
41  * The two-parameter functions take the story file and story file extent\r
42  * as parameters.  The four-parameter ones also take the output\r
43  * buffer and its extent.  They perform the corresponding task to the\r
44  * similarly-named selector.\r
45  *\r
46  * This file also defines the macro ASSERT_OUTPUT_SIZE(x) which\r
47  * returns INVALID_USAGE_RV if output_extent is less than x.\r
48  *\r
49  * #define CONTAINER_FORMAT  before inclusion to generate a container\r
50  * module.  A container module should define three additional functions:\r
51  *    static int32 get_story_format(void *, int32, char *, int32);\r
52  *    static int32 get_story_extent(void *, int32);\r
53  *    static int32 get_story_file(void *, int32, void *, int32);\r
54  *\r
55  */\r
56 \r
57 #ifndef TREATY_BUILDER\r
58 #define TREATY_BUILDER\r
59 \r
60 #include "treaty.h"\r
61 #include <string.h>\r
62 \r
63 #define ASSERT_OUTPUT_SIZE(x) do { if (output_extent < (x)) return INVALID_USAGE_RV; } while (0)\r
64 \r
65 #ifndef NO_METADATA\r
66 static int32 get_story_file_metadata_extent(void *, int32);\r
67 static int32 get_story_file_metadata(void *, int32, char *, int32);\r
68 #endif\r
69 #ifndef NO_COVER\r
70 static int32 get_story_file_cover_extent(void *, int32);\r
71 static int32 get_story_file_cover_format(void *, int32);\r
72 static int32 get_story_file_cover(void *, int32, void *, int32);\r
73 #endif\r
74 static int32 get_story_file_IFID(void *, int32, char *, int32);\r
75 static int32 claim_story_file(void *, int32);\r
76 #ifdef CONTAINER_FORMAT\r
77 static int32 get_story_file(void *, int32, void *, int32);\r
78 static int32 get_story_format(void *, int32, char *, int32);\r
79 static int32 get_story_extent(void *, int32);\r
80 #endif\r
81 #ifdef CUSTOM_EXTENSION\r
82 static int32 get_story_file_extension(void *, int32, char *, int32);\r
83 #else\r
84 #include <stdio.h>\r
85 static int32 get_story_file_extension(void *sf, int32 extent, char *out, int32 output_extent)\r
86 {\r
87  int i;\r
88 \r
89  if (!sf || !extent) return INVALID_STORY_FILE_RV;\r
90 \r
91  for(i=0;FORMAT_EXT[i] && FORMAT_EXT[i]!=',';i++);\r
92  ASSERT_OUTPUT_SIZE(i+1);\r
93  memcpy(out,FORMAT_EXT,i);\r
94  out[i]=0;\r
95  return strlen(out);\r
96 }\r
97 \r
98 #endif\r
99 \r
100 #define TREATY_FUNCTION(X)  DEEP_TREATY_FUNCTION(X)\r
101 #define DEEP_TREATY_FUNCTION(X) X ## _treaty\r
102 #define dSTRFRY(X) #X\r
103 #define STRFRY(X) dSTRFRY(X)\r
104 \r
105 int32 TREATY_FUNCTION(FORMAT)(int32 selector,\r
106                    void *story_file, int32 extent,\r
107                    void *output, int32 output_extent)\r
108 {\r
109  int32 ll, csf;\r
110  if ((TREATY_SELECTOR_INPUT & selector) &&\r
111      (csf=claim_story_file(story_file, extent))<NO_REPLY_RV)\r
112          return INVALID_STORY_FILE_RV;\r
113  \r
114 \r
115  if ((TREATY_SELECTOR_OUTPUT & selector) &&\r
116      (output_extent ==0 ||\r
117      output==NULL))\r
118         return INVALID_USAGE_RV;\r
119  switch(selector)\r
120  {\r
121   case GET_HOME_PAGE_SEL:\r
122                 ASSERT_OUTPUT_SIZE((signed) strlen(HOME_PAGE)+1);\r
123                 strcpy((char *) output,HOME_PAGE);\r
124                 return NO_REPLY_RV;\r
125   case GET_FORMAT_NAME_SEL:\r
126                 ASSERT_OUTPUT_SIZE(512);\r
127                 strncpy((char *) output,STRFRY(FORMAT),output_extent-1);\r
128                 return NO_REPLY_RV;\r
129   case GET_FILE_EXTENSIONS_SEL:\r
130                 ll=(strlen(FORMAT_EXT)+1) < 512 ? (strlen(FORMAT_EXT)+1):512;\r
131                 ASSERT_OUTPUT_SIZE(ll);\r
132                 strncpy((char *) output, FORMAT_EXT, output_extent);\r
133                 return NO_REPLY_RV;\r
134   case CLAIM_STORY_FILE_SEL:\r
135                 return csf;\r
136   case GET_STORY_FILE_METADATA_EXTENT_SEL:\r
137 #ifndef NO_METADATA\r
138                 return get_story_file_metadata_extent(story_file, extent);\r
139 #endif\r
140   case GET_STORY_FILE_METADATA_SEL:\r
141 #ifndef NO_METADATA\r
142                 return get_story_file_metadata(story_file, extent, (char *)output, output_extent);\r
143 #else\r
144                 return NO_REPLY_RV;\r
145 #endif\r
146   case GET_STORY_FILE_COVER_EXTENT_SEL:\r
147 #ifndef NO_COVER\r
148                 return get_story_file_cover_extent(story_file, extent);\r
149 #endif\r
150   case GET_STORY_FILE_COVER_FORMAT_SEL:\r
151 #ifndef NO_COVER\r
152                 return get_story_file_cover_format(story_file, extent);\r
153 #endif\r
154   case GET_STORY_FILE_COVER_SEL:\r
155 #ifndef NO_COVER\r
156                 return get_story_file_cover(story_file, extent, output, output_extent);\r
157 #else\r
158                 return NO_REPLY_RV;\r
159 #endif\r
160   case GET_STORY_FILE_IFID_SEL:\r
161                 return get_story_file_IFID(story_file, extent, (char *)output, output_extent);\r
162   case GET_STORY_FILE_EXTENSION_SEL:\r
163                 return get_story_file_extension(story_file, extent, (char *)output, output_extent);\r
164 #ifdef CONTAINER_FORMAT\r
165   case CONTAINER_GET_STORY_FORMAT_SEL:\r
166                 return get_story_format(story_file, extent, (char *)output, output_extent);\r
167   case CONTAINER_GET_STORY_EXTENT_SEL:\r
168                 return get_story_extent(story_file, extent);\r
169   case CONTAINER_GET_STORY_FILE_SEL:\r
170                 return get_story_file(story_file, extent, output, output_extent);\r
171 #endif\r
172 \r
173  }\r
174  return UNAVAILABLE_RV;\r
175 }\r
176 \r
177 \r
178 #else\r
179 #error "treaty_builder should be used as most once in any source file";\r
180 #endif\r