Use case insensitive dictionary for headers

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25159 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2007-05-15 10:06:42 +00:00
parent 9740458609
commit 96e36de9e8
2 changed files with 20 additions and 113 deletions

View file

@ -4,6 +4,7 @@
* Source/NSURLProtocol.m: Perform automatic redirect from
http://host to http://host/ to standardise URL used for caching as
noted in Apple documentation.
* Source/NSURLRequest.m: use case insensitive dictionary for headers.
2007-05-14 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -23,10 +23,9 @@
*/
#include "GSURLPrivate.h"
#include "GSPrivate.h"
#include "Foundation/NSMapTable.h"
#include "Foundation/NSCoder.h"
#include "NSCallBacks.h"
// Internal data storage
@ -34,7 +33,7 @@ typedef struct {
NSData *body;
NSInputStream *bodyStream;
NSString *method;
NSMapTable *headers;
NSMutableDictionary *headers;
BOOL shouldHandleCookies;
NSURL *URL;
NSURL *mainDocumentURL;
@ -112,14 +111,7 @@ typedef struct {
ASSIGN(inst->bodyStream, this->bodyStream);
ASSIGN(inst->method, this->method);
inst->shouldHandleCookies = this->shouldHandleCookies;
if (this->headers == 0)
{
inst->headers = 0;
}
else
{
inst->headers = NSCopyMapTableWithZone(this->headers, z);
}
inst->headers = [this->headers mutableCopy];
}
}
return o;
@ -135,10 +127,7 @@ typedef struct {
RELEASE(this->URL);
RELEASE(this->mainDocumentURL);
RELEASE(this->properties);
if (this->headers != 0)
{
NSFreeMapTable(this->headers);
}
RELEASE(this->headers);
NSZoneFree([self zone], this);
}
[super dealloc];
@ -241,32 +230,10 @@ typedef struct {
{
return NO;
}
if (this->headers != inst->headers)
if (this->headers != inst->headers
&& [this->headers isEqual: inst->headers] == NO)
{
NSMapEnumerator enumerator;
id k;
id v;
if (this->headers == 0 || inst->headers == 0)
{
return NO;
}
if (NSCountMapTable(this->headers) != NSCountMapTable(inst->headers))
{
return NO;
}
enumerator = NSEnumerateMapTable(this->headers);
while (NSNextMapEnumeratorPair(&enumerator, (void **)(&k), (void**)&v))
{
id ov = (id)NSMapGet(inst->headers, (void*)k);
if ([v isEqual: ov] == NO)
{
NSEndMapTableEnumeration(&enumerator);
return NO;
}
}
NSEndMapTableEnumeration(&enumerator);
return NO;
}
return YES;
}
@ -293,14 +260,7 @@ typedef struct {
ASSIGN(inst->bodyStream, this->bodyStream);
ASSIGN(inst->method, this->method);
inst->shouldHandleCookies = this->shouldHandleCookies;
if (this->headers == 0)
{
inst->headers = 0;
}
else
{
inst->headers = NSCopyMapTableWithZone(this->headers, z);
}
inst->headers = [this->headers mutableCopy];
}
return o;
}
@ -342,66 +302,19 @@ typedef struct {
@end
/*
* Implement map keys for strings with case insensitive comparisons,
* so we can have case insensitive matching of http headers (correct
* behavior), but actually preserve case of headers stored and written
* in case the remote server is buggy and requires particular
* captialisation of headers (some http software is faulty like that).
*/
static unsigned int
_non_retained_id_hash(void *table, NSString* o)
{
return [[o lowercaseString] hash];
}
static BOOL
_non_retained_id_is_equal(void *table, NSString *o, NSString *p)
{
if (o == nil || [o caseInsensitiveCompare: p] != NSOrderedSame)
{
return NO;
}
return YES;
}
typedef unsigned int (*NSMT_hash_func_t)(NSMapTable *, const void *);
typedef BOOL (*NSMT_is_equal_func_t)(NSMapTable *, const void *, const void *);
typedef void (*NSMT_retain_func_t)(NSMapTable *, const void *);
typedef void (*NSMT_release_func_t)(NSMapTable *, void *);
typedef NSString *(*NSMT_describe_func_t)(NSMapTable *, const void *);
static const NSMapTableKeyCallBacks headerKeyCallBacks =
{
(NSMT_hash_func_t) _non_retained_id_hash,
(NSMT_is_equal_func_t) _non_retained_id_is_equal,
(NSMT_retain_func_t) _NS_non_retained_id_retain,
(NSMT_release_func_t) _NS_non_retained_id_release,
(NSMT_describe_func_t) _NS_non_retained_id_describe,
NSNotAPointerMapKey
};
@implementation NSURLRequest (NSHTTPURLRequest)
- (NSDictionary *) allHTTPHeaderFields
{
NSMutableDictionary *fields;
NSDictionary *fields;
fields = [NSMutableDictionary dictionaryWithCapacity: 8];
if (this->headers != 0)
if (this->headers == nil)
{
NSMapEnumerator enumerator;
NSString *k;
NSString *v;
enumerator = NSEnumerateMapTable(this->headers);
while (NSNextMapEnumeratorPair(&enumerator, (void **)(&k), (void**)&v))
{
[fields setObject: v forKey: k];
}
NSEndMapTableEnumeration(&enumerator);
fields = [NSDictionary dictionary];
}
else
{
fields = [NSDictionary dictionaryWithDictionary: this->headers];
}
return fields;
}
@ -428,13 +341,7 @@ static const NSMapTableKeyCallBacks headerKeyCallBacks =
- (NSString *) valueForHTTPHeaderField: (NSString *)field
{
NSString *value = nil;
if (this->headers != 0)
{
value = (NSString*)NSMapGet(this->headers, (void*)field);
}
return value;
return [this->headers objectForKey: field];
}
@end
@ -502,12 +409,11 @@ static const NSMapTableKeyCallBacks headerKeyCallBacks =
- (void) setValue: (NSString *)value forHTTPHeaderField: (NSString *)field
{
if (this->headers == 0)
if (this->headers == nil)
{
this->headers = NSCreateMapTable(headerKeyCallBacks,
NSObjectMapValueCallBacks, 8);
this->headers = [_GSMutableInsensitiveDictionary new];
}
NSMapInsert(this->headers, (void*)field, (void*)value);
[this->headers setObject: value forKey: field];
}
@end