1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_main.h>
8
9
10 /*
11 * Supported formats:
12 * %s null-terminated string
13 * %*s length and string
14 * %FN nxt_file_name_t *
15 * %V nxt_str_t *
16 * %Z '\0', this null is not counted in file name lenght.
17 */
18
19 nxt_int_t
nxt_file_name_create(nxt_mp_t * mp,nxt_file_name_str_t * file_name,const char * format,...)20 nxt_file_name_create(nxt_mp_t *mp, nxt_file_name_str_t *file_name,
21 const char *format, ...)
22 {
23 u_char ch, *p;
24 size_t length;
25 va_list args;
26 nxt_str_t *v;
27 nxt_bool_t zero;
28 const char *fmt;
29 nxt_file_name_t *dst, *fn;
30
31 va_start(args, format);
32 fmt = format;
33 zero = 0;
34 length = 0;
35
36 for ( ;; ) {
37 ch = *fmt++;
38
39 if (ch != '%') {
40
41 if (ch != '\0') {
42 length++;
43 continue;
44 }
45
46 break;
47 }
48
49 ch = *fmt++;
50
51 switch (ch) {
52
53 case 'V':
54 v = va_arg(args, nxt_str_t *);
55
56 if (nxt_fast_path(v != NULL)) {
57 length += v->length;
58 }
59
60 continue;
61
62 case 's':
63 p = va_arg(args, u_char *);
64
65 if (nxt_fast_path(p != NULL)) {
66 while (*p != '\0') {
67 p++;
68 length++;
69 }
70 }
71
72 continue;
73
74 case '*':
75 length += va_arg(args, u_int);
76 fmt++;
77
78 continue;
79
80 case 'F':
81 ch = *fmt++;
82
83 if (nxt_fast_path(ch == 'N')) {
84 fn = va_arg(args, nxt_file_name_t *);
85
86 if (nxt_fast_path(fn != NULL)) {
87 while (*fn != '\0') {
88 fn++;
89 length += sizeof(nxt_file_name_t);
90 }
91 }
92 }
93
94 continue;
95
96 case 'Z':
97 zero = 1;
98 length++;
99 continue;
100
101 default:
102 continue;
103 }
104 }
105
106 va_end(args);
107
108 if (length == 0) {
109 return NXT_ERROR;
110 }
111
112 file_name->len = length - zero;
113
114 fn = nxt_file_name_alloc(mp, length);
115 if (nxt_slow_path(fn == NULL)) {
116 return NXT_ERROR;
117 }
118
119 file_name->start = fn;
120 dst = fn;
121
122 va_start(args, format);
123 fmt = format;
124
125 for ( ;; ) {
126 ch = *fmt++;
127
128 if (ch != '%') {
129
130 if (ch != '\0') {
131 *dst++ = (nxt_file_name_t) ch;
132 continue;
133 }
134
135 break;
136 }
137
138 ch = *fmt++;
139
140 switch (ch) {
141
142 case 'V':
143 v = va_arg(args, nxt_str_t *);
144
145 if (nxt_fast_path(v != NULL)) {
146 dst = nxt_file_name_add(dst, v->start, v->length);
147 }
148
149 continue;
150
151 case 's':
152 p = va_arg(args, u_char *);
153
154 if (nxt_fast_path(p != NULL)) {
155 while (*p != '\0') {
156 *dst++ = (nxt_file_name_t) (*p++);
157 }
158 }
159
160 continue;
161
162 case '*':
163 length += va_arg(args, u_int);
164
165 ch = *fmt++;
166
167 if (nxt_fast_path(ch == 's')) {
168 p = va_arg(args, u_char *);
169 dst = nxt_file_name_add(dst, p, length);
170 }
171
172 continue;
173
174 case 'F':
175 ch = *fmt++;
176
177 if (nxt_fast_path(ch == 'N')) {
178 fn = va_arg(args, nxt_file_name_t *);
179
180 if (nxt_fast_path(fn != NULL)) {
181 while (*fn != '\0') {
182 *dst++ = *fn++;
183 }
184 }
185 }
186
187 continue;
188
189 case 'Z':
190 *dst++ = '\0';
191 continue;
192
193 default:
194 continue;
195 }
196 }
197
198 va_end(args);
199
200 return NXT_OK;
201 }
202