158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file. 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#ifndef BASE_STRINGS_SAFE_SPRINTF_H_ 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define BASE_STRINGS_SAFE_SPRINTF_H_ 758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "build/build_config.h" 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <stddef.h> 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <stdint.h> 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <stdlib.h> 1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_POSIX) 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// For ssize_t 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <unistd.h> 1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif 1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/base_export.h" 2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/basictypes.h" 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace base { 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace strings { 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(_MSC_VER) 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Define ssize_t inside of our namespace. 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(_WIN64) 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)typedef __int64 ssize_t; 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#else 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)typedef long ssize_t; 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// SafeSPrintf() is a type-safe and completely self-contained version of 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// snprintf(). 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// SafeSNPrintf() is an alternative function signature that can be used when 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// not dealing with fixed-sized buffers. When possible, SafeSPrintf() should 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// always be used instead of SafeSNPrintf() 4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// These functions allow for formatting complicated messages from contexts that 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// require strict async-signal-safety. In fact, it is safe to call them from 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// any low-level execution context, as they are guaranteed to make no library 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// or system calls. It deliberately never touches "errno", either. 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The only exception to this rule is that in debug builds the code calls 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// RAW_CHECK() to help diagnose problems when the format string does not 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// match the rest of the arguments. In release builds, no CHECK()s are used, 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// and SafeSPrintf() instead returns an output string that expands only 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// those arguments that match their format characters. Mismatched arguments 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// are ignored. 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The code currently only supports a subset of format characters: 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// %c, %o, %d, %x, %X, %p, and %s. 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// SafeSPrintf() aims to be as liberal as reasonably possible. Integer-like 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// values of arbitrary width can be passed to all of the format characters 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// that expect integers. Thus, it is explicitly legal to pass an "int" to 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// "%c", and output will automatically look at the LSB only. It is also 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// explicitly legal to pass either signed or unsigned values, and the format 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// characters will automatically interpret the arguments accordingly. 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// It is still not legal to mix-and-match integer-like values with pointer 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// values. For instance, you cannot pass a pointer to %x, nor can you pass an 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// integer to %p. 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The one exception is "0" zero being accepted by "%p". This works-around 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// the problem of C++ defining NULL as an integer-like value. 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// All format characters take an optional width parameter. This must be a 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// positive integer. For %d, %o, %x, %X and %p, if the width starts with 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// a leading '0', padding is done with '0' instead of ' ' characters. 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// There are a few features of snprintf()-style format strings, that 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// SafeSPrintf() does not support at this time. 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// If an actual user showed up, there is no particularly strong reason they 7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// couldn't be added. But that assumes that the trade-offs between complexity 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// and utility are favorable. 8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// For example, adding support for negative padding widths, and for %n are all 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// likely to be viewed positively. They are all clearly useful, low-risk, easy 8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// to test, don't jeopardize the async-signal-safety of the code, and overall 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// have little impact on other parts of SafeSPrintf() function. 8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// On the other hands, adding support for alternate forms, positional 8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// arguments, grouping, wide characters, localization or floating point numbers 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// are all unlikely to ever be added. 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// SafeSPrintf() and SafeSNPrintf() mimic the behavior of snprintf() and they 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// return the number of bytes needed to store the untruncated output. This 9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// does *not* include the terminating NUL byte. 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// They return -1, iff a fatal error happened. This typically can only happen, 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// if the buffer size is a) negative, or b) zero (i.e. not even the NUL byte 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// can be written). The return value can never be larger than SSIZE_MAX-1. 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This ensures that the caller can always add one to the signed return code 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// in order to determine the amount of storage that needs to be allocated. 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// While the code supports type checking and while it is generally very careful 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// to avoid printing incorrect values, it tends to be conservative in printing 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// as much as possible, even when given incorrect parameters. Typically, in 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// case of an error, the format string will not be expanded. (i.e. something 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// like SafeSPrintf(buf, "%p %d", 1, 2) results in "%p 2"). See above for 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// the use of RAW_CHECK() in debug builds, though. 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Basic example: 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// char buf[20]; 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// base::strings::SafeSPrintf(buf, "The answer: %2d", 42); 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Example with dynamically sized buffer (async-signal-safe). This code won't 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// work on Visual studio, as it requires dynamically allocating arrays on the 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// stack. Consider picking a smaller value for |kMaxSize| if stack size is 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// limited and known. On the other hand, if the parameters to SafeSNPrintf() 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// are trusted and not controllable by the user, you can consider eliminating 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// the check for |kMaxSize| altogether. The current value of SSIZE_MAX is 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// essentially a no-op that just illustrates how to implement an upper bound: 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// const size_t kInitialSize = 128; 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// const size_t kMaxSize = std::numeric_limits<ssize_t>::max(); 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// size_t size = kInitialSize; 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// for (;;) { 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// char buf[size]; 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// size = SafeSNPrintf(buf, size, "Error message \"%s\"\n", err) + 1; 12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// if (sizeof(buf) < kMaxSize && size > kMaxSize) { 12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// size = kMaxSize; 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// continue; 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// } else if (size > sizeof(buf)) 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// continue; 12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// write(2, buf, size-1); 13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// break; 13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// } 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace internal { 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Helpers that use C++ overloading, templates, and specializations to deduce 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// and record type information from function arguments. This allows us to 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// later write a type-safe version of snprintf(). 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)struct Arg { 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) enum Type { INT, UINT, STRING, POINTER }; 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Any integer-like value. 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(signed char c) : type(INT) { 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = c; 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(char); 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(unsigned char c) : type(UINT) { 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = c; 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(char); 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(signed short j) : type(INT) { 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(short); 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(unsigned short j) : type(UINT) { 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(short); 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(signed int j) : type(INT) { 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(int); 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(unsigned int j) : type(UINT) { 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(int); 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(signed long j) : type(INT) { 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(long); 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(unsigned long j) : type(UINT) { 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(long); 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(signed long long j) : type(INT) { 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(long long); 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg(unsigned long long j) : type(UINT) { 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.i = j; 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch integer.width = sizeof(long long); 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // A C-style text string. 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Arg(const char* s) : str(s), type(STRING) { } 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Arg(char* s) : str(s), type(STRING) { } 18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Any pointer value that can be cast to a "void*". 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) template<class T> Arg(T* p) : ptr((void*)p), type(POINTER) { } 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) union { 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // An integer-like value. 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) struct { 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int64_t i; 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) unsigned char width; 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } integer; 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // A C-style text string. 19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const char* str; 19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // A pointer to an arbitrary object. 20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const void* ptr; 20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const enum Type type; 20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}; 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This is the internal function that performs the actual formatting of 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// an snprintf()-style format string. 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const Arg* args, size_t max_args); 21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if !defined(NDEBUG) 21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// In debug builds, allow unit tests to artificially lower the kSSizeMax 21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// constant that is used as a hard upper-bound for all buffers. In normal 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// use, this constant should always be std::numeric_limits<ssize_t>::max(). 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)BASE_EXPORT void SetSafeSPrintfSSizeMaxForTest(size_t max); 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)BASE_EXPORT size_t GetSafeSPrintfSSizeMaxForTest(); 21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif 21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace internal 22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// TODO(markus): C++11 has a much more concise and readable solution for 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// expressing what we are doing here. 22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2, class T3, class T4, 22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T5, class T6, class T7, class T8, class T9> 22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) { 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, 23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T0, class T1, class T2, class T3, class T4, 23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T5, class T6, class T7, class T8, class T9> 24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, 24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, 24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) { 24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2, class T3, class T4, 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T5, class T6, class T7, class T8> 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T5 arg5, T6 arg6, T7 arg7, T8 arg8) { 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, 26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T0, class T1, class T2, class T3, class T4, class T5, 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T6, class T7, class T8> 26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, 26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, 26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T5 arg5, T6 arg6, T7 arg7, T8 arg8) { 27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2, class T3, class T4, class T5, 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T6, class T7> 28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, 28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T5 arg5, T6 arg6, T7 arg7) { 28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T0, class T1, class T2, class T3, class T4, class T5, 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T6, class T7> 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T5 arg5, T6 arg6, T7 arg7) { 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2, class T3, class T4, class T5, 30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T6> 30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, 30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T5 arg5, T6 arg6) { 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T0, class T1, class T2, class T3, class T4, class T5, 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T6> 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, 32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T6 arg6) { 32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { 32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) arg0, arg1, arg2, arg3, arg4, arg5, arg6 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2, class T3, class T4, class T5> 33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { 33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4, arg5 }; 33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, 34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class T0, class T1, class T2, class T3, class T4, class T5> 34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, 34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { 34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4, arg5 }; 34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2, class T3, class T4> 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { 35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4 }; 35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, class T0, class T1, class T2, class T3, class T4> 36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1, 36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T2 arg2, T3 arg3, T4 arg4) { 36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4 }; 36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2, class T3> 37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3) { 37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3 }; 37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, class T0, class T1, class T2, class T3> 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2, T3 arg3) { 38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3 }; 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1, class T2> 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T0 arg0, T1 arg1, T2 arg2) { 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2 }; 39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, class T0, class T1, class T2> 39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1, 39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) T2 arg2) { 39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1, arg2 }; 40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0, class T1> 40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, T0 arg0, T1 arg1) { 40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1 }; 41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, class T0, class T1> 41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1) { 41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0, arg1 }; 41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 42058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<class T0> 42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, T0 arg0) { 42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0 }; 42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N, class T0> 43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0) { 43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Use Arg() object to record type information and then copy arguments to an 43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // array to make it easier to iterate over them. 43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const internal::Arg arg_array[] = { arg0 }; 43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); 43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Fast-path when we don't actually need to substitute any arguments. 43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt); 43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<size_t N> 44058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)inline ssize_t SafeSPrintf(char (&buf)[N], const char* fmt) { 44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return SafeSNPrintf(buf, N, fmt); 44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 44358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 44458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace strings 44558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace base 44658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 44758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif // BASE_STRINGS_SAFE_SPRINTF_H_ 448