diff --git a/dictionary.rs b/dictionary.rs index 742f324..3baae2d 100644 --- a/dictionary.rs +++ b/dictionary.rs @@ -1,15 +1,26 @@ -use base::{AbstractCFType, AbstractCFTypeRef, CFAllocatorRef, CFIndex, CFRelease, CFTypeRef, kCFAllocatorDefault}; +use base::{ + AbstractCFType, + AbstractCFTypeRef, + Boolean, + CFAllocatorRef, + CFIndex, + CFRelease, + CFTypeID, + CFTypeRef, + kCFAllocatorDefault +}; use cast::reinterpret_cast; use dvec::DVec; use libc::c_void; use ptr::to_unsafe_ptr; use vec::raw::to_ptr; -pub type CFDictionaryRetainCallBack = *u8; -pub type CFDictionaryReleaseCallBack = *u8; +pub type CFDictionaryApplierFunction = *u8; pub type CFDictionaryCopyDescriptionCallBack = *u8; pub type CFDictionaryEqualCallBack = *u8; pub type CFDictionaryHashCallBack = *u8; +pub type CFDictionaryReleaseCallBack = *u8; +pub type CFDictionaryRetainCallBack = *u8; pub struct CFDictionaryKeyCallBacks { version: CFIndex, @@ -102,6 +113,61 @@ pub impl, + ValueType : AbstractCFType> + CFDictionary { + pure fn len() -> uint unsafe { + return CFDictionaryGetCount(self.obj) as uint; + } + + pure fn is_empty() -> bool { self.len() == 0 } + + pure fn contains_key(key: &KeyType) -> bool unsafe { + return CFDictionaryContainsKey(self.obj, cast::transmute(key.get_ref())) as bool; + } + + pure fn find(key: &KeyType) -> Option unsafe { + let value : *c_void = ptr::null(); + let did_find_value = CFDictionaryGetValueIfPresent(self.obj, + cast::transmute(key.get_ref()), + cast::transmute(&value)) as bool; + + // FIXME: this will not handle non-CF dictionary entries + // or ptr::null() values correctly. + return if did_find_value { + Some(base::wrap(cast::transmute::<*c_void, ValueRefType>(value))) + } else { + None + } + } + + pure fn get(key: &KeyType) -> ValueType { + let value = self.find(key); + if value.is_none() { + fail fmt!("No entry found for key: %?", key); + } + option::unwrap(move value) + } + + fn each(blk: fn&(&KeyType, &ValueType) -> bool) unsafe { + let len = self.len(); + let keys: ~[KeyRefType] = vec::from_elem(len, cast::transmute::<*c_void, KeyRefType>(ptr::null())); + let values: ~[ValueRefType] = vec::from_elem(len, cast::transmute::<*c_void, ValueRefType>(ptr::null())); + + do uint::range(0,len) |i| { + let key = base::wrap(keys[i]); + let value = base::wrap(values[i]); + blk(&key, &value) + } + } +} + #[link_args="-framework CoreFoundation"] #[nolink] @@ -113,9 +179,21 @@ extern { const kCFTypeDictionaryKeyCallBacks: CFDictionaryKeyCallBacks; const kCFTypeDictionaryValueCallBacks: CFDictionaryValueCallBacks; + fn CFDictionaryApplyFunction(theDict: CFDictionaryRef, applier: CFDictionaryApplierFunction, + context: *c_void); + fn CFDictionaryContainsKey(theDict: CFDictionaryRef, key: *c_void) -> Boolean; + fn CFDictionaryContainsValue(theDict: CFDictionaryRef, value: *c_void) -> Boolean; fn CFDictionaryCreate(allocator: CFAllocatorRef, keys: **c_void, values: **c_void, numValues: CFIndex, keyCallBacks: *CFDictionaryKeyCallBacks, valueCallBacks: *CFDictionaryValueCallBacks) -> CFDictionaryRef; + fn CFDictionaryCreateCopy(allocator: CFAllocatorRef, theDict: CFDictionaryRef) -> CFDictionaryRef; + fn CFDictionaryGetCount(theDict: CFDictionaryRef) -> CFIndex; + fn CFDictionaryGetCountOfKey(theDict: CFDictionaryRef, key: *c_void) -> CFIndex; + fn CFDictionaryGetCountOfValue(theDict: CFDictionaryRef, value: *c_void) -> CFIndex; + fn CFDictionaryGetKeysAndValues(theDict: CFDictionaryRef, keys: **c_void, values: **c_void); + fn CFDictionaryGetTypeID() -> CFTypeID; + fn CFDictionaryGetValue(theDict: CFDictionaryRef, key: *c_void) -> *c_void; + fn CFDictionaryGetValueIfPresent(theDict: CFDictionaryRef, key: *c_void, value: **c_void) -> Boolean; }