// Python Wrapper object
static PyObject *Produce_Xor_From_Bitstring(PyObject *module, PyObject *args) {
  datastore_descriptor ds;
  int bitstringlength;
  char *bitstringbuffer;
  char *raw_resultbuffer;
  uint64_t *resultbuffer;

  if (!PyArg_ParseTuple(args, "is#", &ds, &bitstringbuffer, &bitstringlength)) {
    // Incorrect args...
    return NULL;
  }

  // Is the ds valid?
  if (!is_table_entry_used(ds)) {
    PyErr_SetString(PyExc_ValueError, "Bad index for Produce_Xor_From_Bitstring");
    return NULL;
  }

  // Let's prepare a place to put this...
  raw_resultbuffer = malloc(xordatastoretable[ds].sizeofablock+sizeof(uint64_t));
  // ...and zero it out...
  bzero(raw_resultbuffer, xordatastoretable[ds].sizeofablock+sizeof(uint64_t));

  // ... now let's get a DWORD aligned offset
  resultbuffer = (uint64_t *) dword_align(raw_resultbuffer);

  // Let's actually calculate this!
  bitstring_xor_worker(ds, bitstringbuffer, bitstringlength, resultbuffer);



  // okay, let's put it in a buffer
  PyObject *return_str_obj = Py_BuildValue("s#",(char *)resultbuffer,xordatastoretable[ds].sizeofablock);

  // clear the buffer
  free(raw_resultbuffer);

  return return_str_obj;
} 
// Python Wrapper object
static PyObject *Produce_Xor_From_Bitstrings(PyObject *module, PyObject *args) {
	datastore_descriptor ds;
	int bitstringlength;
	unsigned int numstrings;
	char *bitstringbuffer;
	char *raw_resultbuffer;
	__m128i *resultbuffer;


	if (!PyArg_ParseTuple(args, "iy#I", &ds, &bitstringbuffer, &bitstringlength, &numstrings)) {
		// Incorrect args...
		return NULL;
	}


	// Is the ds valid?
	if (!is_table_entry_used(ds)) {
		PyErr_SetString(PyExc_ValueError, "Bad index for Produce_Xor_From_Bitstring");
		return NULL;
	}

	// Let's prepare a place to put the answer (numstrings blocks + alignment)
	raw_resultbuffer = (char*) calloc(1, xordatastoretable[ds].sizeofablock * numstrings + sizeof(__m128i));

	// align it
	resultbuffer = (__m128i *) dword_align(raw_resultbuffer);

	// Let's actually calculate this!
	multi_bitstring_xor_worker(ds, bitstringbuffer, bitstringlength, numstrings, resultbuffer);

	// okay, let's put it in a buffer
	PyObject *return_str_obj = Py_BuildValue("y#",(char *)resultbuffer, xordatastoretable[ds].sizeofablock * numstrings);

	// clear the buffer
	free(raw_resultbuffer);

	return return_str_obj;
}
// This allocates memory and stores the size / num_blocks for 
// error checking later
static datastore_descriptor allocate(long block_size, long num_blocks)  {
  int i;

  // If it isn't inited, let's fill in the table with empty entries
  if (!xordatastoreinited) {
    // start the table as entry
    for (i=0; i<STARTING_XORDATASTORE_TABLESIZE; i++) {
      xordatastoretable[i].numberofblocks = 0;
      xordatastoretable[i].sizeofablock = 0;
      xordatastoretable[i].raw_datastore = NULL;
      xordatastoretable[i].datastore = NULL;
    }
    // We've initted now!
    xordatastoreinited = 1;
  }

  for (i=0; i<xordatastorestablesize; i++) {
    // Look for an empty entry
    if (!is_table_entry_used(i)) {
      xordatastoretable[i].numberofblocks = num_blocks;
      xordatastoretable[i].sizeofablock = block_size;

      // I allocate a little bit extra so that I can DWORD align it
      xordatastoretable[i].raw_datastore = malloc(num_blocks * block_size + sizeof(uint64_t));
      // Zero it out
      bzero(xordatastoretable[i].raw_datastore, num_blocks * block_size + sizeof(uint64_t));
      
      // and align it...
      xordatastoretable[i].datastore = (uint64_t *) dword_align(xordatastoretable[i].raw_datastore);
      return i;
    }
  }

  // The table is full!   I really should expand it...
  printf("Internal Error: I need to expand the table size (unimplemented)\n");
  return -1;
}