Find the t_dictionary for a given name, and return a copy of that dictionary When you are done, do not call dictobj_release() on the dictionary, because you are working on a copy rather than on a retained pointer.

Given a complex key (one that includes potential heirarchy or array-member access), return the actual key and the dictionary in which the key should be referenced.

Detailed Description

The Dictionary Passing API defines a means by which t_dictionary instances may be passed between Max objects in a way similar to the way Jitter Matrices are passed between objects.

There are important differences, however, between Jitter matrix passing and dictionary passing. Many of these differences are documented in Max's documentation on dictionaries and structured data.

Every dictionary instance in this system is mapped to a unique name that identifies the dictionary. Dictionaries are passed between objects using the "dictionary" message with a single argument, which is the name of the dictionary.

Registration and Access

The C-API for working with these dictionaries is composed of 5 primary registration/access methods:

It is useful to think of objects in the dictionary system as "nouns" and "verbs".

A "noun" is an object that possess or owns a dictionary. These objects are servers whose dictionary will accessed by other object that are clients. An example of a "noun" is the dict.pack object that creates a dictionary that is passed to other objects.

A "verb" is an object that does not maintain its own dictionary (it is not a thing) but merely does something to any dictionaries it receives. This object is a client rather than a server. An example of a "verb" is the dict.strip object, which removes entries from an existing dictionary but possesses no dictionary of its own.

Any object which is a dictionary "noun", can keep and rely on their dictionary pointer. Because of the way object_register() works, there should be no possiblity for this pointer to change behind the scenes. They each need to call object_free() on their respective object pointer, however. A call to object_free() also calls object_unregister() once, so there's technically not a need to unregister from the owner itself. They work like jit.matrix (and similar to buffer~), and use object_register() to increment a server reference count. If an object has already registered an object with the given name, the pointer passed in to register is freed and the existing one is returned from the registration function.

Dictionary "verbs" on the other hand should just call dict_findregistered_retain() and dict_release() when done. They are not incrementing the server reference count. They increment a reference count with regards to object freeing, which is compatible with and complementary to the server reference count.

Dictionary Syntax

Dictionaries may be represented in a variety of textual formats including JSON. Max also supports a compact YAML-like dictionary notation which is useful for proving data structure contents as lists of atoms in object boxes. This format is documented in Max's documentation of the dictionary features. The following functions are used for formatting and parsing the dictionary syntax.

Utilities

The dictobj_validate() object is a utility routine for validating a dictionary against "schema" dictionary. This enables a behavior somewhat analogous to Objective-C or Smalltalk prototypes. Dictionary validation can be useful to implement a kind of dictionary polymorphism. For a multiple-inheritance behavior, simply validate a dictionary against multiple schemas to verify the presence of required keys and values.

Registration and Access

The dict_outlet_atoms() function will not output A_OBJ atoms directly (nor should any other object) and as such it will also not output t_atomarray instances containing objects, thus atomarrays are not hierarchical in the dictionary passing implementation.

It will output an atom array if provided a single A_OBJ atom with class atomarray. If there is an array of atoms which contain A_OBJ atoms, they are converted to the *symbols* <dictionary-object>, <atomarray-object>, <string-object>, <other-object> respectively. Ideally such a case should never be reached if everything which inserts values into a dictionary is well behaved--i.e.

Find the t_dictionary for a given name, and return a copy of that dictionary When you are done, do not call dictobj_release() on the dictionary, because you are working on a copy rather than on a retained pointer.

Parameters:

name

The name associated with the dictionary for which you wish to obtain a copy.

Returns:

The dictionary cloned from the existing dictionary. Returns NULL if no dictionary is associated with name.

The schema dictionary contains keys and values, like any dictionary. dictobj_validate() checks to make sure that all keys in the schema dictionary are present in the candidate dictionary. If the keys are all present then the candidate passes and the function returns true. Otherwise the the candidate fails the validation and the function returns false.

Generally speaking, the schema dictionary with contain values with the symbol "*", indicating a wildcard, and thus only the key is used to validate the dictionary (all values match the wildcard). However, if the schema dictionary contains non-wildcard values for any of its keys, those keys in the candidate dictionary must also contain matching values in order for the candidate to successfully validate.

An example of this in action is the dict.route object in Max, which simply wraps this function.

Parameters:

schema

The dictionary against which to validate candidate.

candidate

A dictionary to test against the schema.

Returns:

Returns true if the candidate validates against the schema, otherwise returns false.