2013-10-24 14:55:15 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2019-06-06 05:28:23 +00:00
|
|
|
Copyright (c) 2006-2019 Chung, Hyung-Hwan. All rights reserved.
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2014-11-19 14:42:24 +00:00
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2014-11-19 14:42:24 +00:00
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2013-10-24 14:55:15 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2013-11-03 16:01:39 +00:00
|
|
|
qse_size_t strvfmt (char_t* buf, const char_t* fmt, va_list ap)
|
2013-10-24 14:55:15 +00:00
|
|
|
{
|
|
|
|
buf_t b;
|
2013-10-28 09:40:25 +00:00
|
|
|
fmtout_t fo;
|
2013-10-29 14:14:43 +00:00
|
|
|
int x;
|
2013-10-24 14:55:15 +00:00
|
|
|
|
|
|
|
b.ptr = buf;
|
|
|
|
b.len = 0;
|
|
|
|
b.capa = QSE_TYPE_MAX(qse_ssize_t);
|
|
|
|
|
|
|
|
fo.limit = QSE_TYPE_MAX(qse_size_t) - 1;
|
|
|
|
fo.ctx = &b;
|
2013-10-30 05:53:54 +00:00
|
|
|
fo.put = b.ptr? put_char: put_char_null;
|
2013-10-28 09:40:25 +00:00
|
|
|
fo.conv = conv_char;
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2013-10-29 14:14:43 +00:00
|
|
|
/* no I/O error must occurred by fmtout but there can be
|
|
|
|
* encoding conversion error by fmtout */
|
|
|
|
x = fmtout (fmt, &fo, ap);
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2013-10-29 14:14:43 +00:00
|
|
|
/* fmtout must produce no I/O error but it can produce
|
|
|
|
* an encoding conversion error. if you didn't use a conversion
|
|
|
|
* specifier that requires encoding conversion (%S, %C, etc),
|
|
|
|
* you don't need to worry about an error. */
|
|
|
|
|
|
|
|
/* null-terminate regardless of error */
|
2013-10-30 05:53:54 +00:00
|
|
|
if (b.ptr)
|
|
|
|
{
|
|
|
|
QSE_ASSERT (fo.count == b.len);
|
|
|
|
b.ptr[b.len] = T('\0');
|
|
|
|
}
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2013-10-29 14:14:43 +00:00
|
|
|
if (x <= -1) return QSE_TYPE_MAX(qse_size_t);
|
2013-10-30 05:53:54 +00:00
|
|
|
return fo.count;
|
2013-10-24 14:55:15 +00:00
|
|
|
}
|
|
|
|
|
2013-11-03 16:01:39 +00:00
|
|
|
qse_size_t strfmt (char_t* buf, const char_t* fmt, ...)
|
2013-10-24 14:55:15 +00:00
|
|
|
{
|
2013-11-03 16:01:39 +00:00
|
|
|
qse_size_t x;
|
2013-10-24 14:55:15 +00:00
|
|
|
va_list ap;
|
2013-11-03 16:01:39 +00:00
|
|
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
x = strvfmt (buf, fmt, ap);
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
qse_size_t strxvfmt (char_t* buf, qse_size_t len, const char_t* fmt, va_list ap)
|
|
|
|
{
|
|
|
|
buf_t b;
|
2013-10-28 09:40:25 +00:00
|
|
|
fmtout_t fo;
|
2013-10-29 14:14:43 +00:00
|
|
|
int x;
|
2013-10-24 14:55:15 +00:00
|
|
|
|
|
|
|
b.ptr = buf;
|
|
|
|
b.len = 0;
|
|
|
|
|
|
|
|
if (len > QSE_TYPE_MAX(qse_ssize_t))
|
|
|
|
b.capa = QSE_TYPE_MAX(qse_ssize_t);
|
|
|
|
else if (len > 0)
|
|
|
|
b.capa = len - 1;
|
|
|
|
else
|
|
|
|
b.capa = 0;
|
|
|
|
|
|
|
|
fo.limit = QSE_TYPE_MAX(qse_size_t) - 1;
|
|
|
|
fo.ctx = &b;
|
2013-10-30 05:53:54 +00:00
|
|
|
fo.put = b.ptr? put_char: put_char_null;
|
2013-10-28 09:40:25 +00:00
|
|
|
fo.conv = conv_char;
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2013-10-29 14:14:43 +00:00
|
|
|
x = fmtout (fmt, &fo, ap);
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2013-10-29 14:14:43 +00:00
|
|
|
/* fmtout must produce no I/O error but it can produce
|
|
|
|
* an encoding conversion error. if you didn't use a conversion
|
|
|
|
* specifier that requires encoding conversion (%S, %C, etc),
|
|
|
|
* you don't need to worry about an error. */
|
|
|
|
|
|
|
|
/* null-terminate regardless of error */
|
2013-10-30 05:53:54 +00:00
|
|
|
if (b.ptr)
|
|
|
|
{
|
|
|
|
QSE_ASSERT (fo.count == b.len);
|
|
|
|
if (len > 0) b.ptr[b.len] = T('\0');
|
|
|
|
}
|
2013-10-24 14:55:15 +00:00
|
|
|
|
2013-10-30 05:53:54 +00:00
|
|
|
if (x <= -1) return QSE_TYPE_MAX(qse_size_t);
|
|
|
|
return fo.count;
|
2013-10-24 14:55:15 +00:00
|
|
|
}
|
|
|
|
|
2013-11-03 16:01:39 +00:00
|
|
|
qse_size_t strxfmt (char_t* buf, qse_size_t len, const char_t* fmt, ...)
|
|
|
|
{
|
|
|
|
qse_size_t x;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
x = strxvfmt (buf, len, fmt, ap);
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|