1 /* General purpose, i.e. non SoX specific, utility functions.
2 * Copyright (c) 2007-8 robs@users.sourceforge.net
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or (at
7 * your option) any later version.
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 int lsx_strcasecmp(const char * s1
, const char * s2
)
25 #if defined(HAVE_STRCASECMP)
26 return strcasecmp(s1
, s2
);
27 #elif defined(_MSC_VER)
28 return _stricmp(s1
, s2
);
30 while (*s1
&& (toupper(*s1
) == toupper(*s2
)))
32 return toupper(*s1
) - toupper(*s2
);
36 int lsx_strncasecmp(char const * s1
, char const * s2
, size_t n
)
38 #if defined(HAVE_STRCASECMP)
39 return strncasecmp(s1
, s2
, n
);
40 #elif defined(_MSC_VER)
41 return _strnicmp(s1
, s2
, n
);
43 while (--n
&& *s1
&& (toupper(*s1
) == toupper(*s2
)))
45 return toupper(*s1
) - toupper(*s2
);
49 sox_bool
lsx_strends(char const * str
, char const * end
)
51 size_t str_len
= strlen(str
), end_len
= strlen(end
);
52 return str_len
>= end_len
&& !strcmp(str
+ str_len
- end_len
, end
);
55 char const * lsx_find_file_extension(char const * pathname
)
57 /* First, chop off any path portions of filename. This
58 * prevents the next search from considering that part. */
59 char const * result
= LAST_SLASH(pathname
);
63 /* Now look for an filename extension */
64 result
= strrchr(result
, '.');
70 lsx_enum_item
const * lsx_find_enum_text(char const * text
, lsx_enum_item
const * enum_items
, int flags
)
72 lsx_enum_item
const * result
= NULL
; /* Assume not found */
73 sox_bool sensitive
= !!(flags
& lsx_find_enum_item_case_sensitive
);
75 while (enum_items
->text
) {
76 if ((!sensitive
&& !strcasecmp(text
, enum_items
->text
)) ||
77 ( sensitive
&& ! strcmp(text
, enum_items
->text
)))
78 return enum_items
; /* Found exact match */
79 if ((!sensitive
&& !strncasecmp(text
, enum_items
->text
, strlen(text
))) ||
80 ( sensitive
&& ! strncmp(text
, enum_items
->text
, strlen(text
)))) {
81 if (result
!= NULL
&& result
->value
!= enum_items
->value
)
82 return NULL
; /* Found ambiguity */
83 result
= enum_items
; /* Found sub-string match */
90 lsx_enum_item
const * lsx_find_enum_value(unsigned value
, lsx_enum_item
const * enum_items
)
92 for (;enum_items
->text
; ++enum_items
)
93 if (value
== enum_items
->value
)
98 int lsx_enum_option(int c
, char const * arg
, lsx_enum_item
const * items
)
100 lsx_enum_item
const * p
= lsx_find_enum_text(arg
, items
, sox_false
);
103 char * set
= lsx_malloc(len
);
105 for (p
= items
; p
->text
; ++p
) {
106 set
= lsx_realloc(set
, len
+= 2 + strlen(p
->text
));
107 strcat(set
, ", "); strcat(set
, p
->text
);
109 lsx_fail("-%c: `%s' is not one of: %s.", c
, arg
, set
+ 2);
116 char const * lsx_sigfigs3(double number
)
118 static char const symbols
[] = "\0kMGTPEZY";
119 static char string
[16][10]; /* FIXME: not thread-safe */
120 static unsigned n
; /* ditto */
122 sprintf(string
[n
= (n
+1) & 15], "%#.3g", number
);
123 switch (sscanf(string
[n
], "%u.%ue%u", &a
, &b
, &c
)) {
124 case 2: if (b
) return string
[n
]; /* Can fall through */
125 case 1: c
= 2; break;
126 case 3: a
= 100*a
+ b
; break;
128 if (c
< array_length(symbols
) * 3 - 3) switch (c
%3) {
129 case 0: sprintf(string
[n
], "%u.%02u%c", a
/100,a
%100, symbols
[c
/3]); break;
130 case 1: sprintf(string
[n
], "%u.%u%c" , a
/10 ,a
%10 , symbols
[c
/3]); break;
131 case 2: sprintf(string
[n
], "%u%c" , a
, symbols
[c
/3]); break;
136 char const * lsx_sigfigs3p(double percentage
)
138 static char string
[16][10];
140 sprintf(string
[n
= (n
+1) & 15], "%.1f%%", percentage
);
141 if (strlen(string
[n
]) < 5)
142 sprintf(string
[n
], "%.2f%%", percentage
);
143 else if (strlen(string
[n
]) > 5)
144 sprintf(string
[n
], "%.0f%%", percentage
);
148 int lsx_open_dllibrary(
149 int show_error_on_failure
,
150 const char* library_description
,
151 const char* const library_names
[] UNUSED
,
152 const lsx_dlfunction_info func_infos
[],
153 lsx_dlptr selected_funcs
[],
157 lsx_dlhandle dl
= NULL
;
159 /* Track enough information to give a good error message about one failure.
160 * Let failed symbol load override failed library open, and let failed
161 * library open override missing static symbols.
163 const char* failed_libname
= NULL
;
164 const char* failed_funcname
= NULL
;
167 if (library_names
&& library_names
[0])
169 const char* const* libname
;
173 "Unable to load %s - failed to initialize ltdl.",
174 library_description
);
178 for (libname
= library_names
; *libname
; libname
++)
180 lsx_debug("Attempting to open %s (%s).", library_description
, *libname
);
181 dl
= lt_dlopenext(*libname
);
185 lsx_debug("Opened %s (%s).", library_description
, *libname
);
186 for (i
= 0; func_infos
[i
].name
; i
++)
188 union {lsx_dlptr fn
; lt_ptr ptr
;} func
;
189 func
.ptr
= lt_dlsym(dl
, func_infos
[i
].name
);
190 selected_funcs
[i
] = func
.fn
? func
.fn
: func_infos
[i
].stub_func
;
191 if (!selected_funcs
[i
])
195 failed_libname
= *libname
;
196 failed_funcname
= func_infos
[i
].name
;
197 lsx_debug("Cannot use %s (%s) - missing function \"%s\".", library_description
, failed_libname
, failed_funcname
);
205 else if (!failed_libname
)
207 failed_libname
= *libname
;
214 #endif /* HAVE_LIBLTDL */
219 for (i
= 0; func_infos
[i
].name
; i
++)
222 func_infos
[i
].static_func
223 ? func_infos
[i
].static_func
224 : func_infos
[i
].stub_func
;
225 if (!selected_funcs
[i
])
229 failed_libname
= "static";
230 failed_funcname
= func_infos
[i
].name
;
242 for (i
= 0; func_infos
[i
].name
; i
++)
243 selected_funcs
[i
] = NULL
;
245 #define LTDL_MISSING ""
247 #define LTDL_MISSING " (Dynamic library support not configured.)"
248 #endif /* HAVE_LIBLTDL */
251 if (show_error_on_failure
)
253 "Unable to load %s (%s) function \"%s\"." LTDL_MISSING
,
259 "Unable to load %s (%s) function \"%s\"." LTDL_MISSING
,
264 else if (failed_libname
)
266 if (show_error_on_failure
)
268 "Unable to load %s (%s)." LTDL_MISSING
,
273 "Unable to load %s (%s)." LTDL_MISSING
,
279 if (show_error_on_failure
)
281 "Unable to load %s - no dynamic library names selected." LTDL_MISSING
,
282 library_description
);
285 "Unable to load %s - no dynamic library names selected." LTDL_MISSING
,
286 library_description
);
294 void lsx_close_dllibrary(
295 lsx_dlhandle dl UNUSED
)
303 #endif /* HAVE_LIBLTDL */