WWDC2000 Session 124
Transcript
Kind: captions
Language: en
we're going to start by talking about CF
role in Mac OS 10 as a whole then we're
going to look at some of the concert
there and finally in this talk will be
introducing the basic CF type so when I
talk about core foundation this is the
big take-home point core foundation is
the lingua franca in Mac OS 10 well what
does that mean a lingua franca is a
medium of communication between people
of different different languages so what
are the different languages on Mac OS 10
carbon and coco coir foundation is a
substrate layer that lives beneath both
carbon and Coco so it provides the
common language by which those two
environments speak to one another as
such it bridges the basic types between
both stacks and provides those common
services that both stacks need to share
things like the pasteboard the event
model so just as an example here you see
the carbon types on the right and the
cocoa types on the left corefoundation
acts to convert to and fun to and from
the types on either side hopefully
you've seen this diagram by now this is
the basic architecture on Mac OS 10 I
want to point out the core services
layer that lives below the application
services the graphical services like
quartz and OpenGL and QuickTime but
above Darwin the operating system that
layer is where we live we provide the
common services needed by everything
above us that does not depend on
graphics so if you look inside the core
services layer you'll see a number of
the non graphical managers you're
familiar with things like the file
managers memory manager resource manager
and in with all of those is core
foundation in fact core foundation were
you to look inside the core services
code lies below almost all of those
there we go so what is CF it's a non
graphical substrate library available to
both carbon and cocoa in fact it's even
below classic it is written in
you're see because that is the common
language beneath all of those layers and
it's designed around some basic
object-oriented paradigm so CF provides
two basic things to the system the first
one is some basic types by which all of
the different substrates can speak so
that's things like strings arrays and
dictionaries and then we combine them
together in an abstraction that we call
property list the other thing it
provides is the non graphical services
that every application needs so that's
local ations the localization support
user preferences as I said also the
pasteboard and the run loop in this talk
we're going to focus on the basic data
types there's a follow-on to this talk
immediately after lunch in the same room
where we'll be talking about the second
half of that stack the not the app
services so where is CF available on Mac
OS 10 this core foundation is available
as its own library on eight and nine it
ships as part of carbon live now there's
a there are some pieces of core
foundations that are only available on
10 those centres around the mock
specific pieces which obviously do not
apply on eight and nine finally a subset
of core foundation is available inside
of Darwin so if you're interested you
can check out the Darwin source code and
see what we're doing right so I know
that it's a developer when I go and
approach a stack one of the first things
I I don't want to hear is by the way
this is this other large API I have to
learn so if you don't want to learn CF
relax you don't really have to you're
missing out but you don't have to carbon
and cocoa are both complete ap is on to
themselves you can write entirely to
those api's if you wish and core
foundation will silently help out
underneath the stats providing smooth
communication however this is what
you're going to miss if you yourself
need to need to write code that bridges
between carbon and cocoa applications
for instance if you're writing a
low-level library that several
several different applications are going
to use you should be using CF to convert
the types to and from
internationalization support is wired
into core foundation it's one of the
easiest places to get it from there's a
rich simple set of data types around
those internationalized strings inside
of core foundation that's what we're
going to focus on here today and there
is some new functionality which you can
only get by talking to the core
foundation stack so what is that new
functionality property lists is a big
one and that's the one we'll talk about
today there's also an an XML parser
inside of course foundation it's not the
only XML parser on the system but it's
the only one in C and it's nice and low
level for your use user preferences
there's a unified user preferences model
inside of course foundation it will save
you from having to invent your own
preferences file format and doing your
own work of reading and writing to file
finally and perhaps most importantly the
bundle and plug-in model that surrounds
the entire app packaging scheme on Mac
OS 10 is centered in core foundation so
if you want to pull apart the pieces of
that app packaging format you should be
talking to core foundation ok so now I'm
going to move on to talk about the basic
concepts and paradigms inside of core
foundation I'm going to spend a moment
on the general philosophy of the library
then I'm going to talk about how we
managed to get some object orientation
inside of what is a purely see light on
C library and finally I'm going to look
at the memory management scheme that we
use the general philosophy of core
foundation is to be lean and mean we are
just barely above the operating system
layer performance and efficiency is
perhaps our primary goal for that reason
we have exported a minimal API and tried
to make it as powerful and extensible as
possible so you will not find a lot of
convenience functions to do simple
operations you will find some complex
powerful functional API where you may
have to you may have to do some
configuration of the arguments going in
finally there is no safety net in course
foundation we follow the same philosophy
as the C language if you tell us to do
something we're going to do it no
questions asked so if you hand us a bad
pointer we're going to try and access it
to try and ease the road a little bit we
do provide a debug library and that
debug library is available so that as
you code you can run against it and it
will catch a number of common errors and
that way you can help you can start to
debug your program so object orientation
inside of course foundation focuses on
CF types and we try to make this as
available as possible in the maiming
inside of course foundation so each type
is going is opaque and represents a
pseudo class and each such type is going
to be named CF and then the class name
ref the related functions which are
acting as methods on the class will
always be prefixed with the name of the
class CS class name and then in action
describing what the function does
related constants also are prefixed with
the class name k CS class and then a
descriptor so for example if we look at
CF strings the type of CF string ref an
example of a function would be CF string
append and an example of the constant
would be KCF string encoding ascii
furthermore inside the functions the
first argument is always the type
instance what you would consider the
receiver if you were writing in a true
object-oriented language then there's
one important exception to that and
that's creators and we'll get to those
in a minute we use common verbs to have
common meanings throughout the
throughout the API so that CF array get
array add is going to work the same way
as CF dictionary add finally when we are
passing information back to you we will
always put those out parameters the ones
that are going to be passed by reference
at the very end
there are a small number of polymorphic
functions inside of CF this is the
entire list this these functions can be
used with any CF type regardless of
class so I equality and hashing so you
have to equal um c of hash that's what
allows us to add at add objects into
collections and retrieve them out of it
there's a little bit of interest
introspection CF get type ID will return
the type ID of the class CF copy
description will provide a string
description of the object this is for
debugging purposes only these are not
intended to show to the user in fact it
will frequently have the hex address of
the of the object embedded in them and
finally memory memory management we use
a reference counting memory management
scheme so CF retain gains a reference CF
release releases it CF def retain count
is intended for debugging purposes only
so you can track how the reference
counting goes through an object's
lifetime and then CF get allocator
allows you to discover how the object
was allocated so as I just said CF types
of reference counted retained to get to
take a reference release to release it
anytime you have a reference counting
screen you have this common problem of
who gets who has the reference when an
object is returned by a function here
are the rules very very simple if the
function you called includes the word
get you did not get a reference the
object you called retains the reference
so if you intend to keep that object
you'd better retain it yourself
functions that include the words copy or
create on the other hand give you a
reference and when you are done with
that object you must release it or else
you will have a leak there is something
important to keep in mind here we are
simply using copy and create as as a way
of telling you the developer whether or
not you've got a reference there may be
some optimizations going on
the back particularly in the case of
immutable objects so even though you've
received a reference copy may not
actually do any copy memory copying and
likewise create may not do any
allocation CF is simply being more
efficient and it shouldn't matter to you
allocators an alligator there is a type
for at CF allocator ref an alligator
encapsulate an allocation scheme it you
call an alligator to allocate memory to
release it to reallocate it and so on
and every create function so every
function that could create a CF object
takes an alligator as first argument and
uses that alligator to create the memory
necessary normally you're going to want
to pass KCF allocator to default which
asks CF to use whatever the current
default allocator is there's one we have
one that we installed by default if you
want to you can install your own to do
custom memory management that's all I'm
going to say on the basic structure of
CF or the basic concepts and now I'm
going to move on to talk about some of
the basic types inside of core
foundations we're going to start with CF
string because that's probably the most
basic of the types the one that you're
most likely to be using then we're going
to talk briefly about CF array and CF
dictionary which are two of our
collection types once we're done with
that we'll look at how collections and
mutability work together inside this
library and finally we're going to see
how all of that comes together to form
property list conceptually a CF string
is simply an array of Unicode characters
the goal in creating a CF type whereas I
show here we're trying to get strength
to a new level of abstraction we're
trying to solve the 8-bit ASCII problem
if we can do that then
internationalization becomes easy
because the basic type throughout the
entire system will support Unicode
characters
because we're at such a low level we've
worked hard to assure performance so
even though conceptually you're looking
at an array of Unicode characters it may
not internally be stored that way in
particular you're not always going to be
storing two bytes per character and as
we move forward CF strings are becoming
the way to communicate strings in all of
the public api's CF string maintains a
very rich functionality set there are a
number of different creation functions
depending on where you may have gotten
the your string data from whether it's
coming from a carbon stack or or cocoa
or you just read it out of a file
there's a lot of support for encoding
conversions from CF strings to whatever
encoding you need to use we will do
comparisons find searches there are some
more complex operations like exploding a
string into its component pieces or
combining the component pieces back
again and there's even some printf style
formatting and parsing available so
let's look at some of the API for
creation and access I give an example of
a couple of the basic creation methods
here CF create with characters allows
you to take an array of Unicode
characters and create a string out of it
pretty straightforward if on the other
hand you're coming from a Pascal string
for instance you would use the second
function CF string create with Pascal
strength there are several other similar
kinds of functions for the other types
CF string create with file system
representations you have screen create
from data where you provide an encoding
and so on for basic access you use the
next two functions CF string get length
return to the current length of the
string CF string get character at index
returns the character at the given index
if you want more efficient processing
you can get a bunch a range of
characters at once using CF string get
characters and if if you have a CF
string and find that you need a Pascal
string or some other type to communicate
with another API you can get it with CF
string get Pascal string
only the last line there shows you how
you create a constant CF string CF sir
all caps and then the string within
quotes will produce a constant CF string
for your youth mutating some CF strings
are mutable we'll talk more about that
in a bit if you have immutable strings
here are the basic functions you'll use
CF string append append appends another
string onto the bass string CF string
replaced replaces a range of characters
inside the current string with another
string CF string insert performs a
straight-up insertion and CF string trim
is added here is an example of more
complex functionality available CF
string trim will take a trim string and
compare it to the beginning and the end
of the given string and strip it off
however many times it may appear now I
said that CF strings are becoming the
way by which strings are communicated
throughout the api's so here's an
example of this if you look inside the
carbon toolbox and some old API you may
be familiar with set W title and get W
title which set and get the title of a
window after the introduction of core
foundation the API below it has been
introduced set window title with CF
string copy window title as CF string
which allows you to set the window title
in a richer Unicode ready manner
okay another basic type types inside of
CF is CF data see if data is simply a
way to get an object representation
around an array of bytes it's more
versatile than using a simple void store
avoid star or a struct pointer because
it's opaque and because it encapsulates
the notion of length and there are a
couple very basic accessors CF data get
length and CF data get byte pointer I'm
going to move on now to talk about
collections there are a number of
different collections inside of core
foundation and by a collection I simply
implement object which can hold other
pointers and most of the time you're
going to be holding other objects CF
array and dictionary are by far the most
common of the collections you would be
using and array as you would expect
holds an ordered list of values and a
dictionary holds out values as key value
pairs you give me the key i'll give you
the value there and there are a number
of left common collections also on the
system set bad bag bitch vector binary
heap tree are just a few of them there
are actually several others as well so
let's look at CF array a couple creation
method CFRA create creates an immutable
array you give me an array of values and
the number there and i'll create an
array around it CF array create mutable
creates a mutable array and you will
tell us the capacity and the callbacks
we'll talk about that in a moment once
you've got an array the basic API is the
F array get count to find out how many
objects are in the array and then CF
array get value at index which will give
you the value at the given index
mutation CFRA insert value at index is
is the most common mechanism CS
dictionary you'll notice the naming
between CF dictionary and CF array is
very consistent CF dictionary create
creates an immutable dictionary CF
dictionary create mutable creates a
mutable one CF dictionary getcount gives
you the number of key value pairs
currently stored in the dictionary get
value
you provide the key will give you the
value back associated with that key and
set value allows you to associate a
value with a given key so now that we've
looked at those basic api's let's talk
about collections in more general terms
all of our collections contain pointer
sized values as I said most of the time
you're going to be storing other objects
but not always so how do you configure
the behavior differently depending on
what's being stored well that's what the
callbacks are all about you pass the
callbacks one to create when the
collection is first created and the
callbacks tell the object what to do as
objects are being added and removed from
the collection collections can also be
created created either mutable or
immutable and we'll go into into both
callbacks and mutability and greater
detail okay so as I said callbacks
determine what the array or the
dictionary is going to do as values are
added or removed ninety percent of the
time you're going to be storing other CF
objects inside of the collection when
that happens use the default callbacks
we provide so for example KCF type array
callbacks is the set of callbacks you
use for an array that's going to store
CF types as you would expect as objects
are added to an array this set of
callbacks will retain the objects on the
way in release them on the way out of
the remaining ten percent of the time
nine percent of that is going to your
collections are probably going to hold
pointers that you just want to manage
yourself you would rather the collection
does not do any management for you when
that's the case simply pass null at that
point CFR ACF dictionary all the
collections will simply take their hands
off you give them you give it a pointer
value it will hold the pointer value but
it won't do anything with it once in a
blue moon you will be trying you will be
using CF array or CF dictionary to store
a special data structure that has its
own memory management scheme this is the
point at which you're going to be
writing your own call back
you will have to add functions that
define how the object is retained on the
way into the collection how it should be
released on the way out and then you
will pass those callbacks to CF array or
whatever collection you're using moving
on to the mutability there are three
kinds of mutability in the system an
immutable object as you would expect you
can change neither the content nor the
size once the object has been created
the data is going to remain constant
until the object is destroyed a fixed
size collection you can change the
contents all you want as long as you do
not exceed the given capacity and a
fully mutable collection you can change
the content and the size not all of the
collections support all of the kinds of
mutability both array and dictionary do
when you're in doubt check the
documentation the documentation clearly
marked what kinds of mutability are
supported by which collections and also
I wanted to mention here although CF
string and CF data are not themselves
collections of other objects
conceptually a string of the collection
of characters and data is cool is a
collection of bytes and therefore we use
these mutability principles for both CF
string and CF data as well and they also
support all three types of mutability so
the way it works is this when you call
CF string creates the CF array create
whatever you're going to get back a
fully immutable object when you call CF
array create mutable you will get back a
mutable object if the specified capacity
is greater than 0 that will be taken as
the maximum capacity for your collection
so CFRA create create mutable with a
capacity of 10 produces an array that
can never hold more than 10 objects on
the other hand if you pass a capacity of
0 we will create a fully mutable object
for you and the array or string or
dictionary will automatically grow as
new objects are added in so for example
CF array create
it's going to produce an immutable array
you just provide the the objects that
are going in and the number of them and
there you go CS dictionary create
mutable passing a capacity of 10 creates
a mutable dictionary that can never
contain more than 10 key value pairs CF
string create mutable passing a capacity
of 0 produces a fully fully mutable
string of unlimited length and as
strings and characters are added to the
to this string it will grow to
accommodate them so how does this all
come together well given these basic
pieces of strings datas arrays and
dictionaries you can actually build up
some very complex trees of objects you
can also we also support several other
types but string data array and
dictionary form the core of them there
are a couple restrictions first of all
it has to be a true tree no loop so
arrays can't include themselves
dictionaries can't include or it can't
include themselves secondly the keys of
the dictionaries must always be strings
and we create an abstraction on top of
such a structure and call it a CF
property list ref so why are property
lists useful they're useful because we
make them persistent they have a simple
flattened XML representation and you can
easily convert to and from that
flattened XML representation expresses
the data and the rich tree structure now
we do not handle the file access part of
this as a rule core foundation does not
touch the file system so it's up to you
to read and write the data to and from
whatever file you're taking it from so
why are the properties why does this
make property list useful it's useful
because property lists are very easy to
program they're small they're very very
flexible you know just if you need a new
if you need to represent new data just
hack another object onto the end of the
array or create a new string and
as I said they're persistent the API for
persistency is very straightforward so
if you ever find yourself needing a
small flexible data format of some time
try out CF property list see if it'll
manage your needs the one caveat here is
property lists are not useful as a
general database it does not scale well
and that's because XML is a serialized
data representation so there's no
ability to scan into the middle and
locate an object out of the middle so
for example if you look in Mac OS 10
where we use property lists ourselves
you'll find them in small configuration
files all over the place we use them to
configure applications and provide much
of the information that find your needs
for instance when viewing an app package
plugins use configuration files to
announce their API as well as announcing
how they fulfill the API there are a
number of small system eunuch see kind
of parameter configuration files that
are that have been migrated to property
lists we also use them for the user
preferences on the system user
preferences the classic example of where
we don't know what information what
information a given application needs to
store but we do know that it's likely to
be small and we do know that our types
are likely to accommodate them the
pasteboards property list provides a
good flexible medium for communication
on the pasteboard we use it there as
well and this last point is one of my
favorites so you need to deliver an
application yesterday you might well
prototype using property lists as your
datastore that will at least save you
the burden of figuring out how you're
going to what your final data format is
and we found it remarkably flexible for
doing quick prototyping in fact the the
original HTML rendering engine in the
cocoa framework used properly lists
entirely for its backing store so I
mentioned there were some other property
list types these are very simple object
wrappers that you would rarely use
except that you need to store a
particular kind of
value in a property list the three most
common are listed here CF date wraps
asst wraps a date or time CF number and
CF boolean wrap simple numeric values
and again we're not suggesting that you
use this in place of a raw integer or a
raw boolean rather when you find you
need to store such a value in a property
list these rappers are available to do
that ok debugging and getting help I
mentioned earlier that there is a debug
library available inside of course
foundation what the debug library adds
is a number of extra assertions argument
checking that kind of thing and what
happens is as soon as one of those
assertions finds an invalid argument
it's going to log an error and abort
your program that's going to make it
much easier to isolate the problem find
the change get a good back trace and we
found that many of the most common
programming errors in we see with core
foundation can be caught this way so
please run against the debug library as
you develop core foundation code I've
also put a list here of the most common
errors in programming with core
foundation passing null is CF type
there's a classic one null is not a CF
type it is not a valid argument to any
of them any of the pseudo methods inside
of core foundation another common error
is releasing the return value of a get
function you call CF array get value you
never got a reference to the word the
function includes the word get but you
release it anyway well sooner or later
that array is going to be destroyed or
someone else is going to remove that
value from the array at that point the
array will release the object itself
boom memory Smasher the other half of
that equation is failing to retain the
value that came back from a get function
so once again you get a value out of CF
array using CFRA get value you intend to
keep that value pass the lifetime of the
array you need to retain it
if you do not when the array disappears
so does your object okay so there you
are in a debugging session you've got a
CF type you don't know what it is and
you're trying to figure out what's gone
wrong you see us get type ID to
determine the class of the object you've
got you can compare that with CF
typename get type ID so see a string get
type ID returns the type ID for all
strings yes array get type ID returns
the type ID for all arrays CF show will
print out any CF object to the console
or wherever standard out happens to be
in gdb you can invoke CF show directly
from within a break point very useful
for looking at what exactly has gotten
into your string if you would rather get
that that information into memory UCF
copy description it will give you
exactly the same output but stored in a
CF string so you can if you want right
it's a file look at it later whatever
tracking memory problems that occur in
the system CF get retain counts will
always return the current reference
count of an object you can use that to
make sure that the reference count is
incrementing or decrementing as you
expect you can install a custom default
allocator and use that to locate leaks
and memory corruption and finally if you
look on a vp for system there's an
application in system developer
applications called object Alec you can
view you can run your program under
object Alec and it will show you some of
the CF types as they are allocated and
destroyed all of the common ones are
there if you have string or a dictionary
all that kind of stuff finally there's a
fair bit of documentation online you can
find it in system developer
documentation core foundation on the dt
for CD it's also available on the web at
developer.apple.com tech pubs core
foundation there is some example code
inside of system developer examples core
foundation and the release notes are
available in system developer
documentation release notes
corefoundation HTML
you