]>
git.saurik.com Git - apple/libplatform.git/blob - src/simple/string_io.c
2e581e85416da3a0051f508bbb1ae289458e0544
2 * Copyright (c) 2005, 2006, 2009 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #include <mach/mach_init.h>
27 #include <mach/vm_map.h>
30 #include "os/internal.h"
32 #include "platform/string.h"
33 #include "platform/compat.h"
36 #define VM_PAGE_SIZE 4096
39 #define BUF_SIZE(s) (((BUF *)(s))->end - ((BUF *)(s))->buf + 1)
40 /* we use a small buffer to minimize stack usage constraints */
48 void (*full
)(struct _BUF
*);
51 /* flush the buffer */
56 ssize_t n
= b
->ptr
- buf
;
60 w
= write(b
->fd
, buf
, n
);
62 if (errno
== EINTR
|| errno
== EAGAIN
)
71 /* flush the buffer and reset the pointer */
79 /* enlarge the buffer */
88 new = (vm_address_t
)(b
->end
+ 1);
89 if(vm_allocate(mach_task_self(), &new, VM_PAGE_SIZE
, 0) == 0) {
90 /* page is adjacent */
91 b
->end
+= VM_PAGE_SIZE
;
95 snew
= (sold
+ VM_PAGE_SIZE
) & ~(VM_PAGE_SIZE
- 1);
96 if ((kr
= vm_allocate(mach_task_self(), &new, snew
, 1)) != 0) {
97 __LIBPLATFORM_CLIENT_CRASH__(kr
, "Failed to allocate memory for buffer");
99 diff
= new - (vm_address_t
)b
->buf
;
100 memmove((void *)new, b
->buf
, sold
);
101 if((intptr_t)(b
->buf
) & (VM_PAGE_SIZE
- 1)) {
102 sold
&= ~(VM_PAGE_SIZE
- 1);
103 b
->buf
= (char *)((intptr_t)(b
->buf
+ VM_PAGE_SIZE
) & ~(VM_PAGE_SIZE
- 1));
104 b
->end
= (char *)(new + snew
- 1);
106 b
->end
+= diff
+ VM_PAGE_SIZE
;
108 vm_deallocate(mach_task_self(), (vm_address_t
)b
->buf
, sold
);
110 b
->buf
= (char *)new;
114 static inline void put_s(BUF
*, _esc_func
, const char *);
115 /* output a single character */
117 put_c(BUF
*b
, _esc_func esc
, unsigned char c
)
121 if(esc
&& (cp
= esc(c
)) != NULL
)
130 /* output a null-terminated string */
132 put_s(BUF
*b
, _esc_func esc
, const char *str
)
135 put_c(b
, esc
, *str
++);
138 /* output a string of the specified size */
140 put_n(BUF
*b
, _esc_func esc
, const char *str
, ssize_t n
)
143 put_c(b
, esc
, *str
++);
147 * Output the signed decimal string representing the number in "in". "width" is
148 * the minimum field width, and "zero" is a boolean value, true for zero padding
149 * (otherwise blank padding).
152 dec(BUF
*b
, _esc_func esc
, long long in
, int width
, int zero
)
155 char *cp
= buf
+ sizeof(buf
);
158 unsigned long long n
= (unsigned long long)in
;
168 *--cp
= (n
% 10) + '0';
177 pad
= width
- strlen(cp
);
178 zero
= zero
? '0' : ' ';
187 * Output the hex string representing the number in "n". "width" is the
188 * minimum field width, and "zero" is a boolean value, true for zero padding
189 * (otherwise blank padding). "upper" is a boolean value, true for upper
190 * case hex characters, lower case otherwise. "p" is a boolean value, true
191 * if 0x should be prepended (for %p), otherwise nothing.
193 static const char _h
[] = "0123456789abcdef";
194 static const char _H
[] = "0123456789ABCDEF";
195 static const char _0x
[] = "0x";
198 hex(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
, int upper
, int p
)
201 char *cp
= buf
+ sizeof(buf
);
202 const char *h
= upper
? _H
: _h
;
220 zero
= zero
? '0' : ' ';
229 * Output the unsigned decimal string representing the number in "n". "width"
230 * is the minimum field width, and "zero" is a boolean value, true for zero
231 * padding (otherwise blank padding).
234 udec(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
)
237 char *cp
= buf
+ sizeof(buf
);
243 *--cp
= (n
% 10) + '0';
248 pad
= width
- strlen(cp
);
249 zero
= zero
? '0' : ' ';
256 * Output the unsigned decimal string representing the number in "n", rounded
257 * to the nearest MB, KB or b. "width" is the minimum field width, and "zero"
258 * is a boolean value, true for zero padding (otherwise blank padding).
261 ydec(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
)
263 if(n
>= 10 * (1 << 20)) {
265 udec(b
, esc
, n
>> 20, width
, zero
);
267 } else if (n
>= 10 * (1 << 10)) {
269 udec(b
, esc
, n
>> 10, width
, zero
);
272 udec(b
, esc
, n
, width
, zero
);
278 * The actual engine for all the _simple_*printf routines.
281 __simple_bprintf(BUF
*b
, _esc_func esc
, const char *fmt
, va_list ap
)
284 int lflag
, zero
, width
;
286 if(!(cp
= strchr(fmt
, '%'))) {
290 put_n(b
, esc
, fmt
, cp
- fmt
);
297 lflag
= zero
= width
= 0;
304 case '1': case '2': case '3': case '4': case '5':
305 case '6': case '7': case '8': case '9':
306 while(*fmt
>= '0' && *fmt
<= '9')
307 width
= 10 * width
+ (*fmt
++ - '0');
310 zero
= zero
? '0' : ' ';
314 put_c(b
, esc
, va_arg(ap
, int));
319 dec(b
, esc
, va_arg(ap
, int), width
, zero
);
322 dec(b
, esc
, va_arg(ap
, long), width
, zero
);
325 dec(b
, esc
, va_arg(ap
, long long), width
, zero
);
334 hex(b
, esc
, (unsigned long)va_arg(ap
, void *), width
, zero
, 0, 1);
337 cp
= va_arg(ap
, char *);
338 cp
= cp
? cp
: "(null)";
340 zero
= zero
? '0' : ' ';
348 udec(b
, esc
, va_arg(ap
, unsigned int), width
, zero
);
351 udec(b
, esc
, va_arg(ap
, unsigned long), width
, zero
);
354 udec(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
);
361 hex(b
, esc
, va_arg(ap
, unsigned int), width
, zero
,
365 hex(b
, esc
, va_arg(ap
, unsigned long), width
, zero
,
369 hex(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
,
377 ydec(b
, esc
, va_arg(ap
, unsigned int), width
, zero
);
380 ydec(b
, esc
, va_arg(ap
, unsigned long), width
, zero
);
383 ydec(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
);
398 * A simplified vfprintf variant. The format string is interpreted with
399 * arguments from the va_list, and the results are written to the given
403 _simple_vdprintf(int fd
, const char *fmt
, va_list ap
)
411 b
.end
= b
.buf
+ MYBUFSIZE
;
412 b
.full
= _flush_reset
;
413 __simple_bprintf(&b
, NULL
, fmt
, ap
);
418 * A simplified fprintf variant. The format string is interpreted with
419 * arguments from the variable argument list, and the results are written
420 * to the given file descriptor.
423 _simple_dprintf(int fd
, const char *fmt
, ...)
428 _simple_vdprintf(fd
, fmt
, ap
);
433 * A simplified string allocate routine. Pass the opaque pointer to structure
434 * to _simple_*sprintf() routines. Use _simple_string() to retrieve the
435 * current string (the string is guaranteed to be null terminated only on
436 * the call to _simple_string()). Use _simple_sfree() to free the structure
445 kr
= vm_allocate(mach_task_self(), (vm_address_t
*)&b
, VM_PAGE_SIZE
, 1);
447 __LIBPLATFORM_CLIENT_CRASH__(kr
, "Failed to allocate memory for string");
449 b
->ptr
= b
->buf
= (char *)b
+ sizeof(BUF
);
450 b
->end
= (char *)b
+ VM_PAGE_SIZE
- 1;
452 return (_SIMPLE_STRING
)b
;
456 * The format string is interpreted with arguments from the va_list, and the
457 * results are appended to the string maintained by the opaque structure, as
458 * returned by a previous call to _simple_salloc(). Always returns 0.
461 _simple_vsprintf(_SIMPLE_STRING b
, const char *fmt
, va_list ap
)
463 return _simple_vesprintf(b
, NULL
, fmt
, ap
);
467 * The format string is interpreted with arguments from the variable argument
468 * list, and the results are appended to the string maintained by the opaque
469 * structure, as returned by a previous call to _simple_salloc().
473 _simple_sprintf(_SIMPLE_STRING b
, const char *fmt
, ...)
479 ret
= _simple_vesprintf(b
, NULL
, fmt
, ap
);
485 * Like _simple_vsprintf(), except __esc is a function to call on each
486 * character; the function returns NULL if the character should be passed
487 * as is, otherwise, the returned character string is used instead.
490 _simple_vesprintf(_SIMPLE_STRING b
, _esc_func esc
, const char *fmt
, va_list ap
)
492 __simple_bprintf((BUF
*)b
, esc
, fmt
, ap
);
497 * Like _simple_sprintf(), except __esc is a function to call on each
498 * character; the function returns NULL if the character should be passed
499 * as is, otherwise, the returned character string is used instead.
501 int _simple_esprintf(_SIMPLE_STRING b
, _esc_func esc
, const char *fmt
, ...)
507 ret
= _simple_vesprintf(b
, esc
, fmt
, ap
);
513 * Return the null terminated string from the opaque structure, as returned
514 * by a previous call to _simple_salloc().
517 _simple_string(_SIMPLE_STRING b
)
519 *((BUF
*)b
)->ptr
= 0;
520 return ((BUF
*)b
)->buf
;
524 * Reposition the pointer to the first null in the buffer. After a call to
525 * _simple_string, the buffer can be modified, and shrunk.
528 _simple_sresize(_SIMPLE_STRING b
)
530 ((BUF
*)b
)->ptr
= ((BUF
*)b
)->buf
+ strlen(((BUF
*)b
)->buf
);
534 * Append the null-terminated string to the string associated with the opaque
535 * structure. Always returns 0.
538 _simple_sappend(_SIMPLE_STRING b
, const char *str
)
540 return _simple_esappend(b
, NULL
, str
);
544 * Like _simple_sappend(), except __esc is a function to call on each
545 * character; the function returns NULL if the character should be passed
546 * as is, otherwise, the returned character string is used instead.
548 int _simple_esappend(_SIMPLE_STRING b
, _esc_func esc
, const char *str
)
550 put_s((BUF
*)b
, esc
, str
);
555 * Write the string associated with the opaque structure to the file descriptor.
558 _simple_put(_SIMPLE_STRING b
, int fd
)
565 * Write the string associated with the opaque structure and a trailing newline,
566 * to the file descriptor.
569 _simple_putline(_SIMPLE_STRING b
, int fd
)
572 *((BUF
*)b
)->ptr
++ = '\n';
578 * Free the opaque structure, and the associated string.
581 _simple_sfree(_SIMPLE_STRING b
)
585 if(b
== NULL
) return;
586 if(((intptr_t)(((BUF
*)b
)->buf
) & (VM_PAGE_SIZE
- 1)) == 0) {
587 vm_deallocate(mach_task_self(), (vm_address_t
)((BUF
*)b
)->buf
, BUF_SIZE(b
));
590 s
= ((BUF
*)b
)->end
- (char *)b
+ 1;
592 vm_deallocate(mach_task_self(), (vm_address_t
)b
, s
);