]>
git.saurik.com Git - apple/libplatform.git/blob - src/simple/string_io.c
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)
43 /* we use a small buffer to minimize stack usage constraints */
52 void (*full
)(struct _BUF
*);
55 /* flush the buffer */
60 ssize_t n
= b
->ptr
- buf
;
64 w
= write(b
->fd
, buf
, n
);
66 if (errno
== EINTR
|| errno
== EAGAIN
)
75 /* flush the buffer and reset the pointer */
83 /* enlarge the buffer */
92 new = (vm_address_t
)(b
->end
+ 1);
93 if(vm_allocate(mach_task_self(), &new, VM_PAGE_SIZE
, 0) == 0) {
94 /* page is adjacent */
95 b
->end
+= VM_PAGE_SIZE
;
99 snew
= (sold
+ VM_PAGE_SIZE
) & ~(VM_PAGE_SIZE
- 1);
100 if ((kr
= vm_allocate(mach_task_self(), &new, snew
, 1)) != 0) {
101 __LIBPLATFORM_CLIENT_CRASH__(kr
, "Failed to allocate memory for buffer");
103 diff
= new - (vm_address_t
)b
->buf
;
104 memmove((void *)new, b
->buf
, sold
);
105 if((intptr_t)(b
->buf
) & (VM_PAGE_SIZE
- 1)) {
106 sold
&= ~(VM_PAGE_SIZE
- 1);
107 b
->buf
= (char *)((intptr_t)(b
->buf
+ VM_PAGE_SIZE
) & ~(VM_PAGE_SIZE
- 1));
108 b
->end
= (char *)(new + snew
- 1);
110 b
->end
+= diff
+ VM_PAGE_SIZE
;
112 vm_deallocate(mach_task_self(), (vm_address_t
)b
->buf
, sold
);
114 b
->buf
= (char *)new;
118 static inline void put_s(BUF
*, _esc_func
, const char *);
119 /* output a single character */
121 put_c(BUF
*b
, _esc_func esc
, unsigned char c
)
125 if(esc
&& (cp
= esc(c
)) != NULL
)
134 /* output a null-terminated string */
136 put_s(BUF
*b
, _esc_func esc
, const char *str
)
139 put_c(b
, esc
, *str
++);
142 /* output a string of the specified size */
144 put_n(BUF
*b
, _esc_func esc
, const char *str
, ssize_t n
)
147 put_c(b
, esc
, *str
++);
151 * Output the signed decimal string representing the number in "in". "width" is
152 * the minimum field width, and "zero" is a boolean value, true for zero padding
153 * (otherwise blank padding).
156 dec(BUF
*b
, _esc_func esc
, long long in
, int width
, int zero
)
159 char *cp
= buf
+ sizeof(buf
);
162 unsigned long long n
= (unsigned long long)in
;
172 *--cp
= (n
% 10) + '0';
181 pad
= width
- strlen(cp
);
182 zero
= zero
? '0' : ' ';
191 * Output the octal string representing the number in "n". "width" is
192 * the minimum field width, and "zero" is a boolean value, true for zero padding
193 * (otherwise blank padding).
196 oct(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
)
199 char *cp
= buf
+ sizeof(buf
);
205 *--cp
= (n
% 8) + '0';
211 pad
= width
- strlen(cp
);
212 zero
= zero
? '0' : ' ';
220 * Output the hex string representing the number in "n". "width" is the
221 * minimum field width, and "zero" is a boolean value, true for zero padding
222 * (otherwise blank padding). "upper" is a boolean value, true for upper
223 * case hex characters, lower case otherwise. "p" is a boolean value, true
224 * if 0x should be prepended (for %p), otherwise nothing.
226 static const char _h
[] = "0123456789abcdef";
227 static const char _H
[] = "0123456789ABCDEF";
228 static const char _0x
[] = "0x";
231 hex(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
, int upper
, int p
)
234 char *cp
= buf
+ sizeof(buf
);
235 const char *h
= upper
? _H
: _h
;
253 zero
= zero
? '0' : ' ';
262 * Output the unsigned decimal string representing the number in "n". "width"
263 * is the minimum field width, and "zero" is a boolean value, true for zero
264 * padding (otherwise blank padding).
267 udec(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
)
270 char *cp
= buf
+ sizeof(buf
);
276 *--cp
= (n
% 10) + '0';
281 pad
= width
- strlen(cp
);
282 zero
= zero
? '0' : ' ';
289 * Output the unsigned decimal string representing the number in "n", rounded
290 * to the nearest MB, KB or b. "width" is the minimum field width, and "zero"
291 * is a boolean value, true for zero padding (otherwise blank padding).
294 ydec(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
)
296 if(n
>= 10 * (1 << 20)) {
298 udec(b
, esc
, n
>> 20, width
, zero
);
300 } else if (n
>= 10 * (1 << 10)) {
302 udec(b
, esc
, n
>> 10, width
, zero
);
305 udec(b
, esc
, n
, width
, zero
);
311 * The actual engine for all the _simple_*printf routines.
314 __simple_bprintf(BUF
*b
, _esc_func esc
, const char *fmt
, va_list ap
)
317 int lflag
, zero
, width
;
319 if(!(cp
= strchr(fmt
, '%'))) {
323 put_n(b
, esc
, fmt
, cp
- fmt
);
330 lflag
= zero
= width
= 0;
337 case '1': case '2': case '3': case '4': case '5':
338 case '6': case '7': case '8': case '9':
339 while(*fmt
>= '0' && *fmt
<= '9')
340 width
= 10 * width
+ (*fmt
++ - '0');
343 zero
= zero
? '0' : ' ';
347 put_c(b
, esc
, va_arg(ap
, int));
352 dec(b
, esc
, va_arg(ap
, int), width
, zero
);
355 dec(b
, esc
, va_arg(ap
, long), width
, zero
);
358 dec(b
, esc
, va_arg(ap
, long long), width
, zero
);
369 oct(b
, esc
, va_arg(ap
, int), width
, zero
);
372 oct(b
, esc
, va_arg(ap
, long), width
, zero
);
375 oct(b
, esc
, va_arg(ap
, long long), width
, zero
);
380 hex(b
, esc
, (unsigned long)va_arg(ap
, void *), width
, zero
, 0, 1);
383 cp
= va_arg(ap
, char *);
384 cp
= cp
? cp
: "(null)";
386 zero
= zero
? '0' : ' ';
394 udec(b
, esc
, va_arg(ap
, unsigned int), width
, zero
);
397 udec(b
, esc
, va_arg(ap
, unsigned long), width
, zero
);
400 udec(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
);
407 hex(b
, esc
, va_arg(ap
, unsigned int), width
, zero
,
411 hex(b
, esc
, va_arg(ap
, unsigned long), width
, zero
,
415 hex(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
,
423 ydec(b
, esc
, va_arg(ap
, unsigned int), width
, zero
);
426 ydec(b
, esc
, va_arg(ap
, unsigned long), width
, zero
);
429 ydec(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
);
444 * A simplified vfprintf variant. The format string is interpreted with
445 * arguments from the va_list, and the results are written to the given
449 _simple_vdprintf(int fd
, const char *fmt
, va_list ap
)
457 b
.end
= b
.buf
+ MYBUFSIZE
;
458 b
.full
= _flush_reset
;
459 __simple_bprintf(&b
, NULL
, fmt
, ap
);
464 * A simplified fprintf variant. The format string is interpreted with
465 * arguments from the variable argument list, and the results are written
466 * to the given file descriptor.
469 _simple_dprintf(int fd
, const char *fmt
, ...)
474 _simple_vdprintf(fd
, fmt
, ap
);
479 * A simplified string allocate routine. Pass the opaque pointer to structure
480 * to _simple_*sprintf() routines. Use _simple_string() to retrieve the
481 * current string (the string is guaranteed to be null terminated only on
482 * the call to _simple_string()). Use _simple_sfree() to free the structure
490 if(vm_allocate(mach_task_self(), (vm_address_t
*)&b
, VM_PAGE_SIZE
, 1))
492 b
->ptr
= b
->buf
= (char *)b
+ sizeof(BUF
);
493 b
->end
= (char *)b
+ VM_PAGE_SIZE
- 1;
495 return (_SIMPLE_STRING
)b
;
499 * The format string is interpreted with arguments from the va_list, and the
500 * results are appended to the string maintained by the opaque structure, as
501 * returned by a previous call to _simple_salloc(). Non-zero is returned on
502 * out-of-memory error.
505 _simple_vsprintf(_SIMPLE_STRING b
, const char *fmt
, va_list ap
)
507 return _simple_vesprintf(b
, NULL
, fmt
, ap
);
511 * The format string is interpreted with arguments from the variable argument
512 * list, and the results are appended to the string maintained by the opaque
513 * structure, as returned by a previous call to _simple_salloc(). Non-zero is
514 * returned on out-of-memory error.
517 _simple_sprintf(_SIMPLE_STRING b
, const char *fmt
, ...)
523 ret
= _simple_vesprintf(b
, NULL
, fmt
, ap
);
529 * Like _simple_vsprintf(), except __esc is a function to call on each
530 * character; the function returns NULL if the character should be passed
531 * as is, otherwise, the returned character string is used instead.
534 _simple_vesprintf(_SIMPLE_STRING b
, _esc_func esc
, const char *fmt
, va_list ap
)
536 __simple_bprintf((BUF
*)b
, esc
, fmt
, ap
);
541 * Like _simple_sprintf(), except __esc is a function to call on each
542 * character; the function returns NULL if the character should be passed
543 * as is, otherwise, the returned character string is used instead.
545 int _simple_esprintf(_SIMPLE_STRING b
, _esc_func esc
, const char *fmt
, ...)
551 ret
= _simple_vesprintf(b
, esc
, fmt
, ap
);
557 * Return the null terminated string from the opaque structure, as returned
558 * by a previous call to _simple_salloc().
561 _simple_string(_SIMPLE_STRING b
)
563 *((BUF
*)b
)->ptr
= 0;
564 return ((BUF
*)b
)->buf
;
568 * Reposition the pointer to the first null in the buffer. After a call to
569 * _simple_string, the buffer can be modified, and shrunk.
572 _simple_sresize(_SIMPLE_STRING b
)
574 ((BUF
*)b
)->ptr
= ((BUF
*)b
)->buf
+ strlen(((BUF
*)b
)->buf
);
578 * Append the null-terminated string to the string associated with the opaque
579 * structure. Non-zero is returned on out-of-memory error.
582 _simple_sappend(_SIMPLE_STRING b
, const char *str
)
584 return _simple_esappend(b
, NULL
, str
);
588 * Like _simple_sappend(), except __esc is a function to call on each
589 * character; the function returns NULL if the character should be passed
590 * as is, otherwise, the returned character string is used instead.
592 int _simple_esappend(_SIMPLE_STRING b
, _esc_func esc
, const char *str
)
594 put_s((BUF
*)b
, esc
, str
);
599 * Write the string associated with the opaque structure to the file descriptor.
602 _simple_put(_SIMPLE_STRING b
, int fd
)
609 * Write the string associated with the opaque structure and a trailing newline,
610 * to the file descriptor.
613 _simple_putline(_SIMPLE_STRING b
, int fd
)
616 *((BUF
*)b
)->ptr
++ = '\n';
622 * Free the opaque structure, and the associated string.
625 _simple_sfree(_SIMPLE_STRING b
)
629 if(b
== NULL
) return;
630 if(((intptr_t)(((BUF
*)b
)->buf
) & (VM_PAGE_SIZE
- 1)) == 0) {
631 vm_deallocate(mach_task_self(), (vm_address_t
)((BUF
*)b
)->buf
, BUF_SIZE(b
));
634 s
= ((BUF
*)b
)->end
- (char *)b
+ 1;
636 vm_deallocate(mach_task_self(), (vm_address_t
)b
, s
);