/*
 * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
 *
 * @APPLE_APACHE_LICENSE_HEADER_START@
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @APPLE_APACHE_LICENSE_HEADER_END@
 */

#include "internal.h"

#if DISPATCH_DATA_IS_BRIDGED_TO_NSDATA

#if _OS_OBJECT_OBJC_ARC
#error "Cannot build with ARC"
#endif

#include <Foundation/NSString.h>

@interface DISPATCH_CLASS(data) () <DISPATCH_CLASS(data)>
@property (readonly,nonatomic) NSUInteger length;
@property (readonly,nonatomic) const void *bytes NS_RETURNS_INNER_POINTER;

- (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
		freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm;
- (BOOL)_bytesAreVM;
- (BOOL)_isCompact;
@end

@interface DISPATCH_CLASS(data_empty) : DISPATCH_CLASS(data)
@end

@implementation DISPATCH_CLASS(data)

+ (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
	return _dispatch_objc_alloc(self, sizeof(struct dispatch_data_s));
}

- (id)init {
    return [self initWithBytes:NULL length:0 copy:NO freeWhenDone:NO
			bytesAreVM:NO];
}

- (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
		freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm {
	dispatch_block_t destructor;
	if (copy) {
		destructor = DISPATCH_DATA_DESTRUCTOR_DEFAULT;
	} else if (freeBytes) {
		if (vm) {
			destructor = DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
		} else {
			destructor = DISPATCH_DATA_DESTRUCTOR_FREE;
		}
	} else {
		destructor = DISPATCH_DATA_DESTRUCTOR_NONE;
	}
	dispatch_data_init(self, bytes, length, destructor);
	return self;
}

#define _dispatch_data_objc_dispose(selector) \
	struct dispatch_data_s *dd = (void*)self; \
	_dispatch_data_dispose(self); \
	dispatch_queue_t tq = dd->do_targetq; \
	dispatch_function_t func = dd->finalizer; \
	void *ctxt = dd->ctxt; \
	[super selector]; \
	if (func && ctxt) { \
		if (!tq) { \
			 tq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);\
		} \
		dispatch_async_f(tq, ctxt, func); \
	} \
	if (tq) { \
		_os_object_release_internal((_os_object_t)tq); \
	}

- (void)dealloc {
	_dispatch_data_objc_dispose(dealloc);
}

- (BOOL)_bytesAreVM {
	struct dispatch_data_s *dd = (void*)self;
	return dd->destructor == DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
}

- (void)_setContext:(void*)context {
	struct dispatch_data_s *dd = (void*)self;
	dd->ctxt = context;
}

- (void*)_getContext {
	struct dispatch_data_s *dd = (void*)self;
	return dd->ctxt;
}

- (void)_setFinalizer:(dispatch_function_t)finalizer {
	struct dispatch_data_s *dd = (void*)self;
	dd->finalizer = finalizer;
}

- (void)_setTargetQueue:(dispatch_queue_t)queue {
	struct dispatch_data_s *dd = (void*)self;
	_os_object_retain_internal((_os_object_t)queue);
	dispatch_queue_t prev;
	prev = os_atomic_xchg2o(dd, do_targetq, queue, release);
	if (prev) _os_object_release_internal((_os_object_t)prev);
}

- (NSString *)debugDescription {
	Class nsstring = objc_lookUpClass("NSString");
	if (!nsstring) return nil;
	char buf[2048];
	_dispatch_data_debug(self, buf, sizeof(buf));
	NSString *format = [nsstring stringWithUTF8String:"<%s: %s>"];
	if (!format) return nil;
	return [nsstring stringWithFormat:format, class_getName([self class]), buf];
}

- (NSUInteger)length {
	struct dispatch_data_s *dd = (void*)self;
	return dd->size;
}

- (const void *)bytes {
	struct dispatch_data_s *dd = (void*)self;
	return _dispatch_data_get_flattened_bytes(dd);
}

- (BOOL)_isCompact {
	struct dispatch_data_s *dd = (void*)self;
	return !dd->size || _dispatch_data_map_direct(dd, 0, NULL, NULL) != NULL;
}

- (void)_suspend {
}

- (void)_resume {
}

- (void)_activate {
}

@end

@implementation DISPATCH_CLASS(data_empty)

// Force non-lazy class realization rdar://10640168
+ (void)load {
}

- (id)retain {
	return (id)self;
}

- (oneway void)release {
}

- (id)autorelease {
	return (id)self;
}

- (NSUInteger)retainCount {
	return ULONG_MAX;
}

+ (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
	return (id)&_dispatch_data_empty;
}

- (void)_setContext:(void*) DISPATCH_UNUSED context {
}

- (void*)_getContext {
	return NULL;
}

- (void)_setFinalizer:(dispatch_function_t) DISPATCH_UNUSED finalizer {
}

- (void)_setTargetQueue:(dispatch_queue_t) DISPATCH_UNUSED queue {
}

- (void)_suspend {
}

- (void)_resume {
}

- (void)_activate {
}

@end

#endif // USE_OBJC
