libamxo  4.3.4
Object Definition Language (ODL) parsing
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
Function resolvers
Collaboration diagram for Function resolvers:

Modules

 Function Table Resolver API
 
 Import Resolver API
 

Macros

#define AMXO_FUNC(x)   ((amxo_fn_ptr_t) x)
 Function ponter caster macro. More...
 

Functions

int amxo_register_resolver (const char *name, amxo_resolver_t *resolver)
 Registers a function resolver. More...
 
int amxo_unregister_resolver (const char *name)
 Unregisters a function resolver. More...
 
amxc_htable_t * amxo_parser_claim_resolver_data (amxo_parser_t *parser, const char *resolver_name)
 Fetches resolver specific data for a parser instance. More...
 
amxc_htable_t * amxo_parser_get_resolver_data (amxo_parser_t *parser, const char *resolver_name)
 Gets the resolver specific parser data. More...
 
void amxo_parser_remove_resolver_data (amxo_parser_t *parser, const char *resolver_name)
 Removes the resolver specific parser data. More...
 

Detailed Description

Default Function Resolvers

The odl parser can resolve functions for a data model functions. By default the odl parser supports the following function resolvers:

In the odl file, the odl parser can be instructed to use a specific function resolver. After each function definition a resolver directive can be placed. Such a resolver directive starts with "<!" and ends with "!>".

In between the name of the resolver and optionally extra resolver data can be placed. The resolver data is specific for each resolver, please read the documentation of the resolver itself.

Default resolver names:

If no resolver directive is specified, the automatic resolver is used.

If a resolver directive is specified, the resolver is used, no other resolvers are used.

If a data model can not be resolved, the odl parser continues and the data model method exists, but will not have an implementation.

object Greeter {
uint32 say(%in %mandatory string message) <!ftab:dump!>;
}
}
static amxo_resolver_t ftab
define
Definition: main.odl:1

Function Table Resolver

To make it possible for the odl parser to use the function table resolver, the function table must be supplied with function pointers, prior to start parsing an odl file.

To supply the function pointers use amxo_resolver_ftab_add

Function Table Resolver Directive

ftab_directive_format

<!ftab:FUNCTION NAME>

The function name is optional, if not given the name of the function specified in the odl file is used.

ftab_directive_examples

Search a function implementation for the data model method "say" in the function table resolver, with name "say.

object Greeter {
uint32 say(%in %mandatory string message) <!ftab!>;
}
}

Search a function implementation for the data model method "say" in the function table resolver, with name "dump".

object Greeter {
uint32 say(%in %mandatory string message) <!ftab:dump!>;
}
}

Example

In this example, a "say" data model method is defined in the odl file under the object "Greeter". The odl parser can automatically bind a C implementation to this data model method by using the function table resolver.

Example odl file

object Greeter {
uint32 say(%in %mandatory string message);
}
}

Example C implementation

static amxd_status_t _greeter_say(amxd_object_t *object,
AMXB_UNUSED amxd_function_t *func,
amxc_var_t *args,
amxc_var_t *ret) {
amxd_status_t status = amxd_status_unknown_error;
amxc_var_t *msg = amxc_var_get_key(args, "message", AMXC_VAR_FLAG_DEFAULT);
char *msg_txt = amxc_var_dyncast(cstring_t, msg);
printf("==> %s says '%s'\n", from_txt, msg_txt);
fflush(stdout);
status = amxd_status_ok;
exit:
free(msg_txt);
return status;
}
int create_data_model(amxd_dm_t *dm) {
int retval = 0;
amxo_parser_t parser;
amxd_object_t *root = amxd_dm_get_root(dm);
amxo_parser_init(&parser);
amxo_parser_ftab_add(&parser, "say", AMXO_FUNC(_greeter_say));
retval = amxo_parser_parse_file(&parser, "greeter_main.odl", root);
return retval;
}
void amxo_parser_clean(amxo_parser_t *parser)
Cleans up the odl parser instance.
int amxo_parser_parse_file(amxo_parser_t *parser, const char *file_path, amxd_object_t *object)
Parses an odl file.
int amxo_parser_init(amxo_parser_t *parser)
Initializes a new odl parser instance.
#define AMXO_FUNC(x)
Function ponter caster macro.
Definition: amxo_types.h:80
The ODL parser structure.
Definition: amxo_types.h:245

Macro Definition Documentation

◆ AMXO_FUNC

#define AMXO_FUNC (   x)    ((amxo_fn_ptr_t) x)

Function ponter caster macro.

Parameters
xC function pointer

Definition at line 80 of file amxo_types.h.

Function Documentation

◆ amxo_parser_claim_resolver_data()

amxc_htable_t* amxo_parser_claim_resolver_data ( amxo_parser_t parser,
const char *  resolver_name 
)

Fetches resolver specific data for a parser instance.

Allocates or returns the resolver specific data for the parser instance. Each parser instance can keep resolver specific data. This function is typically called in the API functions provided by the resolver.

When there already was a data table for the function resolver available, due to a previous call to this function, that pointer is returned.

A hash table is allocated, the data stored in this table is up to the function resolver implementation.

Warning
Do not delete the table. Deleting the table (or clear all data) can be done in the "clean" method, see amxo_register_resolver.
Parameters
parserthe odl parser instance
resolver_namename of the resolver
Returns
pointer to a hash table or NULL if allocating fails.

Definition at line 167 of file amxo_resolver_mngr.c.

168  {
169  amxc_htable_t* data_table = NULL;
170  amxo_res_data_t* resolver_data = NULL;
171  amxc_htable_it_t* it = NULL;
172  when_null(parser, exit);
173  when_str_empty(resolver_name, exit);
174  when_null(amxc_htable_get(&resolvers, resolver_name), exit);
175 
176  if(parser->resolvers == NULL) {
177  amxc_htable_new(&parser->resolvers, 10);
178  when_null(parser->resolvers, exit);
179  }
180 
181  it = amxc_htable_get(parser->resolvers, resolver_name);
182  if(it == NULL) {
183  resolver_data = (amxo_res_data_t*) calloc(1, sizeof(amxo_res_data_t));
184  when_null(resolver_data, exit);
185  amxc_htable_init(&resolver_data->data, 10);
186  amxc_htable_insert(parser->resolvers, resolver_name, &resolver_data->hit);
187  } else {
188  resolver_data = amxc_htable_it_get_data(it, amxo_res_data_t, hit);
189  }
190 
191  data_table = &resolver_data->data;
192 
193 exit:
194  return data_table;
195 }
static amxc_htable_t resolvers
amxc_htable_t * resolvers
Definition: amxo_types.h:269
amxc_htable_it_t hit
amxc_htable_t data

◆ amxo_parser_get_resolver_data()

amxc_htable_t* amxo_parser_get_resolver_data ( amxo_parser_t parser,
const char *  resolver_name 
)

Gets the resolver specific parser data.

Returns the function resolver specific data for the given parser. If no such data is available it will return a NULL pointer

This function will not allocate a table if there is no available. Use amxo_parser_claim_resolver_data to allocate a resolver data table.

Warning
Do not delete the table. Deleting the table (or clear all data) can be done in the "clean" method, see amxo_register_resolver.
Parameters
parserthe odl parser instance
resolver_namename of the resolver
Returns
pointer to a hash table or NULL if allocating fails.

Definition at line 197 of file amxo_resolver_mngr.c.

198  {
199  amxc_htable_t* data_table = NULL;
200  amxo_res_data_t* resolver_data = NULL;
201  amxc_htable_it_t* it = NULL;
202  when_null(parser, exit);
203  when_str_empty(resolver_name, exit);
204  when_null(parser->resolvers, exit);
205  when_null(amxc_htable_get(&resolvers, resolver_name), exit);
206 
207  it = amxc_htable_get(parser->resolvers, resolver_name);
208  when_null(it, exit);
209  resolver_data = amxc_htable_it_get_data(it, amxo_res_data_t, hit);
210  data_table = &resolver_data->data;
211 
212 exit:
213  return data_table;
214 }

◆ amxo_parser_remove_resolver_data()

void amxo_parser_remove_resolver_data ( amxo_parser_t parser,
const char *  resolver_name 
)

Removes the resolver specific parser data.

Removes the resolver specific data. If the resolver allocated memory for the resolver specific data it is the responsibility of the resolver to free the allocated memory for the data before removing it from the parser context

Parameters
parserthe odl parser instance
resolver_namename of the resolver

Definition at line 216 of file amxo_resolver_mngr.c.

217  {
218  amxo_res_data_t* resolver_data = NULL;
219  amxc_htable_it_t* it = NULL;
220  when_null(parser, exit);
221  when_str_empty(resolver_name, exit);
222  when_null(parser->resolvers, exit);
223  when_null(amxc_htable_get(&resolvers, resolver_name), exit);
224 
225  it = amxc_htable_get(parser->resolvers, resolver_name);
226  when_null(it, exit);
227  resolver_data = amxc_htable_it_get_data(it, amxo_res_data_t, hit);
228  amxc_htable_it_take(&resolver_data->hit);
229  amxc_htable_it_clean(&resolver_data->hit, NULL);
230  free(resolver_data);
231 
232 exit:
233  return;
234 }

◆ amxo_register_resolver()

int amxo_register_resolver ( const char *  name,
amxo_resolver_t resolver 
)

Registers a function resolver.

The odl parser provides already two function resolvers. In most cases this is sufficient. Extra resolvers can be registered using this function.

The resolver must at least provide the "resolve" method, the other two are optional ("get" and "clean").

The "resolve" method is called during the parsing of odl files. The "get" method is called when a parser is initializing to fetch all default configuration options for the function resolver. The "clean" method is called when parsing is done. In this method the resolver can clean-up stuff that was allocated during function resolving.

A function resolver is typically implemented in a library and can provide extra API functions. The default "ftab" and "import" resolvers are providing extra API functions see amxo_resolver_ftab_add, amxo_resolver_ftab_remove, amxo_resolver_ftab_clear, amxo_resolver_import_open and amxo_resolver_import_close_all. A custom function resolver can do the same, so it is easier for an application developer to use your function resolver.

The name of the resolver must be unique.

Parameters
nameof the resolver, must match the name used in the odl files
resolverthe resolver implementation function table
Returns
Retruns 0 when the function is added to the function table.

Definition at line 137 of file amxo_resolver_mngr.c.

138  {
139  int retval = -1;
140  when_null(resolver, exit);
141  when_true(!amxd_name_is_valid(name), exit);
142  when_not_null(amxc_htable_get(&resolvers, name), exit);
143  when_null(resolver->resolve, exit);
144 
145  amxc_htable_insert(&resolvers, name, &resolver->hit);
146 
147  retval = 0;
148 
149 exit:
150  return retval;
151 }
amxo_res_resolve_fn_t resolve
Definition: amxo_types.h:103
amxc_htable_it_t hit
Definition: amxo_types.h:101

◆ amxo_unregister_resolver()

int amxo_unregister_resolver ( const char *  name)

Unregisters a function resolver.

Removes the function resolver. After removing the resolver can not be used in any parsing anymore until it is re-added.

It is not recommended to unregister a function resolver during parsing, for example in parser hooks.

Parameters
nameof the resolver
Returns
Retruns 0 when the function is added to the function table.

Definition at line 153 of file amxo_resolver_mngr.c.

153  {
154  int retval = -1;
155  amxc_htable_it_t* hit = NULL;
156  when_str_empty(name, exit);
157 
158  hit = amxc_htable_get(&resolvers, name);
159  when_null(hit, exit);
160  amxc_htable_it_clean(hit, NULL);
161 
162  retval = 0;
163 exit:
164  return retval;
165 }