/* Copyright (c) 2009
 * Vincenzo Liberatore, Case Western Reserve University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * - Neither the name of Case Western Reserve University nor the names of
 *   its contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

/* Examples 1 and 2: a bag of doubles */

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

typedef struct {
  double *bag;
  size_t n;    /* Maximum size of the double bag */
  size_t cnt;  /* Number of elements in the double bag */
} double_bag_t;


double_bag_t *double_bag_init(size_t n) {
  double_bag_t *bag;

  /* Allocate the bag */
  bag = (double_bag_t *) malloc(sizeof(double_bag_t));
  if (bag == NULL) {
    fprintf(stderr, "Cannot allocate bag\n");
    exit(EXIT_FAILURE);
  }

  /* Allocate the bag array */
  bag->bag = (double *) calloc(n, sizeof(double));
  if (bag->bag == NULL) {
    fprintf(stderr, "Cannot allocate bag array\n");
    exit(EXIT_FAILURE);
  }

  /* Initialize bag values */
  bag->n = n;
  bag->cnt = 0;

  return bag;
}


int double_bag_insert(double_bag_t *bag, double value) {
  assert(bag != NULL);

  /* Check that there is enough room in the bag */
  if (bag->cnt >= bag->n)
    return 0;

  bag->bag[bag->cnt++] = value;
  return 1;
}


int double_bag_search(double_bag_t *bag, double value) {
  size_t i;          /* Cursor */
  size_t cnt;        /* Alias for bag->cnt */
  double *bag_array; /* Alias for bag->bag */

  assert(bag != NULL);

  /* Assign local aliases */
  cnt       = bag->cnt;
  bag_array = bag->bag;

  /* Search the array */
  for (i = 0; i < cnt && bag_array[i] != value; i++);

  /* If i<cnt, the loop terminated earlier --> the element was found.
     Otherwise, it ran to the end --> it was not found */
  return i < cnt;
}


void double_bag_delete(double_bag_t *bag) {
  assert(bag != NULL);

  free(bag->bag);
  free(bag);
}


int main() {
  double_bag_t *bag;

  bag = double_bag_init(10);

  printf("Insert 4: %u (1=ok, 0=failure)\n", double_bag_insert(bag, 4.));
  printf("Insert 9: %u (1=ok, 0=failure)\n", double_bag_insert(bag, 9.));
  printf("Insert 4: %u (1=ok, 0=failure)\n", double_bag_insert(bag, 4.));

  printf("Is 7 in the bag? %u\n", double_bag_search(bag, 7.));

  printf("Insert 7: %u (1=ok, 0=failure)\n", double_bag_insert(bag, 7.));

  printf("Is 7 in the bag? %u\n", double_bag_search(bag, 7.));

  double_bag_delete(bag);
}
