git @ Cat's Eye Technologies Kosheri / master src / save.c
master

Tree @master (Download .tar.gz)

save.c @masterraw · history · blame

/*
 * save.c
 * Save values to a stream-like process.
 */

#include "lib.h"
#include "stream.h"

#include "save.h"
#include "value.h"

#ifdef DEBUG
#include "cmdline.h"
#include "portray.h"
#include "render.h"
#endif

int
value_save(struct process *p, struct value *value)
{
	unsigned char squeeze = (unsigned char)value->type;

#ifdef DEBUG
	process_render(process_err, "(save:%s ", type_name_table[(int)squeeze]);
        if (value->type == VALUE_SYMBOL) {
            process_render(process_err, "[%d] ", value_symbol_get_length(value));
        }
	value_portray(process_err, value);
	process_render(process_err, ")\n");
#endif

	stream_write(NULL, p, &squeeze, sizeof(squeeze));

	if ((value->type & VALUE_STRUCTURED) == 0) {
		stream_write(NULL, p, &value->value, sizeof(value->value));
	} else {
		unsigned int length, i;

		switch (value->type) {
		case VALUE_SYMBOL:
		    {
			const char *token = value_symbol_get_token(value);
			length = value_symbol_get_length(value);
			stream_write(NULL, p, &length, sizeof(length));
			stream_write(NULL, p, token, sizeof(char) * length);
			break;
		    }
		case VALUE_TUPLE:
		    {
                        struct value *tag = value_tuple_get_tag(value);
			value_save(p, tag);
                        /* XXX should eventually dispatch to a handler based on tag. */
                        if (value_equal(tag, &tag_dict)) {
                          	struct value dict_iter;
                                struct value *key;

                                value_dict_new_iter(&dict_iter, value);

                                length = value_dict_get_layer_size(value);
                                stream_write(NULL, p, &length, sizeof(length));
                                length = value_dict_get_length(value);
                                stream_write(NULL, p, &length, sizeof(length));
                          
                                key = value_dict_iter_get_current_key(&dict_iter);
                                while (!value_is_null(key)) {
                                        value_save(p, key);
                                        value_save(p, value_dict_fetch(value, key)); /* XXX not so good; use iter */
                                        value_dict_iter_advance(&dict_iter);
                                        key = value_dict_iter_get_current_key(&dict_iter);
                                }
                        } else {
                                length = value_tuple_get_size(value);
                                stream_write(NULL, p, &length, sizeof(length));
                                for (i = 0; i < length; i++) {
                                        value_save(p, value_tuple_fetch(value, i));
                                }
                        }
			break;
		    }
		default:
			assert(value->type == VALUE_SYMBOL ||
			       value->type == VALUE_TUPLE);
			break;
		}
	}

	return 1;
}