Rev 2479 | Rev 4234 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2479 | Rev 3351 | ||
|---|---|---|---|
| Line 36... | Line 36... | ||
| 36 | #include <stdio.h> |
36 | #include <stdio.h> |
| 37 | #include <string.h> |
37 | #include <string.h> |
| 38 | #include <io/printf_core.h> |
38 | #include <io/printf_core.h> |
| 39 | 39 | ||
| 40 | struct vsnprintf_data { |
40 | struct vsnprintf_data { |
| 41 | size_t size; /* total space for string */ |
41 | size_t size; /* total space for string */ |
| 42 | size_t len; /* count of currently used characters */ |
42 | size_t len; /* count of currently used characters */ |
| 43 | char *string; /* destination string */ |
43 | char *string; /* destination string */ |
| 44 | }; |
44 | }; |
| 45 | 45 | ||
| 46 | /** Write string to given buffer. |
46 | /** Write string to given buffer. |
| 47 | * Write at most data->size characters including trailing zero. According to C99 has snprintf to return number |
47 | * Write at most data->size characters including trailing zero. According to C99 |
| - | 48 | * has snprintf to return number of characters that would have been written if |
|
| 48 | * of characters that would have been written if enough space had been available. Hence the return value is not |
49 | * enough space had been available. Hence the return value is not number of |
| 49 | * number of really printed characters but size of input string. Number of really used characters |
50 | * really printed characters but size of input string. Number of really used |
| 50 | * is stored in data->len. |
51 | * characters is stored in data->len. |
| - | 52 | * |
|
| 51 | * @param str source string to print |
53 | * @param str Source string to print. |
| 52 | * @param count size of source string |
54 | * @param count Size of the source string. |
| 53 | * @param data structure with destination string, counter of used space and total string size. |
55 | * @param data Structure with destination string, counter of used space |
| - | 56 | * and total string size. |
|
| 54 | * @return number of characters to print (not characters really printed!) |
57 | * @return Number of characters to print (not characters really |
| - | 58 | * printed!) |
|
| 55 | */ |
59 | */ |
| - | 60 | static int |
|
| 56 | static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
61 | vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
| 57 | { |
62 | { |
| 58 | size_t i; |
63 | size_t i; |
| 59 | i = data->size - data->len; |
64 | i = data->size - data->len; |
| 60 | 65 | ||
| 61 | if (i == 0) { |
66 | if (i == 0) { |
| 62 | return count; |
67 | return count; |
| 63 | } |
68 | } |
| 64 | 69 | ||
| 65 | if (i == 1) { |
70 | if (i == 1) { |
| - | 71 | /* |
|
| 66 | /* We have only one free byte left in buffer => write there trailing zero */ |
72 | * We have only one free byte left in buffer => write there |
| - | 73 | * trailing zero. |
|
| - | 74 | */ |
|
| 67 | data->string[data->size - 1] = 0; |
75 | data->string[data->size - 1] = 0; |
| 68 | data->len = data->size; |
76 | data->len = data->size; |
| 69 | return count; |
77 | return count; |
| 70 | } |
78 | } |
| 71 | 79 | ||
| 72 | if (i <= count) { |
80 | if (i <= count) { |
| - | 81 | /* |
|
| 73 | /* We have not enought space for whole string with the trailing zero => print only a part of string */ |
82 | * We have not enought space for whole string with the trailing |
| - | 83 | * zero => print only a part of string. |
|
| - | 84 | */ |
|
| 74 | memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
85 | memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
| 75 | data->string[data->size - 1] = 0; |
86 | data->string[data->size - 1] = 0; |
| 76 | data->len = data->size; |
87 | data->len = data->size; |
| 77 | return count; |
88 | return count; |
| 78 | } |
89 | } |
| 79 | 90 | ||
| 80 | /* Buffer is big enought to print whole string */ |
91 | /* Buffer is big enought to print whole string */ |
| 81 | memcpy((void *)(data->string + data->len), (void *)str, count); |
92 | memcpy((void *)(data->string + data->len), (void *)str, count); |
| 82 | data->len += count; |
93 | data->len += count; |
| - | 94 | /* |
|
| 83 | /* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */ |
95 | * Put trailing zero at end, but not count it into data->len so it could |
| - | 96 | * be rewritten next time. |
|
| - | 97 | */ |
|
| 84 | data->string[data->len] = 0; |
98 | data->string[data->len] = 0; |
| 85 | 99 | ||
| 86 | return count; |
100 | return count; |
| 87 | } |
101 | } |
| 88 | 102 | ||
| 89 | /** Print formatted to the given buffer with limited size. |
103 | /** Print formatted to the given buffer with limited size. |
| 90 | * @param str buffer |
104 | * @param str Buffer. |
| 91 | * @param size buffer size |
105 | * @param size Bffer size. |
| 92 | * @param fmt format string |
106 | * @param fmt Format string. |
| 93 | * \see For more details about format string see printf_core. |
107 | * \see For more details about format string see printf_core. |
| 94 | */ |
108 | */ |
| 95 | int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) |
109 | int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) |
| 96 | { |
110 | { |
| 97 | struct vsnprintf_data data = {size, 0, str}; |
111 | struct vsnprintf_data data = {size, 0, str}; |
| - | 112 | struct printf_spec ps = { |
|
| 98 | struct printf_spec ps = {(int(*)(void *, size_t, void *)) vsnprintf_write, &data}; |
113 | (int(*)(void *, size_t, void *)) vsnprintf_write, |
| - | 114 | &data |
|
| - | 115 | }; |
|
| 99 | 116 | ||
| - | 117 | /* |
|
| 100 | /* Print 0 at end of string - fix the case that nothing will be printed */ |
118 | * Print 0 at end of string - fix the case that nothing will be printed. |
| - | 119 | */ |
|
| 101 | if (size > 0) |
120 | if (size > 0) |
| 102 | str[0] = 0; |
121 | str[0] = 0; |
| 103 | 122 | ||
| 104 | /* vsnprintf_write ensures that str will be terminated by zero. */ |
123 | /* vsnprintf_write ensures that str will be terminated by zero. */ |
| 105 | return printf_core(fmt, &ps, ap); |
124 | return printf_core(fmt, &ps, ap); |