/*  *********************************************************************
    *  ASTRIS - Remote JTAG probe
    *
    *  Core Foundation object handling     File: astris_CF.h
    *
    *********************************************************************
    *
    *  Copyright (C) 2015-2019  Apple Inc. All rights reserved.
    *
    *  This document is the property of Apple Inc.
    *  It is considered confidential and proprietary.
    *
    *  This document may not be reproduced or transmitted in any form,
    *  in whole or in part, without the express written permission of
    *  Apple Inc.
    ********************************************************************* */

#ifndef astris_CF_h
#define astris_CF_h

#include <CoreFoundation/CoreFoundation.h>

#define K_CFCONVERT_UINT64_ERROR 0xFFFFFFFFFFFFFFFF

#ifdef __cplusplus

/**
@function astris_cfnum_get_int
@abstract Cast a @c CFNumber to an integer of the correct width
@param number The object to be cast
@param value A pointer to the result
@return @c true if the conversion was successful (i.e., exact), otherwise @c false
*/
template <typename T> bool astris_cfnum_get_int(CFNumberRef number, T *value);

/**
@function astris_cfdict_get_int
@abstract Look up an integer value from a @c CFDictionary
@param dict The dictionary to be queried
@param key The key to be looked up
@param value A pointer to the result
@return @c true if an integer value was found for the specified key, otherwise @c false
*/
template <typename T> bool astris_cfdict_get_int(CFDictionaryRef dict, CFTypeRef key, T *value);

#endif // __cplusplus

__BEGIN_DECLS

/**
@function astris_cfdict_create_from_plist_resource
@abstract Load a plist from the bundle's Resources directory
@param bundle The bundle to read from
@param resourceName The name of the property list (without the '.plist' extension)
@return The contents of the property list as a @c CFDictionary, or @c NULL on failure
 */
CFDictionaryRef astris_cfdict_create_from_plist_resource(CFBundleRef bundle, CFStringRef resourceName);

/**
@function astris_cfdict_get_cfdict
@abstract Look up a sub-dictionary from a nested @c CFDictionary
@param dict The dictionary to be queried
@param key The key to be looked up
@param value A pointer to the result
@return @c true if an integer value was found for the specified key, otherwise @c false
*/
bool astris_cfdict_get_cfdict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef *value);

/**
@function astris_create_cstr_from_cfstr
@abstract Copy a @c CFString to a newly allocated C string
@param cf_str The string to be copied
@return A C string (UTF-8 encoded), or @c NULL if the conversion failed
@note Moved from astris_internal.h
*/
char *astris_create_cstr_from_cfstr(CFStringRef cf_str);

/**
@function astris_create_uint64_from_cfstr
@abstract Convert a @c CFString to an integer using @c strtoull()
@param cf_str The string to be converted
@param base The base for the conversion (e.g. 10 for decimal, 16 for hex)
@return The converted value, or @c K_CFCONVERT_UINT64_ERROR if the conversion failed
@note Moved from astris_internal.h
*/
uint64_t astris_create_uint64_from_cfstr(CFStringRef cf_str, int base);

/**
@function astris_create_cstr_from_cfdict
@abstract Create a C-string description of CFDictionary
@param dict Dict to create description from
@return A C string (UTF-8 encoded), or @c NULL if the conversion failed
@note Moved from astris_internal.h
*/
char *astris_create_cstr_from_cfdict(CFDictionaryRef dict);

bool astris_cfdict_get_cstr(CFDictionaryRef dict, CFStringRef key, char **value);

/*!
 * @function get_value_from_encoded_str
 * @abstract Parse special encoded value
 * @discussion encoded_str can have the following look:
 *             <string>CoolValue</string> OR
 *             <string>A0:CoolValue1;A1:CoolValue2;*:CoolValue3</string>
 *             Each rev:value pair is seperated by a semicolon, and there can
 *             be only one colon between rev and value
 * @param endcoded_str   encoded string contains value
 * @param key     key we are getting value for
 * @returns Either NULL if failed to parse value or there is no value for rev,
 *          or the value for rev. The caller owns the value returned and must
 *          free it.
 */
char *get_value_from_encoded_str(const char *endcoded_str, const char *key);

// return unsigned long value converted from string
uint64_t astris_cstr_to_uint64t(char *str, int base);

__END_DECLS

#endif /* astris_CF_h */
