1 /*
2  * Copyright (C) 2004-2021 Exiv2 authors
3  * This program is part of the Exiv2 distribution.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include "image_int.hpp"
21 
22 #include <cstdarg>
23 #include <cstddef>
24 #include <cstring>
25 #include <vector>
26 #include <cstdio>
27 
28 namespace Exiv2
29 {
30     namespace Internal
31     {
stringFormat(const char * format,...)32         std::string stringFormat(const char* format, ...)
33         {
34             std::string result;
35             std::vector<char> buffer;
36             size_t need = std::strlen(format)*8;  // initial guess
37             int rc = -1;
38 
39             // vsnprintf writes at most size (2nd parameter) bytes (including \0)
40             //           returns the number of bytes required for the formatted string excluding \0
41             // the following loop goes through:
42             // one iteration (if 'need' was large enough for the for formatted string)
43             // or two iterations (after the first call to vsnprintf we know the required length)
44             do {
45                 buffer.resize(need + 1);
46                 va_list args;            // variable arg list
47                 va_start(args, format);  // args start after format
48                 rc = vsnprintf(&buffer[0], buffer.size(), format, args);
49                 va_end(args);     // free the args
50                 assert(rc >= 0);  // rc < 0 => we have made an error in the format string
51                 if (rc > 0)
52                     need = static_cast<size_t>(rc);
53             } while (buffer.size() <= need);
54 
55             if (rc > 0)
56                 result = std::string(&buffer[0], need);
57             return result;
58         }
59 
binaryToHex(const byte * data,size_t size)60         std::string binaryToHex(const byte* data, size_t size)
61         {
62             std::stringstream hexOutput;
63 
64             unsigned long tl = (unsigned long)((size / 16) * 16);
65             unsigned long tl_offset = (unsigned long)(size - tl);
66 
67             for (unsigned long loop = 0; loop < (unsigned long)size; loop++) {
68                 if (data[loop] < 16) {
69                     hexOutput << "0";
70                 }
71                 hexOutput << std::hex << (int)data[loop];
72                 if ((loop % 8) == 7) {
73                     hexOutput << "  ";
74                 }
75                 if ((loop % 16) == 15 || loop == (tl + tl_offset - 1)) {
76                     int max = 15;
77                     if (loop >= tl) {
78                         max = tl_offset - 1;
79                         for (int offset = 0; offset < (int)(16 - tl_offset); offset++) {
80                             if ((offset % 8) == 7) {
81                                 hexOutput << "  ";
82                             }
83                             hexOutput << "   ";
84                         }
85                     }
86                     hexOutput << " ";
87                     for (int offset = max; offset >= 0; offset--) {
88                         if (offset == (max - 8)) {
89                             hexOutput << "  ";
90                         }
91                         byte c = '.';
92                         if (data[loop - offset] >= 0x20 && data[loop - offset] <= 0x7E) {
93                             c = data[loop - offset];
94                         }
95                         hexOutput << (char)c;
96                     }
97                     hexOutput << std::endl;
98                 }
99             }
100 
101             hexOutput << std::endl << std::endl << std::endl;
102 
103             return hexOutput.str();
104         }
105 
indent(int32_t d)106         std::string indent(int32_t d)
107         {
108             std::string result;
109             if (d > 0)
110                 while (d--)
111                     result += "  ";
112             return result;
113         }
114 
115     }  // namespace Internal
116 
117 }  // namespace Exiv2
118