summaryrefslogtreecommitdiffstats
path: root/m_option.h
blob: ae386c0195fd50402d672850581d34cbe59ee789 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#ifndef _M_OPTION_H
#define _M_OPTION_H

typedef struct m_option_type m_option_type_t;
typedef struct m_option m_option_t;
struct m_struct_st;

///////////////////////////// Options types declarations ////////////////////////////

// Simple types
extern m_option_type_t m_option_type_flag;
extern m_option_type_t m_option_type_int;
extern m_option_type_t m_option_type_float;
extern m_option_type_t m_option_type_string;
extern m_option_type_t m_option_type_string_list;
extern m_option_type_t m_option_type_position;

extern m_option_type_t m_option_type_print;
extern m_option_type_t m_option_type_print_indirect;
extern m_option_type_t m_option_type_subconfig;
extern m_option_type_t m_option_type_imgfmt;

// Func based types 
extern m_option_type_t m_option_type_func_full;
extern m_option_type_t m_option_type_func_param;
extern m_option_type_t m_option_type_func;

typedef void (*m_opt_default_func_t)(m_option_t *, char*);
typedef int (*m_opt_func_full_t)(m_option_t *, char *, char *);
typedef int (*m_opt_func_param_t)(m_option_t *, char *);
typedef int (*m_opt_func_t)(m_option_t *);
///////////// Backward compat
typedef m_opt_default_func_t cfg_default_func_t;
typedef m_opt_func_full_t cfg_func_arg_param_t;
typedef m_opt_func_param_t cfg_func_param_t;
typedef m_opt_func_t cfg_func_t;

typedef struct {
  void** list;
  void* name_off;
  void* info_off;
  void* desc_off;
} m_obj_list_t;

typedef struct {
  char* name;
  char** attribs;
} m_obj_settings_t;
extern m_option_type_t m_option_type_obj_settings_list;

// Presets are mean to be used with options struct


typedef struct {
  struct m_struct_st* in_desc;
  struct m_struct_st* out_desc;
  void* presets; // Pointer to an arry of struct defined by in_desc
  void* name_off; // Offset of the preset name inside the in_struct
} m_obj_presets_t;
extern m_option_type_t m_option_type_obj_presets;

extern m_option_type_t m_option_type_custom_url;

typedef struct {
  struct m_struct_st* desc; // Fields description
  char separator; // Field separator to use
} m_obj_params_t;
extern m_option_type_t m_option_type_obj_params;

typedef struct {
  int start;
  int end;
} m_span_t;
extern m_obj_params_t m_span_params_def;


// FIXME: backward compatibility
#define CONF_TYPE_FLAG		(&m_option_type_flag)
#define CONF_TYPE_INT		(&m_option_type_int)
#define CONF_TYPE_FLOAT		(&m_option_type_float)
#define CONF_TYPE_STRING	(&m_option_type_string)
#define CONF_TYPE_FUNC		(&m_option_type_func)
#define CONF_TYPE_FUNC_PARAM	(&m_option_type_func_param)
#define CONF_TYPE_PRINT		(&m_option_type_print)
#define CONF_TYPE_PRINT_INDIRECT (&m_option_type_print_indirect)
#define CONF_TYPE_FUNC_FULL	(&m_option_type_func_full)
#define CONF_TYPE_SUBCONFIG	(&m_option_type_subconfig)
#define CONF_TYPE_STRING_LIST	(&m_option_type_string_list)
#define CONF_TYPE_POSITION	(&m_option_type_position)
#define CONF_TYPE_IMGFMT	(&m_option_type_imgfmt)
#define CONF_TYPE_SPAN		(&m_option_type_span)
#define CONF_TYPE_OBJ_SETTINGS_LIST (&m_option_type_obj_settings_list)
#define CONF_TYPE_OBJ_PRESETS	(&m_option_type_obj_presets)
#define CONF_TYPE_CUSTOM_URL	(&m_option_type_custom_url)
#define CONF_TYPE_OBJ_PARAMS	(&m_option_type_obj_params)

/////////////////////////////////////////////////////////////////////////////////////////////

struct m_option_type {
  char* name;
  char* comments; // syntax desc, etc
  unsigned int size; // size needed for a save slot
  unsigned int flags;

  // parse is the only requiered function all others can be NULL
  // If dst if non-NULL it should create/update the save slot
  // If dst is NULL it should just test the validity of the arg if possible
  // Src tell from where come this setting (ie cfg file, command line, playlist, ....
  // It should return 1 if param was used, 0 if not.
  // On error it must return 1 of the error code below
  int (*parse)(m_option_t* opt,char *name, char *param, void* dst, int src);
  // Print back a value in human form
  char* (*print)(m_option_t* opt,  void* val);

  // These 3 will be a memcpy in 50% of the case, it's called to save/restore the status of
  // the var it's there for complex type like CONF_TYPE_FUNC*
  // update a save slot (dst) from the current value in the prog (src)
  void (*save)(m_option_t* opt,void* dst, void* src);
  // set the current value (dst) from a save slot
  void (*set)(m_option_t* opt,void* dst, void* src);
  // Copy betewen 2 slot (if NULL and size > 0 a memcpy will be used
  void (*copy)(m_option_t* opt,void* dst, void* src);
  // Free the data allocated for a save slot if needed
  void (*free)(void* dst);
};

struct m_option {
  char *name;
  void *p; 
  m_option_type_t* type;
  unsigned int flags;
  double min,max;
  // This used to be function pointer to hold a 'reverse to defaults' func.
  // Nom it can be used to pass any type of extra args.
  // Passing a 'default func' is still valid for all func based option types
  void* priv; // Type dependent data (for all kind of extended setting)
};


//////////////////////////////// Option flags /////////////////////////////////

// Option flags
#define M_OPT_MIN		(1<<0)
#define M_OPT_MAX		(1<<1)
#define M_OPT_RANGE		(M_OPT_MIN|M_OPT_MAX)
#define M_OPT_NOCFG		(1<<2)
#define M_OPT_NOCMD		(1<<3)
// This option is global : it won't be saved on push and the command
// line parser will set it when it's parsed (ie. it won't be set later)
// e.g options : -v, -quiet
#define M_OPT_GLOBAL		(1<<4)
// Do not save this option : it won't be saved on push but the command
// line parser will put it with it's entry (ie : it may be set later)
// e.g options : -include
#define M_OPT_NOSAVE		(1<<5)
// Emulate old behaviour by pushing the option only if it was set by the user
#define M_OPT_OLD		(1<<6)

// FIXME: backward compatibility
#define CONF_MIN		M_OPT_MIN
#define CONF_MAX		M_OPT_MAX
#define CONF_RANGE		M_OPT_RANGE
#define CONF_NOCFG		M_OPT_NOCFG
#define CONF_NOCMD		M_OPT_NOCMD
#define CONF_GLOBAL		M_OPT_GLOBAL
#define CONF_NOSAVE		M_OPT_NOSAVE
#define CONF_OLD		M_OPT_OLD


///////////////////////////// Option type flags ///////////////////////////////////

// These flags are for the parsers. The description here apply to the m_config_t
// based parsers (ie. cmd line and config file parsers)
// Some parser will refuse option types that have some of these flags

// This flag is used for the subconfig
// When this flag is set, opt->p should point to another m_option_t array
// Only the parse function will be called. If dst is set, it should create/update
// an array of char* containg opt/val pairs.
// Then the options in the child array will then be set automaticly.
// You can only affect the way suboption are parsed.
// Also note that suboptions may be directly accessed by using -option:subopt blah :-)
#define M_OPT_TYPE_HAS_CHILD		(1<<0)
// If this flag is set the option type support option name with * at the end (used for -aa*)
// This only affect the option name matching, the option type have to implement
// the needed stuff.
#define M_OPT_TYPE_ALLOW_WILDCARD	(1<<1)
// This flag indicate that the data is dynamicly allocated (opt->p point to a pointer)
// It enable a little hack wich replace the initial value by a dynamic copy
// in case the initial value is staticly allocated (pretty common with strings)
#define M_OPT_TYPE_DYNAMIC		(1<<2)
/// If this is set the parse function doesn't directly return
// the wanted thing. Options use this if for some reasons they have to wait
// until the set call to be able to correctly set the target var.
// So for those types you have to first parse and then set the target var
// If this flag isn't set you can parse directly to the target var
// It's used for the callback based option as the callback call may append
// later on.
#define M_OPT_TYPE_INDIRECT		(1<<3)


///////////////////////////// Parser flags ////////////////////////////////////////

// Config mode : some parser type behave differently depending
// on config->mode value wich is passed in the src param of parse()
#define M_CONFIG_FILE 0
#define M_COMMAND_LINE 1

// Option parser error code
#define M_OPT_UNKNOWN		-1
#define M_OPT_MISSING_PARAM	-2
#define M_OPT_INVALID		-3
#define M_OPT_OUT_OF_RANGE	-4
#define M_OPT_PARSER_ERR	-5
#define M_OPT_EXIT              -6

// FIXME: backward compatibility
#define ERR_NOT_AN_OPTION	M_OPT_UNKNOWN
#define ERR_MISSING_PARAM	M_OPT_MISSING_PARAM
#define ERR_OUT_OF_RANGE	M_OPT_OUT_OF_RANGE
#define ERR_FUNC_ERR		M_OPT_PARSER_ERR

m_option_t* m_option_list_find(m_option_t* list,char* name);

inline static int
m_option_parse(m_option_t* opt,char *name, char *param, void* dst, int src) {
  return opt->type->parse(opt,name,param,dst,src);
}

inline static  char*
m_option_print(m_option_t* opt,  void* val_ptr) {
  if(opt->type->print)
    return opt->type->print(opt,val_ptr);
  else
    return (char*)-1;
}

inline static  void
m_option_save(m_option_t* opt,void* dst, void* src) {
  if(opt->type->save)
    opt->type->save(opt,dst,src);
}

inline static  void
m_option_set(m_option_t* opt,void* dst, void* src) {
  if(opt->type->set)
    opt->type->set(opt,dst,src);
}

inline  static void
m_option_copy(m_option_t* opt,void* dst, void* src) {
  if(opt->type->copy)
    opt->type->set(opt,dst,src);
  else if(opt->type->size > 0)
    memcpy(dst,src,opt->type->size);
}

inline static void
m_option_free(m_option_t* opt,void* dst) {
  if(opt->type->free)
    opt->type->free(dst);
}

#endif /* _M_OPTION_H */