Date: | Wed, 26 Apr 2006 09:36:32 +0300 |
From: | Diomidis Spinellis <dds@aueb.gr> |
Organization: | Athens University of Economics and Business |
User-Agent: | Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.2) Gecko/20060404 SeaMonkey/1.0.1 |
MIME-Version: | 1.0 |
Newsgroups: | comp.lang.c |
Subject: | Re: writing alibrary funtion ssprintf() |
References: | <1146028371.868585.203760@j33g2000cwa.googlegroups.com> |
In-Reply-To: | <1146028371.868585.203760@j33g2000cwa.googlegroups.com> |
Content-Type: | text/plain; charset=ISO-8859-1; format=flowed |
Content-Transfer-Encoding: | 7bit |
jitu.csewizard@gmail.com wrote:
> question:
> function ssprintf(<buffername>,<format string>, .....)
> i need to write a funtion in time and space optimized way so that i
> should allocate buffername after getting the string.(ignore the time of
> mallocing the memory...there is a different strategy for mallocing...it
> won't take much time)
> i have thought of a strategy:
> 1. writing the format string to /dev/null or to memory and get the
> length of the string and then again malloc(not exactly malloc ....there
> is a different optimized strategy) the required string.
> problem: a call to printf takes time if the string is long
> note:calling string functions like strlen also takes time.
> can you suggest me a better optimized strategy.
A portable approach would involve allocating a buffer with a default
large size, and calling snprintf and (your) realloc on it. Snprintf
will return the size of the buffer required for printing the whole
string, so you can always adjust the default size upwards to match that
number, and keep it that way in subsequent calls. For the first few
calls your implementation will call snprintf multiple times to establish
the size needed, but this overhead will be amortized over time.
One other more cumbersome approach is to take an open-source sprintf
implementation and modify it to make it work in the way you want. You
will find that most printf implementations keep track of the size of the
resulting string, in order to implement functions like snprintf. For
example, the FreeBSD/NetBSD implementation keeps the distinct elements
to be printed in an iov vector of output objects, and tallies their
length. This is done by a call to a PRINT macro for each distinct element.
#define PRINT(ptr, len) { \
iovp->iov_base = (ptr); \
iovp->iov_len = (len); \
uio.uio_resid += (len); \
iovp++; \
if (++uio.uio_iovcnt >= NIOV) { \
if (__sprint(fp, &uio)) \
goto error; \
iovp = iov; \
} \
}
You can thus take uio.uio_resid and use it to allocate the string's
buffer, before flushing the buffer to it. For an example on how this is
done, look at the FreeBSD asprintf implementation, which allocates the
buffer memory with malloc.
A different (non-portable) approach is to create an stdio object that
will write to a dynamically growing buffer. Nowadays many stdio
implementations are object-oriented, and provide you a (non-portable and
sometimes undocumented) way to supply your own underlying I/O functions.
For example, the FreeBSD implementation's fwopen function takes as an
argument a pointer to a write function.
FILE *fwopen(void *cookie, int (*writefn)(void *, const char *, int));
I assume that your optimized malloc implementation can grow objects
dynamically. If not, look at the GNU Obstack facility
<http://gcc.gnu.org/onlinedocs/libiberty/Growing-Objects.html#Growing-Objects>.
Also, keep in mind that I/O processing is seldom a program's bottleneck:
the underlying I/O operations (for example disk writes) are orders of
magnitude more expensive. Therefore be sure to profile your program to
establish the need for implementing the more exotic solutions I described.
--
Diomidis Spinellis
Code Quality: The Open Source Perspective (Addison-Wesley 2006)
http://www.spinellis.gr/codequality?clc
Newsgroup comp.lang.c contents
Newsgroup list
Diomidis Spinellis home page
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.