struct archive_string * __archive_string_append(struct archive_string *as, const char *p, size_t s) { if (__archive_string_ensure(as, as->length + s + 1) == NULL) __archive_errx(1, "Out of memory"); memcpy(as->s + as->length, p, s); as->s[as->length + s] = 0; as->length += s; return (as); }
void __archive_string_concat(struct archive_string *dest, struct archive_string *src) { if (src->length > 0) { if (__archive_string_ensure(dest, dest->length + src->length + 1) == NULL) __archive_errx(1, "Out of memory"); memcpy(dest->s + dest->length, src->s, src->length); dest->length += src->length; dest->s[dest->length] = 0; } }
void __archive_string_copy(struct archive_string *dest, struct archive_string *src) { if (src->length == 0) dest->length = 0; else { if (__archive_string_ensure(dest, src->length + 1) == NULL) __archive_errx(1, "Out of memory"); memcpy(dest->s, src->s, src->length); dest->length = src->length; dest->s[dest->length] = 0; } }
/* * Like 'vsprintf', but ensures the target is big enough, resizing if * necessary. */ void __archive_string_vsprintf(struct archive_string *as, const char *fmt, va_list ap) { char long_flag; intmax_t s; /* Signed integer temp. */ uintmax_t u; /* Unsigned integer temp. */ const char *p, *p2; if (__archive_string_ensure(as, 64) == NULL) __archive_errx(1, "Out of memory"); if (fmt == NULL) { as->s[0] = 0; return; } for (p = fmt; *p != '\0'; p++) { const char *saved_p = p; if (*p != '%') { archive_strappend_char(as, *p); continue; } p++; long_flag = '\0'; switch(*p) { case 'j': long_flag = 'j'; p++; break; case 'l': long_flag = 'l'; p++; break; } switch (*p) { case '%': __archive_strappend_char(as, '%'); break; case 'c': s = va_arg(ap, int); __archive_strappend_char(as, s); break; case 'd': switch(long_flag) { case 'j': s = va_arg(ap, intmax_t); break; case 'l': s = va_arg(ap, long); break; default: s = va_arg(ap, int); break; } append_int(as, s, 10); break; case 's': p2 = va_arg(ap, char *); archive_strcat(as, p2); break; case 'o': case 'u': case 'x': case 'X': /* Common handling for unsigned integer formats. */ switch(long_flag) { case 'j': u = va_arg(ap, uintmax_t); break; case 'l': u = va_arg(ap, unsigned long); break; default: u = va_arg(ap, unsigned int); break; } /* Format it in the correct base. */ switch (*p) { case 'o': append_uint(as, u, 8); break; case 'u': append_uint(as, u, 10); break; default: append_uint(as, u, 16); break; } break; default: /* Rewind and print the initial '%' literally. */ p = saved_p; archive_strappend_char(as, *p); } } }