
#ifndef __STRUCT_H
#define __STRUCT_H

/*
 * header files
 */
#include "p.basic.h"

@begin
   header "basic.h";
@end

/*
 * definition of structure string_s
 */

/*
 * structure which implement string
 */
struct string_s
{
   unsigned size;
   char *data;

   inline void init();
   inline void clear();
   inline void create(unsigned a_length);
   inline void set(unsigned a_length,char *a_data);
   inline void conc_set(unsigned a_flength,char *a_fdata,unsigned a_slength,char *a_sdata);
   inline void flush_all();
   inline void swap(string_s &second);
   inline char &operator[](unsigned a_idx);
   inline string_s &operator=(string_s &src);
   inline bool operator==(string_s &second);
   inline bool compare_char_ptr(unsigned a_length,char *a_data);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr,char *b_ptr_end);
   inline void print();
   inline bool load_text_file(char *file);
   inline bool save_text_file(char *file);
};

/*
 * definition of structure mutex_s
 */

struct mutex_s
{
   pthread_mutex_t mutex;

   inline void init();
   inline void clear();
   inline void flush_all() {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"flush_all");};
   inline void swap(mutex_s &second) {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"swap");};
   inline mutex_s &operator=(mutex_s &src) {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"operator=");};
   inline bool operator==(mutex_s &second) {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"operator==");};
   inline unsigned save_size() {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"save_size");};
   inline void save_to(char **b_ptr) {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"save_to");};
   inline void load_from(char **b_ptr,char *b_ptr_end) {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"load_from");};
   inline void print() {err_test1(0,c_DR_ERR_MUTEXT_OPERATION_UNIMPLEMENTED,(unsigned)"print");};
   inline void lock();
   inline void unlock();
};

/*
 * definition of generated structures
 */

// -- bc_array_s --
@begin
   array<char> bc_array_s;
@end

// -- bi_array_s --
@begin
   array<int> bi_array_s;
@end

// -- ui_array_s --
@begin
   array<unsigned> ui_array_s;
@end

// -- bd_array_s --
@begin
   array<double> bd_array_s;
@end

// -- string_array_s --
@begin
   array<string_s>
   "unsigned get_idx_char_ptr(unsigned a_length,char *a_data);"
   string_array_s;
@end

// -- ui_arrays_s --
@begin
   array<ui_array_s> ui_arrays_s;
@end

// -- lalr_stack_element_s --
// -- symbol_s --
// -- sp_mcs_s --
@begin
   struct
   <
   unsigned
   unsigned
   unsigned
   >
   <-v	       $//sp_mutex_s	    sp_condition_s
   ui_first    $//locked/unlocked   waiting_cnt
   ui_second   $//handler_cnt	    handler_cnt
   ui_third    $//owner_idx	    signal_cnt
   >
   lalr_stack_element_s
   symbol_s
   sp_mcs_s;
@end

// -- lalr_stack_s --
// -- symbols_s --
// -- sp_mcs_array_s --
@begin
   array<lalr_stack_element_s>
   "inline void push(unsigned a_ui_first);"
   "inline void push(unsigned a_ui_first,unsigned a_ui_second,unsigned a_ui_third);"
   "unsigned get_idx_by_ui_first(unsigned a_ui_first);"
   lalr_stack_s
   symbols_s
   sp_mcs_array_s;
@end

/*
 * inline methods of structure string_s
 */

inline void string_s::init()
{
   size = 0;
   data = NULL;
}

inline void string_s::clear()
{
   if (data != NULL) {
      cfree(data);
   }

   init();
}

inline void string_s::create(unsigned a_length)
{
   clear();
   data = (char *)cmalloc((a_length + 1)*sizeof(char));

   data[a_length] = '\0';
   size = a_length + 1;
}

inline void string_s::set(unsigned a_length,char *a_data)
{
   clear();
   data = (char *)cmalloc((a_length + 1)*sizeof(char));

   if (a_length != 0) {
      memcpy(data,a_data,a_length*sizeof(char));
   }

   data[a_length] = '\0';
   size = a_length + 1;
}

inline void string_s::conc_set(unsigned a_flength,char *a_fdata,unsigned a_slength,char *a_sdata)
{
   clear();
   data = (char *)cmalloc((a_flength + a_slength + 1)*sizeof(char));

   if (a_flength != 0) {
      memcpy(data,a_fdata,a_flength*sizeof(char));
   }

   if (a_slength != 0) {
      memcpy(data + a_flength,a_sdata,a_slength*sizeof(char));
   }

   data[a_flength + a_slength] = '\0';
   size = a_flength + a_slength + 1;
}

inline void string_s::flush_all()
{
}

inline void string_s::swap(string_s &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   char *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline char &string_s::operator[](unsigned a_idx)
{
   debug_assert(a_idx < size);
   return data[a_idx];
}

inline string_s &string_s::operator=(string_s &src)
{
   clear();
   if (src.size == 0) return *this;
   data = (char *)cmalloc(src.size*sizeof(char));
   memcpy(data,src.data,src.size*sizeof(char));
   size = src.size;

   return *this;
}

inline bool string_s::operator==(string_s &second)
{
   if (size != second.size) return false;
   if (size == 0) return true;
   return (memcmp(data,second.data,size*sizeof(char)) == 0);
}

inline bool string_s::compare_char_ptr(unsigned a_length,char *a_data)
{
   if (size != a_length + 1) return false;
   if (a_length == 0) return true;
   return (memcmp(data,a_data,a_length*sizeof(char)) == 0);
}

inline unsigned string_s::save_size()
{
   return sizeof(unsigned) + size*sizeof(char);
}

inline void string_s::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = size; *b_ptr += sizeof(unsigned);

   if (size == 0) return;
   memcpy(*b_ptr,data,size*sizeof(char));
   *b_ptr += size*sizeof(char);
}

inline void string_s::load_from(char **b_ptr,char *b_ptr_end)
{
   clear();
   err_test(*b_ptr + sizeof(unsigned) <= b_ptr_end,c_R_ERR_LOAD_BUFFER_OVERFLOW);
   size = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);

   unsigned data_size = size*sizeof(char);
   data = (char *)cmalloc(data_size);
   err_test(*b_ptr + data_size <= b_ptr_end,c_R_ERR_LOAD_BUFFER_OVERFLOW);
   memcpy(data,*b_ptr,data_size);
   *b_ptr += data_size;
}

inline void string_s::print()
{
   if (size == 0) return;
   printf("%s",data);
}

inline bool string_s::load_text_file(char *file)
{
   if (file == NULL) return false;
   FILE *f = fopen(file,"rb");
   if (f == NULL) return false;

   fseek(f,0,SEEK_END);
   unsigned file_size = ftell(f);
   fseek(f,0,SEEK_SET);

   clear();
   data = (char *)cmalloc((file_size + 1)*sizeof(char));
   fread(data,file_size,1,f);
   fclose(f);

   data[file_size] = '\0';
   size = file_size + 1;

   return true;
}

inline bool string_s::save_text_file(char *file)
{
   if (file == NULL) return false;
   FILE *f = fopen(file,"wb");
   if (f == NULL) return false;

   if (size > 1) {
      fwrite(data,size - 1,1,f);
   }

   fclose(f);
   return true;
}

/*
 * inline methods of structure mutex_s
 */

inline void mutex_s::init()
{
   pthread_mutex_init(&mutex,NULL);
}

inline void mutex_s::clear()
{
   int ret = pthread_mutex_destroy(&mutex);
   err_test1(ret == 0,c_DR_ERR_MUTEX_OPERATION_FAILED,(unsigned)"clear");
}

inline void mutex_s::lock()
{
   int ret = pthread_mutex_lock(&mutex);
   err_test1(ret == 0,c_DR_ERR_MUTEX_OPERATION_FAILED,(unsigned)"lock");
}

inline void mutex_s::unlock()
{
   int ret = pthread_mutex_unlock(&mutex);
   err_test1(ret == 0,c_DR_ERR_MUTEX_OPERATION_FAILED,(unsigned)"unlock");
}

/*
 * inline methods of generated structures
 */

// -- bc_array_s --
@begin
   inlines "bc_array_s";
@end

// -- bi_array_s --
@begin
   inlines "bi_array_s";
@end

// -- ui_array_s --
@begin
   inlines "ui_array_s";
@end

// -- bd_array_s --
@begin
   inlines "bd_array_s";
@end

// -- string_array_s --
@begin
   inlines "string_array_s";
@end

// -- ui_arrays_s --
@begin
   inlines "ui_arrays_s";
@end

// -- lalr_stack_element_s --
// -- symbol_s --
// -- sp_mcs_s --
@begin
   inlines "lalr_stack_element_s";
@end

// -- lalr_stack_s --
// -- symbols_s --
// -- sp_mcs_array_s --
@begin
   inlines "lalr_stack_s";
@end

/*
 * push new value at the top of stack
 */

inline void lalr_stack_s::push(unsigned a_ui_first)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   lalr_stack_element_s &target = data[used++];

   target.ui_first = a_ui_first;
}

/*
 * push new value at the top of stack
 */

inline void lalr_stack_s::push(unsigned a_ui_first,unsigned a_ui_second,unsigned a_ui_third)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   lalr_stack_element_s &target = data[used++];

   target.ui_first = a_ui_first;
   target.ui_second = a_ui_second;
   target.ui_third = a_ui_third;
}

#endif

