60 lines
2.5 KiB
Objective-C
60 lines
2.5 KiB
Objective-C
// Code credit to @mxcl. Based on:
|
|
// https://github.com/mxcl/OMGHTTPURLRQ/blob/a757e2a3043c5f031b23ef8dadf82a97856dbfab/Sources/OMGFormURLEncode.m
|
|
//
|
|
|
|
#import "ARTFormEncode.h"
|
|
|
|
static inline NSString *enc(id in, NSString *ignore) {
|
|
NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet characterSetWithCharactersInString:ignore];
|
|
[allowedSet formUnionWithCharacterSet:[NSCharacterSet URLQueryAllowedCharacterSet]];
|
|
[allowedSet removeCharactersInString:@":/?&=;+!@#$()',*"];
|
|
|
|
return [[in description] stringByAddingPercentEncodingWithAllowedCharacters:allowedSet];
|
|
}
|
|
|
|
#define enckey(in) enc(in, @"[]")
|
|
#define encval(in) enc(in, @"")
|
|
|
|
static NSArray *DoQueryMagic(NSString *key, id value) {
|
|
NSMutableArray *parts = [NSMutableArray new];
|
|
|
|
// Sort dictionary keys to ensure consistent ordering in query string,
|
|
// which is important when deserializing potentially ambiguous sequences,
|
|
// such as an array of dictionaries
|
|
#define sortDescriptor [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)]
|
|
|
|
if ([value isKindOfClass:[NSDictionary class]]) {
|
|
NSDictionary *dictionary = value;
|
|
for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor]]) {
|
|
id recursiveKey = key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey;
|
|
[parts addObjectsFromArray:DoQueryMagic(recursiveKey, dictionary[nestedKey])];
|
|
}
|
|
} else if ([value isKindOfClass:[NSArray class]]) {
|
|
for (id nestedValue in value)
|
|
[parts addObjectsFromArray:DoQueryMagic([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
|
} else if ([value isKindOfClass:[NSSet class]]) {
|
|
for (id obj in [value sortedArrayUsingDescriptors:@[sortDescriptor]])
|
|
[parts addObjectsFromArray:DoQueryMagic(key, obj)];
|
|
} else {
|
|
[parts addObjectsFromArray:[NSArray arrayWithObjects:key, value, nil]];
|
|
}
|
|
|
|
return parts;
|
|
|
|
#undef sortDescriptor
|
|
}
|
|
|
|
NSString *ARTFormEncode(NSDictionary *parameters) {
|
|
if (parameters.count == 0)
|
|
return @"";
|
|
NSMutableString *queryString = [NSMutableString new];
|
|
NSEnumerator *e = DoQueryMagic(nil, parameters).objectEnumerator;
|
|
for (;;) {
|
|
id const obj = e.nextObject;
|
|
if (!obj) break;
|
|
[queryString appendFormat:@"%@=%@&", enckey(obj), encval(e.nextObject)];
|
|
}
|
|
[queryString deleteCharactersInRange:NSMakeRange(queryString.length - 1, 1)];
|
|
return queryString;
|
|
}
|