xref: /trafficserver/src/tscore/ink_sprintf.cc (revision 4cfd5a73)
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