vsnprintf.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2006 Josef Cejka
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <stdarg.h>
00036 #include <stdio.h>
00037 #include <str.h>
00038 #include <io/printf_core.h>
00039 #include <errno.h>
00040 
00041 typedef struct {
00042         size_t size;    /* Total size of the buffer (in bytes) */
00043         size_t len;     /* Number of already used bytes */
00044         char *dst;      /* Destination */
00045 } vsnprintf_data_t;
00046 
00064 static int vsnprintf_str_write(const char *str, size_t size, vsnprintf_data_t *data)
00065 {
00066         size_t left = data->size - data->len;
00067         
00068         if (left == 0)
00069                 return ((int) size);
00070         
00071         if (left == 1) {
00072                 /* We have only one free byte left in buffer
00073                  * -> store trailing zero
00074                  */
00075                 data->dst[data->size - 1] = 0;
00076                 data->len = data->size;
00077                 return ((int) size);
00078         }
00079         
00080         if (left <= size) {
00081                 /* We do not have enough space for the whole string
00082                  * with the trailing zero => print only a part
00083                  * of string
00084                  */
00085                 size_t index = 0;
00086                 
00087                 while (index < size) {
00088                         wchar_t uc = str_decode(str, &index, size);
00089                         
00090                         if (chr_encode(uc, data->dst, &data->len, data->size - 1) != EOK)
00091                                 break;
00092                 }
00093                 
00094                 /* Put trailing zero at end, but not count it
00095                  * into data->len so it could be rewritten next time
00096                  */
00097                 data->dst[data->len] = 0;
00098                 
00099                 return ((int) size);
00100         }
00101         
00102         /* Buffer is big enough to print the whole string */
00103         memcpy((void *)(data->dst + data->len), (void *) str, size);
00104         data->len += size;
00105         
00106         /* Put trailing zero at end, but not count it
00107          * into data->len so it could be rewritten next time
00108          */
00109         data->dst[data->len] = 0;
00110         
00111         return ((int) size);
00112 }
00113 
00131 static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
00132 {
00133         size_t index = 0;
00134         
00135         while (index < (size / sizeof(wchar_t))) {
00136                 size_t left = data->size - data->len;
00137                 
00138                 if (left == 0)
00139                         return ((int) size);
00140                 
00141                 if (left == 1) {
00142                         /* We have only one free byte left in buffer
00143                          * -> store trailing zero
00144                          */
00145                         data->dst[data->size - 1] = 0;
00146                         data->len = data->size;
00147                         return ((int) size);
00148                 }
00149                 
00150                 if (chr_encode(str[index], data->dst, &data->len, data->size - 1) != EOK)
00151                         break;
00152                 
00153                 index++;
00154         }
00155         
00156         /* Put trailing zero at end, but not count it
00157          * into data->len so it could be rewritten next time
00158          */
00159         data->dst[data->len] = 0;
00160         
00161         return ((int) size);
00162 }
00163 
00164 int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
00165 {
00166         vsnprintf_data_t data = {
00167                 size,
00168                 0,
00169                 str
00170         };
00171         printf_spec_t ps = {
00172                 (int(*) (const char *, size_t, void *)) vsnprintf_str_write,
00173                 (int(*) (const wchar_t *, size_t, void *)) vsnprintf_wstr_write,
00174                 &data
00175         };
00176         
00177         /* Print 0 at end of string - fix the case that nothing will be printed */
00178         if (size > 0)
00179                 str[0] = 0;
00180         
00181         /* vsnprintf_write ensures that str will be terminated by zero. */
00182         return printf_core(fmt, &ps, ap);
00183 }
00184 

Generated on Thu Jun 2 07:45:46 2011 for HelenOS/USB by  doxygen 1.4.7