#include "cfmunge.h"
#include <security_utilities/cfutilities.h>
#include <security_utilities/errors.h>
+#include <utilities/SecCFRelease.h>
namespace Security {
#define F_NUMBER 'N'
-//
-// Initialize a CFMunge. We start out with the default CFAllocator, and
-// we do not throw errors.
-//
-CFMunge::CFMunge(const char *fmt, va_list arg)
- : format(fmt), allocator(NULL), error(errSecSuccess)
-{
- va_copy(args, arg);
-}
-
-CFMunge::~CFMunge()
-{
- va_end(args);
-}
-
-
//
// Skip whitespace and other fluff and deliver the next significant character.
//
switch (*++format) {
case 'A':
++format;
- allocator = va_arg(args, CFAllocatorRef);
+ allocator = va_arg(*args, CFAllocatorRef);
return true;
case 'E':
++format;
- error = va_arg(args, OSStatus);
+ error = va_arg(*args, OSStatus);
return true;
default:
return false;
//
// The top constructor.
//
-CFTypeRef CFMake::make()
+CFTypeRef CF_RETURNS_RETAINED CFMake::make()
{
while (next() == '@')
parameter();
}
-CFTypeRef CFMake::makeformat()
+CFTypeRef CF_RETURNS_RETAINED CFMake::makeformat()
{
++format;
switch (*format++) {
case 'b': // blob (pointer, length)
{
- const void *data = va_arg(args, const void *);
- size_t length = va_arg(args, size_t);
+ const void *data = va_arg(*args, const void *);
+ size_t length = va_arg(*args, size_t);
return CFDataCreate(allocator, (const UInt8 *)data, length);
}
case F_BOOLEAN: // boolean (with int promotion)
- return va_arg(args, int) ? kCFBooleanTrue : kCFBooleanFalse;
+ return va_arg(*args, int) ? kCFBooleanTrue : kCFBooleanFalse;
case 'd':
- return makeCFNumber(va_arg(args, int));
+ return makeCFNumber(va_arg(*args, int));
case 's':
- return CFStringCreateWithCString(allocator, va_arg(args, const char *),
+ return CFStringCreateWithCString(allocator, va_arg(*args, const char *),
kCFStringEncodingUTF8);
case F_OBJECT:
- return CFRetain(va_arg(args, CFTypeRef));
+ return CFRetain(va_arg(*args, CFTypeRef));
case 'u':
- return makeCFNumber(va_arg(args, unsigned int));
+ return makeCFNumber(va_arg(*args, unsigned int));
default:
assert(false);
return NULL;
// Embedded strings can either be alphanumeric (only), or delimited with single quotes ''.
// No escapes are processed within such quotes. If you want arbitrary string values, use %s.
//
-CFTypeRef CFMake::makestring()
+CFTypeRef CF_RETURNS_RETAINED CFMake::makestring()
{
const char *start, *end;
if (*format == '\'') {
//
// Construct a CFDictionary
//
-CFTypeRef CFMake::makedictionary()
+CFTypeRef CF_RETURNS_RETAINED CFMake::makedictionary()
{
++format; // next '{'
next('!'); // indicates mutable (currently always true)
CFMutableDictionaryRef dict;
if (next('+')) { // {+%O, => copy dictionary argument, then proceed
if (next('%') && next('O')) {
- CFDictionaryRef source = va_arg(args, CFDictionaryRef);
+ CFDictionaryRef source = va_arg(*args, CFDictionaryRef);
dict = CFDictionaryCreateMutableCopy(allocator, NULL, source);
if (next('}'))
return dict;
} else
dict = CFDictionaryCreateMutable(allocator, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (dict == NULL)
+ return dict;
if (add(dict))
return dict;
else {
- CFRelease(dict);
+ CFReleaseSafe(dict);
return NULL;
}
}
//
// Construct a CFArray
//
-CFTypeRef CFMake::makearray()
+CFTypeRef CF_RETURNS_RETAINED CFMake::makearray()
{
++format; // next '['
next('!'); // indicates mutable (currently always)
- CFMutableArrayRef array = makeCFMutableArray(0);
+ CFMutableArrayRef array = NULL;
+ if (next('+')) { // {+%O, => copy array argument, then proceed
+ if (next('%') && next('O')) {
+ CFArrayRef source = va_arg(*args, CFArrayRef);
+ array = CFArrayCreateMutableCopy(allocator, 0, source);
+ if (next('}'))
+ return array;
+ } else
+ return NULL; // bad syntax
+ } else {
+ array = makeCFMutableArray(0);
+ }
while (next() != ']') {
CFTypeRef value = make();
if (value == NULL) {
//
class CFScan : public CFMake {
public:
- CFScan(const char *format, va_list args)
+ CFScan(const char *format, va_list *args)
: CFMake(format, args), suppress(false) { }
bool scan(CFTypeRef obj);
void CFScan::store(Type value)
{
if (!suppress)
- *va_arg(args, Type *) = value;
+ *va_arg(*args, Type *) = value;
}
switch (*format) {
case 'f': // %Bf - two arguments (value, &variable)
{
- unsigned flag = va_arg(args, unsigned);
- unsigned *value = va_arg(args, unsigned *);
+ unsigned flag = va_arg(*args, unsigned);
+ unsigned *value = va_arg(*args, unsigned *);
if (obj == kCFBooleanTrue && !suppress)
*value |= flag;
return true;
//
// The public functions
//
-CFTypeRef cfmake(const char *format, ...)
+CFTypeRef CF_RETURNS_RETAINED cfmake(const char *format, ...)
{
va_list args;
va_start(args, format);
- CFTypeRef result = CFMake(format, args).make();
+ CFTypeRef result = CFMake(format, &args).make();
va_end(args);
return result;
}
-CFTypeRef vcfmake(const char *format, va_list args)
+CFTypeRef CF_RETURNS_RETAINED vcfmake(const char *format, va_list *args)
{
return CFMake(format, args).make();
}
{
va_list args;
va_start(args, format);
- CFDictionaryRef result = CFMake(format, args).addto(dict);
+ CFDictionaryRef result = CFMake(format, &args).addto(dict);
va_end(args);
return result;
}
{
va_list args;
va_start(args, format);
- bool result = vcfscan(obj, format, args);
+ bool result = vcfscan(obj, format, &args);
va_end(args);
return result;
}
-bool vcfscan(CFTypeRef obj, const char *format, va_list args)
+bool vcfscan(CFTypeRef obj, const char *format, va_list *args)
{
return CFScan(format, args).scan(obj);
}
{
va_list args;
va_start(args, format);
- CFTypeRef result = vcfget(obj, format, args);
+ CFTypeRef result = vcfget(obj, format, &args);
va_end(args);
return result;
}
-CFTypeRef vcfget(CFTypeRef obj, const char *format, va_list args)
+CFTypeRef vcfget(CFTypeRef obj, const char *format, va_list *args)
{
return CFScan(format, args).dictpath(obj);
}