Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
2bd4b7e16a56ee5416288c4abbc554d3a21fdbbc
[simgrid.git] / src / xbt / snprintf.c
1 /* Copyright (c) 2005-2019. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /*
8  * snprintf.c - a portable implementation of snprintf
9  *
10  * AUTHOR
11  *   Mark Martinec <mark.martinec@ijs.si>, April 1999.
12  *
13  *   Copyright 1999, Mark Martinec. All rights reserved.
14  *
15  * TERMS AND CONDITIONS
16  *   This program is free software; you can redistribute it and/or modify
17  *   it under the terms of the "Frontier Artistic License" which comes
18  *   with this Kit.
19  *
20  *   This program is distributed in the hope that it will be useful,
21  *   but WITHOUT ANY WARRANTY; without even the implied warranty
22  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23  *   See the Frontier Artistic License for more details.
24  *
25  *   You should have received a copy of the Frontier Artistic License
26  *   with this Kit in the file named LICENSE.txt .
27  *   If not, I'll be glad to provide one.
28  *
29  * FEATURES
30  * - careful adherence to specs regarding flags, field width and precision;
31  * - good performance for large string handling (large format, large
32  *   argument or large paddings). Performance is similar to system's sprintf
33  *   and in several cases significantly better (make sure you compile with
34  *   optimizations turned on, tell the compiler the code is strict ANSI
35  *   if necessary to give it more freedom for optimizations);
36  * - return value semantics per ISO/IEC 9899:1999 ("ISO C99");
37  * - written in standard ISO/ANSI C - requires an ANSI C compiler.
38  *
39  * [...]
40  *
41  * Routines asprintf and vasprintf return a pointer (in the ptr argument)
42  * to a buffer sufficiently large to hold the resulting string. This pointer
43  * should be passed to free(3) to release the allocated storage when it is
44  * no longer needed. If sufficient space cannot be allocated, these functions
45  * will return -1 and set ptr to be a NULL pointer. These two routines are a
46  * GNU C library extensions (glibc).
47  *
48  * AVAILABILITY
49  *   http://www.ijs.si/software/snprintf/
50  */
51
52 /* find vasprintf in stdio.h */
53 #ifndef _GNU_SOURCE
54 #  define _GNU_SOURCE
55 #endif
56 #include <stdio.h>
57
58 #include "xbt/sysdep.h"           /* xbt_abort() */
59 #include "src/internal_config.h"  /* Do we need vasprintf? */
60
61 #include <assert.h>
62
63 #if !HAVE_VASPRINTF
64 #include <stdarg.h> /* vsnprintf */
65 int vasprintf(char **ptr, const char *fmt, va_list ap);
66 int vasprintf(char **ptr, const char *fmt, va_list ap)
67 {
68   size_t str_m;
69   int str_l;
70
71   *ptr = NULL;
72   {
73     va_list ap2;
74     va_copy(ap2, ap);           /* don't consume the original ap, we'll need it again */
75     str_l = vsnprintf(NULL, (size_t) 0, fmt, ap2);     /*get required size */
76     va_end(ap2);
77   }
78   xbt_assert(str_l >= 0);           /* possible integer overflow if str_m > INT_MAX */
79   *ptr = (char *) xbt_malloc(str_m = (size_t) str_l + 1);
80
81   int str_l2 = vsnprintf(*ptr, str_m, fmt, ap);
82   assert(str_l2 == str_l);
83
84   return str_l;
85 }
86 #endif
87
88 char *bvprintf(const char *fmt, va_list ap)
89 {
90   char *res;
91
92   if (vasprintf(&res, fmt, ap) < 0) {
93     /* Do not want to use xbt_die() here, as it uses the logging
94      * infrastructure and may fail to allocate memory too. */
95     fprintf(stderr, "bprintf: vasprintf failed. Aborting.\n");
96     xbt_abort();
97   }
98   return res;
99 }
100
101 char *bprintf(const char *fmt, ...)
102 {
103   va_list ap;
104
105   va_start(ap, fmt);
106   char *res = bvprintf(fmt, ap);
107   va_end(ap);
108   return res;
109 }