Subject: Re: XML config file
To: Jason Thorpe <thorpej@shagadelic.org>
From: Jason Thorpe <thorpej@shagadelic.org>
List: tech-userlevel
Date: 07/24/2006 11:07:34
On Jul 23, 2006, at 2:03 PM, Jason Thorpe wrote:

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

Ok, I fleshed it out a bit more.

typedef enum {
         PROP_INGEST_ERROR_NO_ERROR              = 0,
         PROP_INGEST_ERROR_NO_KEY                = 1,
         PROP_INGEST_ERROR_WRONG_TYPE            = 2,
         PROP_INGEST_ERROR_HANDLER_FAILED        = 3
} prop_ingest_error_t;

typedef struct _prop_ingest_context *prop_ingest_context_t;

typedef boolean_t (*prop_ingest_handler_t)(prop_ingest_context_t,
					   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 }

prop_ingest_context_t
                 prop_ingest_context_alloc(void *);
void            prop_ingest_context_free(prop_ingest_context_t);

prop_ingest_error_t
                 prop_ingest_context_error(prop_ingest_context_t);
prop_type_t     prop_ingest_context_type(prop_ingest_context_t);
const char *    prop_ingest_context_key(prop_ingest_context_t);
void *          prop_ingest_context_private(prop_ingest_context_t);

boolean_t       prop_dictionary_ingest(prop_dictionary_t,
                                        prop_ingest_table_entry[],  
void *);


  ...

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(prop_ingest_context_t ctx,
			    prop_object_t obj)
{
	struct bsd44_ingest_context *bsd44ctx =
	    prop_ingest_context_private(ctx);
	struct disklabel *lp = bsd44ctx->label;
	uint64_t val;

	val = prop_number_integer_value(obj);
	if (val > 0xffffffff) {
		bsd44ctx->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 bsd44ctx;
	prop_ingest_context_t ctx;

	...

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

	bsd44ctx.lp = lp;
	bsd44ctx.errorstr = NULL;

	ctx = prop_ingest_context_alloc(&bsd44ctx);
	if (ctx == NULL) {
		/* return an error */
	}

	if (prop_dictionary_ingest(geom_dict,
				   bsd44_geom_ingest_table,
				   ctx) == FALSE) {
		/* report error */
		switch (prop_ingest_context_error(ctx)) {
		case PROP_INGEST_ERROR_NO_KEY:
			/* prop_ingest_context_key(ctx)
			   returns the key that was missing. */
			break;

		case PROP_INGEST_ERROR_WRONG_TYPE:
			/* prop_ingest_context_key(ctx)
			   returns the key that failed and
			   prop_ingest_context_type(ctx)
			   returns the ACTUAL type of that
			   key's object. */
			break;

		case PROP_INGEST_ERROR_HANDLER_FAILED:
			/* Our handler filled in
			   bsd44ctx.errorstr */
			break;

		default:
			/* can't happen */
			break;
		}
	}


-- thorpej