1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 /*****************************************************************************
25
26 ink_sprintf.cc
27
28 This file implements some Inktomi variants of sprintf, to do bounds
29 checking and length counting.
30
31
32 ****************************************************************************/
33
34 #include "tscore/ink_sprintf.h"
35
36 #define NUL '\0'
37
38 //////////////////////////////////////////////////////////////////////////////
39 //
40 // int ink_bsprintf(char *buffer, char *format, ...)
41 // int ink_bvsprintf(char *buffer, char *format, va_list ap)
42 //
43 // This is a very simplified version of sprintf that has the following
44 // behavior:
45 //
46 // (1) the length in output characters is returned, including final NUL
47 // (2) buffer can be nullptr, for just counting the output chars
48 // (3) only %s and %d are supported, with no field modifiers
49 //
50 //////////////////////////////////////////////////////////////////////////////
51
52 int
ink_bsprintf(char * buffer,const char * format,...)53 ink_bsprintf(char *buffer, const char *format, ...)
54 {
55 int l;
56
57 va_list ap;
58 va_start(ap, format);
59 l = ink_bvsprintf(buffer, format, ap);
60 va_end(ap);
61
62 return (l);
63 }
64
65 int
ink_bvsprintf(char * buffer,const char * format,va_list ap)66 ink_bvsprintf(char *buffer, const char *format, va_list ap)
67 {
68 int d_val;
69 const char *s;
70 char *d, *p, *s_val, d_buffer[32];
71 va_list ap_local;
72
73 va_copy(ap_local, ap);
74
75 s = format;
76 d = buffer;
77
78 while (*s) {
79 /////////////////////////////
80 // handle non-% characters //
81 /////////////////////////////
82
83 if (buffer) { // if have output buffer
84 while (*s && (*s != '%')) {
85 *d++ = *s++;
86 } // really copy, else
87 } else {
88 while (*s && (*s != '%')) {
89 d++;
90 s++;
91 } // pass over string
92 }
93
94 ///////////////////////////
95 // handle NUL characters //
96 ///////////////////////////
97
98 if (*s == NUL) {
99 break; // end of string
100 }
101
102 /////////////////////////
103 // handle % characters //
104 /////////////////////////
105
106 ++s; // consume % character
107
108 switch (*s) // dispatch on flag
109 {
110 case 's': // %s pattern
111 ++s; // consume 's'
112 s_val = va_arg(ap_local, char *); // grab string argument
113 p = s_val; // temporary pointer
114 if (buffer) { // if have output buffer
115 while (*p) {
116 *d++ = *p++;
117 } // copy value
118 } else { // else
119 while (*p) {
120 d++;
121 p++;
122 } // pass over value
123 }
124 break;
125 case 'd': // %d pattern
126 ++s; // consume 'd'
127 d_val = va_arg(ap_local, int); // grab integer argument
128 snprintf(d_buffer, sizeof(d_buffer), "%d", d_val); // stringify integer
129 p = d_buffer; // temporary pointer
130 if (buffer) { // if have output buffer
131 while (*p) {
132 *d++ = *p++;
133 } // copy value
134 } else { // else
135 while (*p) {
136 d++;
137 p++;
138 } // pass over value
139 }
140 break;
141 default: // something else
142 if (buffer) {
143 *d = *s; // copy unknown character
144 }
145 ++d;
146 ++s;
147 break;
148 }
149 }
150
151 if (buffer) {
152 *d = NUL;
153 }
154 ++d;
155
156 va_end(ap_local);
157 return static_cast<int>(d - buffer);
158 }
159