forked from dynexcoin/DynexSolve
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdprintf.cpp
More file actions
104 lines (91 loc) · 3.17 KB
/
dprintf.cpp
File metadata and controls
104 lines (91 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
////////////////////////////////////////////////////////////////////////////////
// Author: Andy Rushton
// Copyright: (c) Southampton University 1999-2004
// (c) Andy Rushton 2004 onwards
// License: BSD License, see ../docs/license.html
//
// Notes:
//
// Original version did a lot of formatting itself, re-inventing the C-runtime
// functions
//
// Feb 2007: Rewritten in terms of platform-specific fixes to the
// buffer-overflow problem. Using native functions for this has the added
// benefit of giving access to other features of the C-runtime such as Unicode
// support.
//
// Jan 2017: Rewritten because a platform-specific fix has been made obsolete,
// need to rethink the whole approach
//
////////////////////////////////////////////////////////////////////////////////
#include "dprintf.hpp"
#include <stdio.h>
#include <stdlib.h>
// fix for Visual Studios pre-VS2013 which don't define va_copy in their stdarg.h
// all other platforms *should* define this OK
// see https://stackoverflow.com/questions/558223/va-copy-porting-to-visual-c
#ifndef va_copy
#define va_copy(dest,src)(dest=src)
#endif
////////////////////////////////////////////////////////////////////////////////
namespace stlplus
{
int vdprintf(std::string& formatted, const char* format, va_list args)
{
// Note: cannot reuse a va_list, need to restart it each time it's used
// make a copy here - this means the copy is started but not traversed
va_list copy_args;
va_copy(copy_args, args);
// first work out the size of buffer needed to receive the formatted output
// do this by having a dummy run with a null buffer
int length = vsnprintf(0, 0, format, args);
// detect a coding error and give up straight away
// TODO - error handling? errno may be set and could be made into an exception
if (length < 0)
{
va_end(copy_args);
return length;
}
// allocate a buffer just exactly the right size, adding an extra byto for null termination
char* buffer = (char*)malloc(length+1);
if (!buffer)
{
va_end(copy_args);
return -1;
}
// now call the print function again to generate the actual formatted string
int result = vsnprintf(buffer, length+1, format, copy_args);
va_end(copy_args);
// TODO - error handling?
// now append this to the C++ string
formatted += buffer;
// recover the buffer memory
free(buffer);
return result;
}
int dprintf(std::string& formatted, const char* format, ...)
{
va_list args;
va_start(args, format);
int result = vdprintf(formatted, format, args);
va_end(args);
return result;
}
std::string vdformat(const char* format, va_list args)
{
std::string formatted;
int length = vdprintf(formatted, format, args);
if (length < 0) throw std::invalid_argument("dprintf");
return formatted;
}
std::string dformat(const char* format, ...)
{
std::string formatted;
va_list args;
va_start(args, format);
int length = vdprintf(formatted, format, args);
va_end(args);
if (length < 0) throw std::invalid_argument("dprintf");
return formatted;
}
} // end namespace stlplus