Beispiel #1
0
Generator* generator_new(int flags, void* cookie)/*{{{*/
{
  Generator* self = (Generator*)calloc(1, sizeof(Generator));

  if (self)
  {
    self->flags       = flags;
    self->cookie      = cookie;
    self->properties  = s_hash_table_new(id_hash, id_equal, 20);
    self->buffer      = strbuf_new(NULL);
    self->state       = STATE_IDLE;
  }

  return self;
}/*}}}*/
Beispiel #2
0
static void read_relation_items(SEbmlRead *ebmlReader, SRelation *rel,
								s_hash_table *items_content_table, s_erc *error)
{
	uint32 id;
	SItem *item = NULL;
	s_hash_table *relation_items = NULL;
	s_bool container_exhausted;


	S_CLR_ERR(error);

	/* read S_UTT_EBML_RELATION_ITEMS container */
	id = S_EBMLREAD_CALL(ebmlReader, container)(ebmlReader, error);
	if (S_CHK_ERR(error, S_CONTERR,
				  "read_relation_items",
				  "ebmlRead method \"container\" failed"))
		goto quit_error;

	/* 2^8 = 256 items */
	relation_items = s_hash_table_new(&relation_items_table_free_fp, 8, error);
	if (S_CHK_ERR(error, S_CONTERR,
				  "read_relation_items",
				  "Call to \"relation_items\" failed"))
		goto quit_error;

	while (1)
	{
		container_exhausted = S_EBMLREAD_CALL(ebmlReader, container_at_end)(ebmlReader, error);
		if (S_CHK_ERR(error, S_CONTERR,
					  "read_relation_items",
					  "ebmlRead method \"container_at_end\" failed"))
			goto quit_error;

		if (container_exhausted)
		{
			SItem *current;
			SItem *next;


			/* connect relation head and tail items
			 * find the first item.
			 */
			current = get_item(relation_items, 1, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"get_item\" failed"))
				goto quit_error;

			rel->head = current;

			/* find the last item*/
			while (current != NULL)
			{
				next = SItemNext(current, error);
				if (S_CHK_ERR(error, S_CONTERR,
							  "read_relation_items",
							  "Call to \"SItemNext\" failed"))
					goto quit_error;

				if (next == NULL)
				{
					rel->tail = current;
					break;
				}

				current = next;
			}

			s_hash_table_delete(relation_items, error);
			S_CHK_ERR(error, S_CONTERR,
					  "read_relation_items",
					  "Call to \"s_hash_table_delete\" failed");

			break;
		}

		/* peek id  */
		id = S_EBMLREAD_CALL(ebmlReader, peek_id)(ebmlReader, error);
		if (S_CHK_ERR(error, S_CONTERR,
					  "read_relation_items",
					  "ebmlRead method \"peek_id\" failed"))
			goto quit_error;

		switch(id)
		{
		case S_UTT_EBML_RELATION_ITEM_NODE:
		{
			uint32 item_node_number;


			item_node_number = S_EBMLREAD_CALL(ebmlReader, read_uint)(ebmlReader, &id, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "ebmlRead method \"read_uint\" failed"))
				goto quit_error;

			/* find the item. */
			item = get_item(relation_items, item_node_number, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"get_item\" failed"))
				goto quit_error;

			item->relation = rel;

			break;
		}
		case S_UTT_EBML_RELATION_ITEM_CONTENT_ID:
		{
			uint32 item_content_id;
			const s_hash_element *he;
			s_items_content_container *ic;


			item_content_id = S_EBMLREAD_CALL(ebmlReader, read_uint)(ebmlReader, &id, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "ebmlRead method \"read_uint\" failed"))
				goto quit_error;

			/* find the item content */
			he = s_hash_table_find(items_content_table, (void*)&item_content_id,
								   sizeof(uint32), error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"s_hash_table_find\" failed"))
				goto quit_error;

			if (he == NULL)
			{
				S_CTX_ERR(error, S_FAILURE,
						  "read_relation_items",
						  "Failed to find item content for read content id");
				goto quit_error;
			}

			ic = (s_items_content_container *)s_hash_element_get_data(he, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"s_hash_element_get_data\" failed"))
				goto quit_error;

			item->content = ic->content;
			ic->used = 1;

			/* add the item in item's content relations. This is for
			 * the SItemAs and SItemIn item functions.
			 */
			SItmContentAdd(item->content, rel->name, item, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"SItmContentAdd\" failed"))
				goto quit_error;

			break;
		}
		case S_UTT_EBML_RELATION_ITEM_UP_NODE:
		{
			uint32 item_node_number;
			SItem *itemParent;


			item_node_number = S_EBMLREAD_CALL(ebmlReader, read_uint)(ebmlReader, &id, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "ebmlRead method \"read_uint\" failed"))
				goto quit_error;

			/* find the item. */
			itemParent = get_item(relation_items, item_node_number, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"get_item\" failed"))
				goto quit_error;

			item->up = itemParent;
			break;
		}
		case S_UTT_EBML_RELATION_ITEM_DOWN_NODE:
		{
			uint32 item_node_number;
			SItem *itemDaughter;


			item_node_number = S_EBMLREAD_CALL(ebmlReader, read_uint)(ebmlReader, &id, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "ebmlRead method \"read_uint\" failed"))
				goto quit_error;

			/* find the item. */
			itemDaughter = get_item(relation_items, item_node_number, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"get_item\" failed"))
				goto quit_error;

			item->down = itemDaughter;
			break;
		}
		case S_UTT_EBML_RELATION_ITEM_NEXT_NODE:
		{
			uint32 item_node_number;
			SItem *itemNext;


			item_node_number = S_EBMLREAD_CALL(ebmlReader, read_uint)(ebmlReader, &id, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "ebmlRead method \"read_uint\" failed"))
				goto quit_error;

			/* find the item. */
			itemNext = get_item(relation_items, item_node_number, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"get_item\" failed"))
				goto quit_error;

			item->next = itemNext;
			break;
		}
		case S_UTT_EBML_RELATION_ITEM_PREV_NODE:
		{
			uint32 item_node_number;
			SItem *itemPrev;


			item_node_number = S_EBMLREAD_CALL(ebmlReader, read_uint)(ebmlReader, &id, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "ebmlRead method \"read_uint\" failed"))
				goto quit_error;

			/* find the item. */
			itemPrev = get_item(relation_items, item_node_number, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "Call to \"get_item\" failed"))
				goto quit_error;;

			item->prev = itemPrev;
			break;
		}
		default:
			/* unknown elements, skip */
			S_WARNING(S_FAILURE,
					  "read_relation_items",
					  "Skipping element with unknown id '0x%x'",
					  id);

			S_EBMLREAD_CALL(ebmlReader, element_skip)(ebmlReader, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_relation_items",
						  "ebmlRead method \"element_skip\" failed"))
				goto quit_error;
		}
	}

	/* here everything went OK */
	return;

	/* errors here, clean up code */
quit_error:

	/* disconnect items from relation */
	rel->head = NULL;
	rel->tail = NULL;

	/* delete them, can't use normal s_hash_table_delete
	 * because the delete function pointer
	 * (relation_items_table_free_fp) does not delete the items.
	 */
	if (relation_items != NULL)
	{
		s_hash_element *hte;
		s_hash_element *next;
		s_erc local_err = S_SUCCESS;

		hte = (s_hash_element *)s_hash_table_first(relation_items, &local_err);
		if (S_CHK_ERR(&local_err, S_CONTERR,
					  "read_relation_items",
					  "Call to \"s_hash_table_first\" failed"))
			return;

		while (hte != NULL)
		{
			SItem *item;
			uint32 *item_node_number;


			next = (s_hash_element *)s_hash_element_next(hte, &local_err);
			if (S_CHK_ERR(&local_err, S_CONTERR,
						  "read_relation_items",
						  "Call to \"s_hash_element_next\" failed"))
				next = NULL;

			item_node_number = (uint32 *)s_hash_element_key(hte, &local_err);
			if (!S_CHK_ERR(&local_err, S_CONTERR,
						   "read_relation_items",
						   "Call to \"s_hash_element_key\" failed"))
				S_FREE(item_node_number);

			item = (SItem *)s_hash_element_get_data(hte, &local_err);
			if (!S_CHK_ERR(&local_err, S_CONTERR,
						   "read_relation_items",
						   "Call to \"s_hash_element_get_data\" failed"))
				S_FORCE_DELETE(item, "read_relation_items", &local_err);

			s_hash_element_unlink(hte, &local_err);
			S_CHK_ERR(&local_err, S_CONTERR,
					  "read_relation_items",
					  "Call to \"s_hash_element_unlink\" failed");

			hte = next;
		}

		s_hash_table_delete(relation_items, &local_err);
		S_CHK_ERR(&local_err, S_CONTERR,
				  "read_relation_items",
				  "Call to \"s_hash_table_delete\" failed");
	}
}
Beispiel #3
0
static s_hash_table *read_item_contents(SEbmlRead *ebmlReader, s_erc *error)
{
	s_hash_table *items_content_table = NULL;
	s_items_content_container *ic = NULL;
	uint32 *item_content_id = NULL;
	uint32 id;
	s_bool container_exhausted;


	S_CLR_ERR(error);

	/* read S_UTT_EBML_ITEMS_CONTENTS container */
	id = S_EBMLREAD_CALL(ebmlReader, container)(ebmlReader, error);
	if (S_CHK_ERR(error, S_CONTERR,
				  "read_item_contents",
				  "ebmlRead method \"container\" failed"))
		goto quit_error;

	/* 2^9 = 512 item contents for a start */
	items_content_table = s_hash_table_new(&items_content_table_free_fp, 9, error);
	if (S_CHK_ERR(error, S_CONTERR,
				  "read_item_contents",
				  "Call to \"s_hash_table_new\" failed"))
		goto quit_error;

	while (1)
	{
		container_exhausted = S_EBMLREAD_CALL(ebmlReader, container_at_end)(ebmlReader, error);
		if (S_CHK_ERR(error, S_CONTERR,
					  "read_item_contents",
					  "ebmlRead method \"container_at_end\" failed"))
			goto quit_error;

		if (container_exhausted)
			break;

		/* peek id  */
		id = S_EBMLREAD_CALL(ebmlReader, peek_id)(ebmlReader, error);
		if (S_CHK_ERR(error, S_CONTERR,
					  "read_item_contents",
					  "ebmlRead method \"peek_id\" failed"))
			goto quit_error;

		switch(id)
		{
		case S_UTT_EBML_ITEMS_CONTENT_ID:
		{
			item_content_id = S_MALLOC(uint32, 1);
			if (item_content_id == NULL)
			{
				S_FTL_ERR(error, S_MEMERROR,
						  "read_item_contents",
						  "Failed to allocate memory for 'uint32' object");
				goto quit_error;
			}

			*item_content_id = S_EBMLREAD_CALL(ebmlReader, read_uint)(ebmlReader, &id, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_item_contents",
						  "ebmlRead method \"read_uint\" failed"))
				goto quit_error;

			/* make new item contents container */
			ic = S_CALLOC(s_items_content_container, 1);
			if (ic == NULL)
			{
				S_FTL_ERR(error, S_MEMERROR,
						  "read_item_contents",
						  "Failed to allocate memory for 's_items_content_container' object");
				goto quit_error;
			}

			/* create a new item contents */
			ic->content =  S_NEW(SItmContent, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_item_contents",
						  "Failed to create new item content"))
				goto quit_error;

			break;
		}
		case S_UTT_EBML_ITEMS_CONTENT_FEATURES:
		{
			/* read S_UTT_EBML_ITEMS_CONTENT_FEATURES container */
			id = S_EBMLREAD_CALL(ebmlReader, container)(ebmlReader, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_item_contents",
						  "ebmlRead method \"container\" failed"))
				goto quit_error;

			while (1)
			{
				container_exhausted = S_EBMLREAD_CALL(ebmlReader, container_at_end)(ebmlReader, error);
				if (S_CHK_ERR(error, S_CONTERR,
							  "read_item_contents",
							  "ebmlRead method \"container_at_end\" failed"))
					goto quit_error;

				if (container_exhausted)
				{
					/* add item contents container to hash table */
					s_hash_table_add(items_content_table, (void*)item_content_id,
									 sizeof(uint32), ic, error);
					if (S_CHK_ERR(error, S_CONTERR,
								  "read_item_contents",
								  "Call to \"s_hash_table_add\" failed"))
						goto quit_error;

					item_content_id = NULL;
					ic = NULL;
					break; /* we are finished reading the item content
							* features */
				}

				/* peek id for item content feature elements */
				id = S_EBMLREAD_CALL(ebmlReader, peek_id)(ebmlReader, error);
				if (S_CHK_ERR(error, S_CONTERR,
							  "read_item_contents",
							  "ebmlRead method \"peek_id\" failed"))
					goto quit_error;

				switch(id)
				{
				case S_UTT_EBML_ITEMS_CONTENT_FEAT_NAME:
				{
					char *feat_name;
					SObject *featObject;


					/* feature elements are ordered (feat name, feat object),
					 * so we do it in one go
					 */
					read_feature(ebmlReader,
								 &feat_name, S_UTT_EBML_ITEMS_CONTENT_FEAT_NAME,
								 &featObject, S_UTT_EBML_ITEMS_CONTENT_FEAT_OBJECT,
								 error);
					if (S_CHK_ERR(error, S_CONTERR,
								  "read_item_contents",
								  "Call to \"read_feature\" failed"))
						goto quit_error;

					/* set item content feature */
					SMapSetObject(ic->content->features, feat_name, featObject, error);
					if (S_CHK_ERR(error, S_CONTERR,
								  "read_item_contents",
								  "Call to \"SMapSetObject\" failed"))
						goto quit_error;

					/* feat name is copied */
					S_FREE(feat_name); /* sets to NULL */
					featObject = NULL;
					break;
				}
				default:
					/* unknown elements, skip */
					S_WARNING(S_FAILURE,
							  "read_item_contents",
							  "Skipping element with unknown id '0x%x'",
							  id);

					S_EBMLREAD_CALL(ebmlReader, element_skip)(ebmlReader, error);
					if (S_CHK_ERR(error, S_CONTERR,
								  "read_item_contents",
								  "ebmlRead method \"element_skip\" failed"))
						goto quit_error;
				}
			}
			break;
		}
		default:
			/* unknown elements, skip */
			S_WARNING(S_FAILURE,
					  "read_item_contents",
					  "Skipping element with unknown id '0x%x'",
					  id);

			S_EBMLREAD_CALL(ebmlReader, element_skip)(ebmlReader, error);
			if (S_CHK_ERR(error, S_CONTERR,
						  "read_item_contents",
						  "ebmlRead method \"element_skip\" failed"))
				goto quit_error;
		}
	}

	/* here everything went OK */
	return items_content_table;

	/* errors here, clean up code */
quit_error:
	if (ic != NULL)
	{
		if (ic->content != NULL)
			S_FORCE_DELETE(ic->content, "read_item_contents", error);
		S_FREE(ic);
	}

	if (items_content_table != NULL)
	{
		s_erc local_err = S_SUCCESS;

		s_hash_table_delete(items_content_table, &local_err);
		S_CHK_ERR(&local_err, S_CONTERR,
				  "read_item_contents",
				  "Call to \"s_hash_table_delete\" failed");
	}

	if (item_content_id != NULL)
		S_FREE(item_content_id);

	return NULL;
}
Beispiel #4
0
int main()
{
	s_erc error = S_SUCCESS; /* start of with a clean slate */
	s_hash_table *ht_ptr = NULL;
	const key_val *itr;
	size_t size;
	const s_hash_element *el;
	int counter;
	char *stats;


	/* initialize speect */
	error = speect_init(NULL);
	if (error != S_SUCCESS)
	{
		printf("Failed to initialize Speect\n");
		return 1;
	}

	/* create new hash table, no free function
	 * initial size is 6 (2^3) and we have 10 data elements, so
	 * hash table will grow (note that this is relatively slow).
	 */
	ht_ptr = s_hash_table_new(NULL, 3, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_new\" failed"))
		goto exit_error;

	/*
	 * add data, note that the key and value data elements can
	 * be of any type, but keys must be unique.
	 */
	for (itr = test_data; itr->key != NULL; itr++)
	{
		size = s_strsize(itr->key, &error);
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_strsize\" failed"))
			goto exit_error;

		s_hash_table_add(ht_ptr,
						 (void*)itr->key, size, (void*)&(itr->val),
						 &error);
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_hash_table_add\" failed"))
			goto exit_error;
	}

	/*
	 * iterate through hash table elements
	 */
	el = s_hash_table_first(ht_ptr, &error);  /* get first element */
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_first\" failed"))
		goto exit_error;

	counter = 0;
	printf("#\tkey\t\tvalue\n");
	while (el != NULL)
	{
		const char *key;
		const int *val;


		/* get hash element key */
		key = s_hash_element_key(el, &error);
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_hash_element_key\" failed"))
			goto exit_error;

		printf("%d\t%s\t\t", counter++, key);

		/* get hash element value */
		val = s_hash_element_get_data(el, &error);
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_hash_element_get_data\" failed"))
			goto exit_error;

		printf("%d\n", *val);

		el = s_hash_element_next(el, &error);  /* get next element */
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_hash_element_next\" failed"))
			goto exit_error;
	}
	printf("\n");


	/* get table size (number of elements in table) */
	size = s_hash_table_size(ht_ptr, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_size\" failed"))
		goto exit_error;

	printf("the hash table contains %lu elements\n\n", (unsigned long)size);

	/* get some statistics and info on the table and it's elements */
	stats = s_hash_table_stats(ht_ptr, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_stats\" failed"))
		goto exit_error;

	if (stats != NULL)
	{
		printf("%s\n", stats);
		S_FREE(stats);
	}

	/* resize hash table to 2^8 */
	s_hash_table_resize(ht_ptr, 8, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_resize\" failed"))
		goto exit_error;

	/* get some statistics and info on the table and it's elements */
	stats = s_hash_table_stats(ht_ptr, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_stats\" failed"))
		goto exit_error;

	if (stats != NULL)
	{
		printf("%s\n", stats);
		S_FREE(stats);
	}

	/* resize hash table to minimum allowed size */
	s_hash_table_resize(ht_ptr, -1, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_resize\" failed"))
		goto exit_error;

	/* get some statistics and info on the table and it's elements */
	stats = s_hash_table_stats(ht_ptr, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_stats\" failed"))
		goto exit_error;

	if (stats != NULL)
	{
		printf("%s\n", stats);
		S_FREE(stats);
	}

	/*
	 * iterate through hash table elements
	 */
	el = s_hash_table_first(ht_ptr, &error);  /* get first element */
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_first\" failed"))
		goto exit_error;

	counter = 0;
	printf("#\tkey\t\tvalue\n");
	while (el != NULL)
	{
		const char *key;
		const int *val;


		/* get hash element key */
		key = s_hash_element_key(el, &error);
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_hash_element_key\" failed"))
			goto exit_error;

		printf("%d\t%s\t\t", counter++, key);

		/* get hash element value */
		val = s_hash_element_get_data(el, &error);
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_hash_element_get_data\" failed"))
			goto exit_error;

		printf("%d\n", *val);

		el = s_hash_element_next(el, &error);  /* get next element */
		if (S_CHK_ERR(&error, S_CONTERR,
					  "main",
					  "Call to \"s_hash_element_next\" failed"))
			goto exit_error;
	}
	printf("\n");

	/* delete the hash table */
	s_hash_table_delete(ht_ptr, &error);
	if (S_CHK_ERR(&error, S_CONTERR,
				  "main",
				  "Call to \"s_hash_table_delete\" failed"))
		goto exit_error;

	/* quit speect */
	error = speect_quit();
	if (error != S_SUCCESS)
	{
		printf("Call to 'speect_quit' failed\n");
		return 1;
	}

	return 0;

exit_error:
	if (ht_ptr != NULL)
	{
		s_erc local_err = S_SUCCESS;


		/* we use a local error here because we already have an set
		 * error by the time we reach this point, and
		 * s_hash_table_delete will clear it.
		 */
		s_hash_table_delete(ht_ptr, &local_err);
	}

	error = speect_quit();
	if (error != S_SUCCESS)
		printf("Call to 'speect_quit' failed\n");

	return 1;
}