#ifndef _CSSMINC_H_
#define _CSSMINC_H_

#include "cssm.h"
#include "asnbase.h"


class EXPORTCLASS cssm_inc {
private:
  memory_funcs_t m;
  uint32 rd; // Points to the next object to read
  uint32 wr; // Points to the next object to write
  uint32 sz; // Gives the total number of objects
  CSSM_DATA_PTR * darr;
  uint32 extend(int n = 10) {
    uint32 i;
    if (int(sz - wr) > n) return 0; // Already space
    darr = (CSSM_DATA_PTR *)m.realloc(darr, (wr + n) * sizeof(CSSM_DATA_PTR));
    if (darr == NULL) throw "Out of memory in cssm_inc";
    for (i=wr;i<wr+n;i++) darr[i] = 0;
    sz = wr + n;
    return 0;
  };
public:
  uint32 unread_count(void) {
    return wr - rd;
  };
  cssm_inc(memory_funcs_t mems) {
    m = mems;
    rd = 0;
    wr = 0;
    sz = 0;
    darr = NULL;
  };
  ~cssm_inc() {
    uint32 i;
    for (i=rd; i < wr; i++) {
      if (darr[i] && darr[i]->Data) m.free(darr[i]->Data);
      if (darr[i]) m.free(darr[i]);
    };
    m.free(darr);
  };
  void append(const r_buffer_t & b) {
    extend(1);
    darr[wr] = (CSSM_DATA_PTR)m.malloc(sizeof(CSSM_DATA));
    darr[wr]->Data = (unsigned char *)m.malloc(b.data_len);
    memcpy(darr[wr]->Data, b.data, b.data_len);
    darr[wr]->Length = b.data_len;
  };
  void append_own(buffer_t & b) {
    extend(1);
    darr[wr] = (CSSM_DATA_PTR)m.malloc(sizeof(CSSM_DATA));
    darr[wr]->Data = b.data;
    darr[wr]->Length = b.data_len;
    b.detach();
  };
  CSSM_DATA_PTR extract(void) {
    CSSM_DATA_PTR res;
    if (rd < wr) {
      res = darr[rd];
      darr[rd++] = NULL;
      return res;
    } else return (CSSM_DATA_PTR) 0;
  };
};


// These functions allow pointers to be safe casting between
// pointers and 32-bit integers, regardless of the size of a 
// pointer on the platform.
EXPORTFN(uint32, ptrToHandle, (void * ptr));

EXPORTFN(void *, handleToPtr, (uint32 h, bool destroy = false));

#endif