]>
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 hex string representing the number in "n". "width" is the
192 * minimum field width, and "zero" is a boolean value, true for zero padding
193 * (otherwise blank padding). "upper" is a boolean value, true for upper
194 * case hex characters, lower case otherwise. "p" is a boolean value, true
195 * if 0x should be prepended (for %p), otherwise nothing.
197 static const char _h
[] = "0123456789abcdef";
198 static const char _H
[] = "0123456789ABCDEF";
199 static const char _0x
[] = "0x";
202 hex(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
, int upper
, int p
)
205 char *cp
= buf
+ sizeof(buf
);
206 const char *h
= upper
? _H
: _h
;
224 zero
= zero
? '0' : ' ';
233 * Output the unsigned decimal string representing the number in "n". "width"
234 * is the minimum field width, and "zero" is a boolean value, true for zero
235 * padding (otherwise blank padding).
238 udec(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
)
241 char *cp
= buf
+ sizeof(buf
);
247 *--cp
= (n
% 10) + '0';
252 pad
= width
- strlen(cp
);
253 zero
= zero
? '0' : ' ';
260 * Output the unsigned decimal string representing the number in "n", rounded
261 * to the nearest MB, KB or b. "width" is the minimum field width, and "zero"
262 * is a boolean value, true for zero padding (otherwise blank padding).
265 ydec(BUF
*b
, _esc_func esc
, unsigned long long n
, int width
, int zero
)
267 if(n
>= 10 * (1 << 20)) {
269 udec(b
, esc
, n
>> 20, width
, zero
);
271 } else if (n
>= 10 * (1 << 10)) {
273 udec(b
, esc
, n
>> 10, width
, zero
);
276 udec(b
, esc
, n
, width
, zero
);
282 * The actual engine for all the _simple_*printf routines.
285 __simple_bprintf(BUF
*b
, _esc_func esc
, const char *fmt
, va_list ap
)
288 int lflag
, zero
, width
;
290 if(!(cp
= strchr(fmt
, '%'))) {
294 put_n(b
, esc
, fmt
, cp
- fmt
);
301 lflag
= zero
= width
= 0;
308 case '1': case '2': case '3': case '4': case '5':
309 case '6': case '7': case '8': case '9':
310 while(*fmt
>= '0' && *fmt
<= '9')
311 width
= 10 * width
+ (*fmt
++ - '0');
314 zero
= zero
? '0' : ' ';
318 put_c(b
, esc
, va_arg(ap
, int));
323 dec(b
, esc
, va_arg(ap
, int), width
, zero
);
326 dec(b
, esc
, va_arg(ap
, long), width
, zero
);
329 dec(b
, esc
, va_arg(ap
, long long), width
, zero
);
338 hex(b
, esc
, (unsigned long)va_arg(ap
, void *), width
, zero
, 0, 1);
341 cp
= va_arg(ap
, char *);
342 cp
= cp
? cp
: "(null)";
344 zero
= zero
? '0' : ' ';
352 udec(b
, esc
, va_arg(ap
, unsigned int), width
, zero
);
355 udec(b
, esc
, va_arg(ap
, unsigned long), width
, zero
);
358 udec(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
);
365 hex(b
, esc
, va_arg(ap
, unsigned int), width
, zero
,
369 hex(b
, esc
, va_arg(ap
, unsigned long), width
, zero
,
373 hex(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
,
381 ydec(b
, esc
, va_arg(ap
, unsigned int), width
, zero
);
384 ydec(b
, esc
, va_arg(ap
, unsigned long), width
, zero
);
387 ydec(b
, esc
, va_arg(ap
, unsigned long long), width
, zero
);
402 * A simplified vfprintf variant. The format string is interpreted with
403 * arguments from the va_list, and the results are written to the given
407 _simple_vdprintf(int fd
, const char *fmt
, va_list ap
)
415 b
.end
= b
.buf
+ MYBUFSIZE
;
416 b
.full
= _flush_reset
;
417 __simple_bprintf(&b
, NULL
, fmt
, ap
);
422 * A simplified fprintf variant. The format string is interpreted with
423 * arguments from the variable argument list, and the results are written
424 * to the given file descriptor.
427 _simple_dprintf(int fd
, const char *fmt
, ...)
432 _simple_vdprintf(fd
, fmt
, ap
);
437 * A simplified string allocate routine. Pass the opaque pointer to structure
438 * to _simple_*sprintf() routines. Use _simple_string() to retrieve the
439 * current string (the string is guaranteed to be null terminated only on
440 * the call to _simple_string()). Use _simple_sfree() to free the structure
448 if(vm_allocate(mach_task_self(), (vm_address_t
*)&b
, VM_PAGE_SIZE
, 1))
450 b
->ptr
= b
->buf
= (char *)b
+ sizeof(BUF
);
451 b
->end
= (char *)b
+ VM_PAGE_SIZE
- 1;
453 return (_SIMPLE_STRING
)b
;
457 * The format string is interpreted with arguments from the va_list, and the
458 * results are appended to the string maintained by the opaque structure, as
459 * returned by a previous call to _simple_salloc(). Non-zero is returned on
460 * out-of-memory error.
463 _simple_vsprintf(_SIMPLE_STRING b
, const char *fmt
, va_list ap
)
465 return _simple_vesprintf(b
, NULL
, fmt
, ap
);
469 * The format string is interpreted with arguments from the variable argument
470 * list, and the results are appended to the string maintained by the opaque
471 * structure, as returned by a previous call to _simple_salloc(). Non-zero is
472 * returned on out-of-memory error.
475 _simple_sprintf(_SIMPLE_STRING b
, const char *fmt
, ...)
481 ret
= _simple_vesprintf(b
, NULL
, fmt
, ap
);
487 * Like _simple_vsprintf(), except __esc is a function to call on each
488 * character; the function returns NULL if the character should be passed
489 * as is, otherwise, the returned character string is used instead.
492 _simple_vesprintf(_SIMPLE_STRING b
, _esc_func esc
, const char *fmt
, va_list ap
)
494 __simple_bprintf((BUF
*)b
, esc
, fmt
, ap
);
499 * Like _simple_sprintf(), except __esc is a function to call on each
500 * character; the function returns NULL if the character should be passed
501 * as is, otherwise, the returned character string is used instead.
503 int _simple_esprintf(_SIMPLE_STRING b
, _esc_func esc
, const char *fmt
, ...)
509 ret
= _simple_vesprintf(b
, esc
, fmt
, ap
);
515 * Return the null terminated string from the opaque structure, as returned
516 * by a previous call to _simple_salloc().
519 _simple_string(_SIMPLE_STRING b
)
521 *((BUF
*)b
)->ptr
= 0;
522 return ((BUF
*)b
)->buf
;
526 * Reposition the pointer to the first null in the buffer. After a call to
527 * _simple_string, the buffer can be modified, and shrunk.
530 _simple_sresize(_SIMPLE_STRING b
)
532 ((BUF
*)b
)->ptr
= ((BUF
*)b
)->buf
+ strlen(((BUF
*)b
)->buf
);
536 * Append the null-terminated string to the string associated with the opaque
537 * structure. Non-zero is returned on out-of-memory error.
540 _simple_sappend(_SIMPLE_STRING b
, const char *str
)
542 return _simple_esappend(b
, NULL
, str
);
546 * Like _simple_sappend(), except __esc is a function to call on each
547 * character; the function returns NULL if the character should be passed
548 * as is, otherwise, the returned character string is used instead.
550 int _simple_esappend(_SIMPLE_STRING b
, _esc_func esc
, const char *str
)
552 put_s((BUF
*)b
, esc
, str
);
557 * Write the string associated with the opaque structure to the file descriptor.
560 _simple_put(_SIMPLE_STRING b
, int fd
)
567 * Write the string associated with the opaque structure and a trailing newline,
568 * to the file descriptor.
571 _simple_putline(_SIMPLE_STRING b
, int fd
)
574 *((BUF
*)b
)->ptr
++ = '\n';
580 * Free the opaque structure, and the associated string.
583 _simple_sfree(_SIMPLE_STRING b
)
587 if(b
== NULL
) return;
588 if(((intptr_t)(((BUF
*)b
)->buf
) & (VM_PAGE_SIZE
- 1)) == 0) {
589 vm_deallocate(mach_task_self(), (vm_address_t
)((BUF
*)b
)->buf
, BUF_SIZE(b
));
592 s
= ((BUF
*)b
)->end
- (char *)b
+ 1;
594 vm_deallocate(mach_task_self(), (vm_address_t
)b
, s
);