00001
00038 #include <util.h>
00039 #include <string.h>
00040 #include <stream.h>
00041 #include <compiler.h>
00042
00047 #define BUFFER_STREAM_BUFFER_SIZE 32
00048
00054 struct string_stream {
00056 struct stream stream;
00058 size_t offset;
00060 size_t size;
00062 char *string;
00064 char buffer[BUFFER_STREAM_BUFFER_SIZE];
00065 };
00066
00071 static inline struct string_stream *string_stream_of(struct stream *s)
00072 {
00073 return container_of(s, struct string_stream, stream);
00074 }
00075
00080 static void snprintf_stream_commit(struct stream *s)
00081 {
00082 struct string_stream *ss = string_stream_of(s);
00083
00084
00085
00086 while (stream_buf_has_data(s) && ss->offset < ss->size) {
00087 ss->string[ss->offset] = stream_buf_extract_char(s);
00088
00089
00090
00091 ss->offset++;
00092 }
00093
00094
00095 if (stream_buf_has_data(s) && (ss->offset + 1) >= ss->size) {
00096
00097
00098
00099
00100
00101 while (stream_buf_has_data(s)) {
00102 stream_buf_extract_char(s);
00103 }
00104 }
00105 }
00106
00111 static void sprintf_stream_commit(struct stream *s)
00112 {
00113 struct string_stream *ss = string_stream_of(s);
00114
00115 while (stream_buf_has_data(s)) {
00116 ss->string[ss->offset] = stream_buf_extract_char(s);
00117
00118
00119
00120 ss->offset++;
00121 }
00122 }
00123
00128 static bool string_stream_make_room(struct stream *s, unsigned int goal)
00129 {
00130 s->ops->commit(s);
00131 return true;
00132 }
00133
00134 static const struct stream_ops snprintf_stream_ops = {
00135 .commit = snprintf_stream_commit,
00136 .make_room = string_stream_make_room,
00137 };
00138
00139 static const struct stream_ops sprintf_stream_ops = {
00140 .commit = sprintf_stream_commit,
00141 .make_room = string_stream_make_room,
00142 };
00143
00152 int snprintf(char *str, size_t size, const char *format, ...)
00153 {
00154 int n;
00155 va_list ap;
00156 struct string_stream ss = {
00157 {
00158 .ops = &snprintf_stream_ops,
00159 .ring_mask = BUFFER_STREAM_BUFFER_SIZE - 1,
00160 },
00161 .string = str,
00162 .offset = 0,
00163
00164
00165
00166
00167 .size = size - 1,
00168 };
00169
00170 va_start(ap, format);
00171
00172 memset(ss.buffer, 0, BUFFER_STREAM_BUFFER_SIZE);
00173 ss.stream.data = ss.buffer;
00174 n = stream_vprintf(&ss.stream, format, ap);
00175
00176 va_end(ap);
00177
00178
00179 if (ss.offset >= size)
00180 str[ss.offset - 1] = '\0';
00181 else
00182 str[ss.offset] = '\0';
00183
00184 return n;
00185 }
00186
00196 int sprintf(char *str, const char *format, ...)
00197 {
00198 int n;
00199 va_list ap;
00200 struct string_stream ss = {
00201 {
00202 .ops = &sprintf_stream_ops,
00203 .ring_mask = BUFFER_STREAM_BUFFER_SIZE - 1,
00204 },
00205 .string = str,
00206 .offset = 0,
00207 };
00208
00209 va_start(ap, format);
00210
00211 memset(ss.buffer, 0, BUFFER_STREAM_BUFFER_SIZE);
00212 ss.stream.data = ss.buffer;
00213 n = stream_vprintf(&ss.stream, format, ap);
00214
00215 va_end(ap);
00216
00217
00218 str[ss.offset] = '\0';
00219
00220 return n;
00221 }