17ec681f3Smrg// 27ec681f3Smrg// Copyright 2020 Serge Martin 37ec681f3Smrg// 47ec681f3Smrg// Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg// copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg// to deal in the Software without restriction, including without limitation 77ec681f3Smrg// the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg// and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg// Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg// 117ec681f3Smrg// The above copyright notice and this permission notice shall be included in 127ec681f3Smrg// all copies or substantial portions of the Software. 137ec681f3Smrg// 147ec681f3Smrg// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157ec681f3Smrg// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ec681f3Smrg// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177ec681f3Smrg// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 187ec681f3Smrg// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 197ec681f3Smrg// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 207ec681f3Smrg// OTHER DEALINGS IN THE SOFTWARE. 217ec681f3Smrg// 227ec681f3Smrg// Extract from Serge's printf clover code by airlied. 237ec681f3Smrg 247ec681f3Smrg#include "u_printf.h" 257ec681f3Smrg#include <assert.h> 267ec681f3Smrg#include <stdarg.h> 277ec681f3Smrg#include "util/macros.h" 287ec681f3Smrg 297ec681f3Smrg/* Some versions of MinGW are missing _vscprintf's declaration, although they 307ec681f3Smrg * still provide the symbol in the import library. */ 317ec681f3Smrg#ifdef __MINGW32__ 327ec681f3Smrg_CRTIMP int _vscprintf(const char *format, va_list argptr); 337ec681f3Smrg#endif 347ec681f3Smrg 357ec681f3Smrg#ifndef va_copy 367ec681f3Smrg#ifdef __va_copy 377ec681f3Smrg#define va_copy(dest, src) __va_copy((dest), (src)) 387ec681f3Smrg#else 397ec681f3Smrg#define va_copy(dest, src) (dest) = (src) 407ec681f3Smrg#endif 417ec681f3Smrg#endif 427ec681f3Smrg 437ec681f3Smrgsize_t util_printf_next_spec_pos(const std::string &s, size_t pos) 447ec681f3Smrg{ 457ec681f3Smrg size_t next_tok, spec_pos; 467ec681f3Smrg do { 477ec681f3Smrg pos = s.find_first_of('%', pos); 487ec681f3Smrg 497ec681f3Smrg if (pos == std::string::npos) 507ec681f3Smrg return -1; 517ec681f3Smrg 527ec681f3Smrg if (s[pos + 1] == '%') { 537ec681f3Smrg pos += 2; 547ec681f3Smrg continue; 557ec681f3Smrg } 567ec681f3Smrg 577ec681f3Smrg next_tok = s.find_first_of('%', pos + 1); 587ec681f3Smrg spec_pos = s.find_first_of("cdieEfFgGaAosuxXp", pos + 1); 597ec681f3Smrg if (spec_pos != std::string::npos) 607ec681f3Smrg if (spec_pos < next_tok) 617ec681f3Smrg return spec_pos; 627ec681f3Smrg 637ec681f3Smrg pos++; 647ec681f3Smrg } while (1); 657ec681f3Smrg} 667ec681f3Smrg 677ec681f3Smrgsize_t util_printf_next_spec_pos(const char *str, size_t pos) 687ec681f3Smrg{ 697ec681f3Smrg return util_printf_next_spec_pos(std::string(str), pos); 707ec681f3Smrg} 717ec681f3Smrg 727ec681f3Smrgsize_t 737ec681f3Smrgu_printf_length(const char *fmt, va_list untouched_args) 747ec681f3Smrg{ 757ec681f3Smrg int size; 767ec681f3Smrg char junk; 777ec681f3Smrg 787ec681f3Smrg /* Make a copy of the va_list so the original caller can still use it */ 797ec681f3Smrg va_list args; 807ec681f3Smrg va_copy(args, untouched_args); 817ec681f3Smrg 827ec681f3Smrg#ifdef _WIN32 837ec681f3Smrg /* We need to use _vcsprintf to calculate the size as vsnprintf returns -1 847ec681f3Smrg * if the number of characters to write is greater than count. 857ec681f3Smrg */ 867ec681f3Smrg size = _vscprintf(fmt, args); 877ec681f3Smrg (void)junk; 887ec681f3Smrg#else 897ec681f3Smrg size = vsnprintf(&junk, 1, fmt, args); 907ec681f3Smrg#endif 917ec681f3Smrg assert(size >= 0); 927ec681f3Smrg 937ec681f3Smrg va_end(args); 947ec681f3Smrg 957ec681f3Smrg return size; 967ec681f3Smrg} 97