vlc_fixups.h 9.98 KB
Newer Older
1
2
3
/*****************************************************************************
 * fixups.h: portability fixups included from config.h
 *****************************************************************************
4
 * Copyright © 1998-2008 the VideoLAN project
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/**
 * \file
 * This file is a collection of portability fixes
 */

26
27
28
#ifndef LIBVLC_FIXUPS_H
# define LIBVLC_FIXUPS_H 1

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
29
#ifndef HAVE_STRDUP
30
31
32
33
34
# include <string.h>
# include <stdlib.h>
static inline char *strdup (const char *str)
{
    size_t len = strlen (str) + 1;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
35
    char *res = (char *)malloc (len);
36
37
38
    if (res) memcpy (res, str, len);
    return res;
}
39
40
#endif

41
42
43
44
#ifdef WIN32
/* Windows' printf doesn't support %z modifiers, thus we need to rewrite
 * the format string in a wrapper. */
# include <string.h>
45
# include <stdlib.h>
46
47
static inline char *vlc_fix_format_string (const char *format)
{
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
    char *fmt;
# ifdef WIN64
    const char *src = format, *tmp;
    char *dst;
    size_t n = 0;
    while ((tmp = strstr (src, "%z")) != NULL)
    {
        n++;
        src = tmp + 2;
    }
    if (n == 0)
        return NULL;

    fmt = (char*)malloc (strlen (format) + n + 1);
    if (fmt == NULL)
        return NULL;

    src = format;
    dst = fmt;
    while ((tmp = strstr (src, "%z")) != NULL)
    {
        size_t d = tmp - src;
        memcpy (dst, src, d);
        dst += d;
        memcpy (dst, "%ll", 3);
        dst += 3;
        src = tmp + 2;
    }
    strcpy (dst, src);
# else
    char *f;
79
80
81
82
83
84
85
86
87
88
89
    if (strstr (format, "%z") == NULL)
        return NULL;

    fmt = strdup (format);
    if (fmt == NULL)
        return NULL;

    while ((f = strstr (fmt, "%z")) != NULL)
    {
       f[1] = 'l';
    }
90
# endif
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
    return fmt;
}

# include <stdio.h>
# include <stdarg.h>

static inline int vlc_vprintf (const char *format, va_list ap)
{
    char *fmt = vlc_fix_format_string (format);
    int ret = vprintf (fmt ? fmt : format, ap);
    free (fmt);
    return ret;
}
# define vprintf vlc_vprintf

static inline int vlc_vfprintf (FILE *stream, const char *format, va_list ap)
{
    char *fmt = vlc_fix_format_string (format);
    int ret = vfprintf (stream, fmt ? fmt : format, ap);
    free (fmt);
    return ret;
}
# define vfprintf vlc_vfprintf

static inline int vlc_vsprintf (char *str, const char *format, va_list ap)
{
    char *fmt = vlc_fix_format_string (format);
    int ret = vsprintf (str, fmt ? fmt : format, ap);
    free (fmt);
    return ret;
}
# define vsprintf vlc_vsprintf

static inline int vlc_vsnprintf (char *str, size_t size, const char *format, va_list ap)
{
    char *fmt = vlc_fix_format_string (format);
    int ret = vsnprintf (str, size, fmt ? fmt : format, ap);
    free (fmt);
    return ret;
}
# define vsnprintf vlc_vsnprintf

static inline int vlc_printf (const char *format, ...)
{
    va_list ap;
    int ret;
    va_start (ap, format);
    ret = vprintf (format, ap);
    va_end (ap);
    return ret;
}
# define printf(...) vlc_printf(__VA_ARGS__)

static inline int vlc_fprintf (FILE *stream, const char *format, ...)
{
    va_list ap;
    int ret;
    va_start (ap, format);
    ret = vfprintf (stream, format, ap);
    va_end (ap);
    return ret;
}
# define fprintf vlc_fprintf

155
#if 0
156
157
158
159
160
161
162
163
164
165
static inline int vlc_sprintf (char *str, const char *format, ...)
{
    va_list ap;
    int ret;
    va_start (ap, format);
    ret = vsprintf (str, format, ap);
    va_end (ap);
    return ret;
}
# define sprintf vlc_sprintf
166
#endif
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

static inline int vlc_snprintf (char *str, size_t size, const char *format, ...)
{
    va_list ap;
    int ret;
    va_start (ap, format);
    ret = vsnprintf (str, size, format, ap);
    va_end (ap);
    return ret;
}
# define snprintf vlc_snprintf

/* Make sure we don't use flawed vasprintf or asprintf either */
# undef HAVE_VASPRINTF
# undef HAVE_ASPRINTF
#endif

184
#ifndef HAVE_VASPRINTF
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
185
186
# include <stdio.h>
# include <stdlib.h>
187
188
189
# include <stdarg.h>
static inline int vasprintf (char **strp, const char *fmt, va_list ap)
{
geal's avatar
geal committed
190
#ifndef UNDER_CE
191
    int len = vsnprintf (NULL, 0, fmt, ap) + 1;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
192
    char *res = (char *)malloc (len);
193
194
195
    if (res == NULL)
        return -1;
    *strp = res;
Ken Self's avatar
Ken Self committed
196
    return vsnprintf (res, len, fmt, ap);
geal's avatar
geal committed
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
#else
    /* HACK: vsnprintf in the WinCE API behaves like
     * the one in glibc 2.0 and doesn't return the number of characters
     * it needed to copy the string.
     * cf http://msdn.microsoft.com/en-us/library/1kt27hek.aspx
     * and cf the man page of vsnprintf
     *
     Guess we need no more than 50 bytes. */
    int n, size = 50;
    char *res, *np;

    if ((res = (char *) malloc (size)) == NULL)
        return -1;

    while (1)
    {
        n = vsnprintf (res, size, fmt, ap);

        /* If that worked, return the string. */
        if (n > -1 && n < size)
        {
            *strp = res;
            return n;
        }

        /* Else try again with more space. */
223
        size *= 2;  /* twice the old size */
geal's avatar
geal committed
224
225
226
227
228
229
230
231
232
233
234
235
236

        if ((np = (char *) realloc (res, size)) == NULL)
        {
            free(res);
            return -1;
        }
        else
        {
            res = np;
        }

    }
#endif /* UNDER_CE */
237
}
238
239
240
#endif

#ifndef HAVE_ASPRINTF
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
241
# include <stdio.h>
242
243
244
245
246
# include <stdarg.h>
static inline int asprintf (char **strp, const char *fmt, ...)
{
    va_list ap;
    int ret;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
247
    va_start (ap, fmt);
248
249
250
251
    ret = vasprintf (strp, fmt, ap);
    va_end (ap);
    return ret;
}
252
253
#endif

254
#ifndef HAVE_STRNLEN
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
255
# include <string.h>
256
257
static inline size_t strnlen (const char *str, size_t max)
{
Rafaël Carré's avatar
Rafaël Carré committed
258
    const char *end = (const char *) memchr (str, 0, max);
259
260
261
262
    return end ? (size_t)(end - str) : max;
}
#endif

263
#ifndef HAVE_STRNDUP
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
264
265
# include <string.h>
# include <stdlib.h>
266
267
static inline char *strndup (const char *str, size_t max)
{
268
    size_t len = strnlen (str, max);
Rafaël Carré's avatar
Rafaël Carré committed
269
    char *res = (char *) malloc (len + 1);
270
271
272
273
274
275
276
    if (res)
    {
        memcpy (res, str, len);
        res[len] = '\0';
    }
    return res;
}
277
278
279
280
281
282
283
#endif

#ifndef HAVE_STRLCPY
# define strlcpy vlc_strlcpy
#endif

#ifndef HAVE_STRTOF
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
284
# define strtof( a, b ) ((float)strtod (a, b))
285
286
#endif

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
287
288
#ifndef HAVE_ATOF
# define atof( str ) (strtod ((str), (char **)NULL, 10))
289
290
291
292
293
294
#endif

#ifndef HAVE_STRTOLL
# define strtoll vlc_strtoll
#endif

295
#ifndef HAVE_STRSEP
Rémi Denis-Courmont's avatar
typo    
Rémi Denis-Courmont committed
296
static inline char *strsep( char **ppsz_string, const char *psz_delimiters )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
{
    char *psz_string = *ppsz_string;
    if( !psz_string )
        return NULL;

    char *p = strpbrk( psz_string, psz_delimiters );
    if( !p )
    {
        *ppsz_string = NULL;
        return psz_string;
    }
    *p++ = '\0';

    *ppsz_string = p;
    return psz_string;
}
313
314
#endif

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
315
316
317
318
#ifndef HAVE_ATOLL
# define atoll( str ) (strtoll ((str), (char **)NULL, 10))
#endif

319
#ifndef HAVE_LLDIV
320
321
322
323
324
325
326
327
328
329
typedef struct {
    long long quot; /* Quotient. */
    long long rem;  /* Remainder. */
} lldiv_t;

static inline lldiv_t lldiv (long long numer, long long denom)
{
    lldiv_t d = { .quot = numer / denom, .rem = numer % denom };
    return d;
}
330
331
332
333
334
335
336
337
#endif

#ifndef HAVE_SCANDIR
# define scandir vlc_scandir
# define alphasort vlc_alphasort
#endif

#ifndef HAVE_GETENV
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
338
static inline char *getenv (const char *name)
339
340
341
342
{
    (void)name;
    return NULL;
}
343
344
345
346
#endif

#ifndef HAVE_STRCASECMP
# ifndef HAVE_STRICMP
347
348
349
350
351
352
#  include <ctype.h>
static inline int strcasecmp (const char *s1, const char *s2)
{
    for (size_t i = 0;; i++)
    {
        int d = tolower (s1[i]) - tolower (s2[i]);
353
        if (d || !s1[i]) return d;
354
355
356
    }
    return 0;
}
357
358
359
360
361
362
363
# else
#  define strcasecmp stricmp
# endif
#endif

#ifndef HAVE_STRNCASECMP
# ifndef HAVE_STRNICMP
364
365
366
367
368
369
#  include <ctype.h>
static inline int strncasecmp (const char *s1, const char *s2, size_t n)
{
    for (size_t i = 0; i < n; i++)
    {
        int d = tolower (s1[i]) - tolower (s2[i]);
370
        if (d || !s1[i]) return d;
371
372
373
    }
    return 0;
}
374
375
376
377
378
379
380
381
382
383
384
385
386
# else
#  define strncasecmp strnicmp
# endif
#endif

#ifndef HAVE_STRCASESTR
# ifndef HAVE_STRISTR
#  define strcasestr vlc_strcasestr
# else
#  define strcasestr stristr
# endif
#endif

387
388
389
390
#ifndef HAVE_LOCALTIME_R
/* If localtime_r() is not provided, we assume localtime() uses
 * thread-specific storage. */
# include <time.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
391
static inline struct tm *localtime_r (const time_t *timep, struct tm *result)
392
393
394
395
396
397
398
399
{
    struct tm *s = localtime (timep);
    if (s == NULL)
        return NULL;

    *result = *s;
    return result;
}
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
400
401
402
403
404
405
406
407
408
static inline struct tm *gmtime_r (const time_t *timep, struct tm *result)
{
    struct tm *s = gmtime (timep);
    if (s == NULL)
        return NULL;

    *result = *s;
    return result;
}
409
410
#endif

411
412
413
414
415
416
417
/* Alignment of critical static data structures */
#ifdef ATTRIBUTE_ALIGNED_MAX
#   define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
#else
#   define ATTR_ALIGN(align)
#endif

418
419
420
421
422
423
424
#ifndef HAVE_USELOCALE
typedef void *locale_t;
# define newlocale( a, b, c ) ((locale_t)0)
# define uselocale( a ) ((locale_t)0)
# define freelocale( a ) (void)0
#endif

425
#ifdef WIN32
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
426
# include <dirent.h>
427
428
429
430
431
# define opendir Use_utf8_opendir_or_vlc_wopendir_instead!
# define readdir Use_utf8_readdir_or_vlc_wreaddir_instead!
# define closedir vlc_wclosedir
#endif

432
/* libintl support */
433
#define _(str) vlc_gettext (str)
434
435
436
437
438
439
440
441

#if defined (ENABLE_NLS)
# include <libintl.h>
#endif

#define N_(str) gettext_noop (str)
#define gettext_noop(str) (str)

geal's avatar
geal committed
442
443
444
445
446
447
448
449
#ifdef UNDER_CE
static inline void rewind ( FILE *stream )
{
    fseek(stream, 0L, SEEK_SET);
    clearerr(stream);
}
#endif

450
#endif /* !LIBVLC_FIXUPS_H */