Subject: Re: XML config file
To: Iain Hibbert <plunky@rya-online.net>
From: Jason Thorpe <thorpej@shagadelic.org>
List: tech-userlevel
Date: 07/23/2006 14:03:47
[ Resending, because the message got chopped off prematurely by the  
MTA... ]

On Jul 22, 2006, at 1:36 PM, Iain Hibbert wrote:

> struct prop_hint {
> 	const char *name;
> 	prop_type_t type;
> 	void       *arg;
> };
>
> struct prop_hint service_hints[] = {
> 	{ "smtp",	PROP_TYPE_DICTIONARY,	NULL	},
> 	{ "nntp",	PROP_TYPE_DICTIONARY,	NULL	},
> };
>
> struct prop_hint hints[] = {
> 	{ "name",	PROP_TYPE_STRING,	NULL	},
>         { "address",	PROP_TYPE_STRING,	ip4	},
> 	{ "services",	PROP_TYPE_DICTIONARY,	service_hints },
> };
>
> prop_object_t
> ip4(prop_string_t str)
> {
> 	/* we transform the string object to our preferred form */
> 	return obj or NULL;
> }
>
> 	dict = prop_dictionary_internalize(xml, hints);
>
> and if anything is not mentioned in the hints, it is just passed  
> through
> as normal. Does anything like this exist in the OSXAPI?

No, the OS X property list API doesn't have anything like this.  But  
that's not too surprising, considering how the OS X APIs (esp. the  
Foundation APIs) are designed to be used.

I like you suggestion, and I have been considering something like it  
since the beginning of proplib, but I do not want it to be part of  
the internalize step.

I have been thinking of a "property list ingest" helper that could  
"parse" the internalized form (i.e. a prop_dictionary_t, NOT the  
XML).  The reason for this is that you might want to be able to pass  
a dictionary to some application plugin or shared library and give it  
the opportunity to gobble it up into its own format.

The stuff I've been playing around with looks a bit like this:

typedef boolean_t (*prop_ingest_handler_t)(void *, prop_object_t);

typedef struct {
	const char *pite_key;
	prop_type_t pite_type;
	prop_ingest_handler_t pite_handler;
} prop_ingest_table_entry;

#define	PROP_INGEST(key_, type_, handler_) \
	{ .pite_key = key_, .pite_type = type_, \
	  .pite_handler = handler_ }

#define	PROP_INGEST_END { .pite_key = NULL }

   .
   .
   .

static prop_ingest_table_entry bsd44_geom_ingest_table[] = {
	.
	.
	.
	PROP_INGEST("sectors-per-unit", PROP_TYPE_NUMBER,
		    bsd44_geom_sectors_per_unit),
	.
	.
	.
	PROP_INGEST_END
};

static boolean_t
bsd44_geom_sectors_per_unit(void *v, prop_object_t obj)
{
	struct bsd44_ingest_context *ctx = v;
	struct disklabel *lp = ctx->label;
	uint64_t val;

	val = prop_number_integer_value(obj);
	if (val > 0xffffffff) {
		ctx->errorstr =
		    "sectors-per-unit exceeds maximum allowed value";
		return (FALSE);
	}

	lp->d_secperunit = (uint32_t)(val & 0xffffffff);

	return (TRUE);
}

   .
   .
   .

{
	.
	.
	.
	struct disklabel *lp;
	bsd44_ingest_context ctx;
	.
	.
	.


	geom_dict = prop_dictionary_get(props, "disk-geometry");
	if (prop_object_type(geom_dict) != PROP_TYPE_DICTIONARY) {
		/* return an error */
	}

	ctx.label = lp;
	ctx.errorstr = NULL;

	if (prop_dictionary_ingest(geom_dict,
				   bsd44_geom_ingest_table,
				   &ctx) == FALSE) {
		/* return the error string */
	}

	.
	.
	.


(I've been toying around with this in partition map manipulation  
library... in my new world order, a partition maps and other disk  
information are dictionaries and arrays of dictionaries.)

-- thorpej