#include "term/z-form.h"
#include "term/z-util.h"
#include "term/z-virt.h"
+#include <span>
#include <vector>
/*
*/
uint vstrnfmt(char *buf, uint max, concptr fmt, va_list vp)
{
- concptr s;
-
- /* The argument is "long" */
- bool do_long;
-
- /* The argument is "long long" */
- bool do_long_long;
-
- /* The argument needs "processing" */
- bool do_xtra;
-
- /* Bytes used in buffer */
- uint n;
-
- /* Bytes used in format sequence */
- uint q;
-
- /* Format sequence */
- char aux[128];
-
- /* Resulting string */
- char tmp[1024];
-
- /* Mega-Hack -- treat "illegal" length as "infinite" */
- if (!max) {
- max = 32767;
- }
-
- /* Mega-Hack -- treat "no format" as "empty string" */
- if (!fmt) {
- fmt = "";
+ /* treat "no format" or "illegal" length as "empty string" */
+ if (!fmt || (max == 0)) {
+ buf[0] = '\0';
+ return 0;
}
- /* Begin the buffer */
- n = 0;
-
- /* Begin the format string */
- s = fmt;
-
- /* Scan the format string */
- while (true) {
- /* All done */
- if (!*s) {
- break;
- }
+ /* Output length to buffer */
+ auto n = 0U;
+ for (auto s = fmt; *s != '\0';) {
/* Normal character */
if (*s != '%') {
- /* Check total length */
if (n == max - 1) {
break;
}
- /* Save the character */
buf[n++] = *s++;
continue;
}
- /* Skip the "percent" */
s++;
/* Pre-process "%%" */
if (*s == '%') {
- /* Check total length */
if (n == max - 1) {
break;
}
- /* Save the percent */
buf[n++] = '%';
-
- /* Skip the "%" */
s++;
continue;
}
/* Pre-process "%n" */
if (*s == 'n') {
- int *arg;
-
- /* Access the next argument */
- arg = va_arg(vp, int *);
-
/* Save the current length */
+ auto *arg = va_arg(vp, int *);
(*arg) = n;
- /* Skip the "n" */
s++;
continue;
}
- /* Begin the "aux" string */
- q = 0;
+ auto do_long = false;
+ auto do_long_long = false;
+ auto do_capitalize = false;
- /* Save the "percent" */
- aux[q++] = '%';
+ /* Format sequence */
+ std::string aux;
+ aux.reserve(128);
+ aux.push_back('%');
- /* Assume no "long" argument */
- do_long = false;
-
- /* Assume no "long long" argument */
- do_long_long = false;
-
- /* Assume no "xtra" processing */
- do_xtra = false;
-
- /* Build the "aux" string */
+ /* Build the format sequence string */
while (true) {
/* Error -- format sequence is not terminated */
- if (!*s) {
- /* Terminate the buffer */
+ if (*s == '\0') {
buf[0] = '\0';
-
- /* Return "error" */
return 0;
}
/* Error -- format sequence may be too long */
- if (q > 100) {
- /* Terminate the buffer */
+ if (aux.length() > 100) {
buf[0] = '\0';
-
- /* Return "error" */
return 0;
}
- /* Handle "alphabetic" chars */
if (isalpha(*s)) {
- /* Hack -- handle "long" request */
+ /* handle "long" request */
if (*s == 'l') {
- /* Save the character */
- aux[q++] = *s++;
-
- /* Note the "long" flag */
+ aux.push_back(*s++);
do_long = true;
}
- /* Mega-Hack -- handle "extra-long" request */
+ /* handle "extra-long" request */
else if (*s == 'L') {
- /* Save the character */
- aux[q++] = 'l';
- aux[q++] = 'l';
- s++;
-
- /* Note the "long long" flag */
+ aux.append("ll");
do_long_long = true;
+ s++;
}
/* Handle normal end of format sequence */
else {
- /* Save the character */
- aux[q++] = *s++;
-
- /* Stop processing the format sequence */
+ aux.push_back(*s++);
break;
}
- }
-
- /* Handle "non-alphabetic" chars */
- else {
- /* Hack -- Handle 'star' (for "variable length" argument) */
+ } else {
+ /* Handle 'star' (for "variable length" argument) */
if (*s == '*') {
- int arg;
-
- /* Access the next argument */
- arg = va_arg(vp, int);
-
- /* Hack -- append the "length" */
- snprintf(aux + q, sizeof(aux) - q, "%d", arg);
-
- /* Hack -- accept the "length" */
- while (aux[q]) {
- q++;
- }
-
- /* Skip the "*" */
+ auto arg = va_arg(vp, int);
+ aux.append(std::to_string(arg));
s++;
}
- /* Mega-Hack -- Handle 'caret' (for "uppercase" request) */
+ /* Handle 'caret' (for "uppercase" request) */
else if (*s == '^') {
- /* Note the "xtra" flag */
- do_xtra = true;
-
- /* Skip the "^" */
+ do_capitalize = true;
s++;
}
/* Collect "normal" characters (digits, "-", "+", ".", etc) */
else {
- /* Save the character */
- aux[q++] = *s++;
+ aux.push_back(*s++);
}
}
}
- /* Terminate "aux" */
- aux[q] = '\0';
-
- /* Clear "tmp" */
- tmp[0] = '\0';
+ /* Resulting string */
+ char tmp[1024]{};
/* Process the "format" char */
- switch (aux[q - 1]) {
+ switch (aux.back()) {
/* Simple Character -- standard format */
case 'c': {
- int arg;
-
- /* Access next argument */
- arg = va_arg(vp, int);
-
- /* Format the argument */
+ auto arg = va_arg(vp, int);
snprintf(tmp, sizeof(tmp), "%c", arg);
-
break;
}
case 'd':
case 'i': {
if (do_long) {
- long arg;
-
- /* Access next argument */
- arg = va_arg(vp, long);
-
- /* Format the argument */
- snprintf(tmp, sizeof(tmp), aux, arg);
+ auto arg = va_arg(vp, long);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
} else if (do_long_long) {
- long long arg;
-
- /* Access next argument */
- arg = va_arg(vp, long long);
-
- /* Format the argument */
- snprintf(tmp, sizeof(tmp), aux, arg);
+ auto arg = va_arg(vp, long long);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
} else {
- int arg;
-
- /* Access next argument */
- arg = va_arg(vp, int);
-
- /* Format the argument */
- snprintf(tmp, sizeof(tmp), aux, arg);
+ auto arg = va_arg(vp, int);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
}
-
break;
}
case 'x':
case 'X': {
if (do_long) {
- ulong arg;
-
- /* Access next argument */
- arg = va_arg(vp, ulong);
-
- snprintf(tmp, sizeof(tmp), aux, arg);
+ auto arg = va_arg(vp, unsigned long);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
} else if (do_long_long) {
- unsigned long long arg;
-
- /* Access next argument */
- arg = va_arg(vp, unsigned long long);
-
- snprintf(tmp, sizeof(tmp), aux, arg);
+ auto arg = va_arg(vp, unsigned long long);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
} else {
- uint arg;
-
- /* Access next argument */
- arg = va_arg(vp, uint);
- snprintf(tmp, sizeof(tmp), aux, arg);
+ auto arg = va_arg(vp, unsigned int);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
}
-
break;
}
case 'E':
case 'g':
case 'G': {
- double arg;
-
- /* Access next argument */
- arg = va_arg(vp, double);
-
- /* Format the argument */
- snprintf(tmp, sizeof(tmp), aux, arg);
-
+ auto arg = va_arg(vp, double);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
break;
}
/* Pointer -- implementation varies */
case 'p': {
- vptr arg;
-
- /* Access next argument */
- arg = va_arg(vp, vptr);
-
- /* Format the argument */
- snprintf(tmp, sizeof(tmp), aux, arg);
-
+ auto arg = va_arg(vp, void *);
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
break;
}
/* String */
case 's': {
- concptr arg;
- char arg2[1024];
-
- /* Access next argument */
- arg = va_arg(vp, concptr);
-
- /* Hack -- convert nullptr to EMPTY */
- if (!arg) {
+ auto arg = va_arg(vp, const char *);
+ if (arg == nullptr) {
arg = "";
}
-
- /* Prevent buffer overflows */
- strncpy(arg2, arg, 1024);
- arg2[1023] = '\0';
-
- /* Format the argument */
- snprintf(tmp, sizeof(tmp), aux, arg);
-
+ snprintf(tmp, sizeof(tmp), aux.data(), arg);
break;
}
default: {
/* Error -- illegal format char */
buf[0] = '\0';
-
- /* Return "error" */
return 0;
}
}
+ std::span<char> formatted_str(std::begin(tmp), strlen(tmp));
#ifdef JP
- for (q = 0; tmp[q]; q++) {
- if (iskanji(tmp[q])) {
- do_xtra = false;
+ for (auto ch : formatted_str) {
+ if (iskanji(ch)) {
+ do_capitalize = false;
break;
}
}
#endif
- /* Mega-Hack -- handle "capitilization" */
- if (do_xtra) {
- /* Now append "tmp" to "buf" */
- for (q = 0; tmp[q]; q++) {
- /* Notice first non-space */
- if (!iswspace(tmp[q])) {
- /* Capitalize if possible */
- if (islower(tmp[q])) {
- tmp[q] = (char)toupper(tmp[q]);
+ if (do_capitalize) {
+ for (auto &ch : formatted_str) {
+ if (!iswspace(ch)) {
+ if (islower(ch)) {
+ ch = static_cast<char>(toupper(ch));
}
-
break;
}
}
}
- /* Now append "tmp" to "buf" */
- for (q = 0; tmp[q]; q++) {
- /* Check total length */
+ /* Now append formatted_str to "buf" */
+ for (auto it = formatted_str.begin(), it_end = formatted_str.end(); it != it_end;) {
if (n == max - 1) {
break;
}
-
- /* Save the character */
#ifdef JP
- if (iskanji(tmp[q])) {
- if (tmp[q + 1]) {
- buf[n++] = tmp[q++];
+ if (iskanji(*it)) {
+ if ((n < max - 2) && ((it + 1) != it_end)) {
+ buf[n++] = *it++;
} else {
// 最後の文字が2バイト文字の前半で終わる場合は空白で置き換えて終了する
buf[n++] = ' ';
}
}
#endif
- buf[n++] = tmp[q];
+ buf[n++] = *it++;
}
}
- /* Terminate buffer */
buf[n] = '\0';
-
- /* Return length */
return n;
}