#include <list>
#include <stdio.h>
#include "properties_file.h"

namespace util_tools {

properties_file::~properties_file()
{
   for(int i = 0; i < _prop_vec.size(); i++) {
      delete [] (_prop_vec[i]->first);
      delete [] (_prop_vec[i]);
   }
}

char * 
new_strdup(const char * str) 
{
   size_t len = strlen(str);
   char * p = new char[len+1];
   memset(p, 0, len+1);
   memcpy(p, str, len);
   return p;
}

bool
properties_file::_load()
{
   FILE * fin = fopen(_file_name, "r");
   if(fin == NULL)
      return false;

   pair_ptr_type p_pair;
   const size_t BUFFER_SIZE = 1024 * 4;
   char buffer[BUFFER_SIZE];
   size_t length;
   list< char * > string_buffer;
   char * ptr;

   memset(buffer, 0, BUFFER_SIZE);
   while(fgets(buffer, BUFFER_SIZE - 1, fin) != NULL) {
      length = strlen(buffer);
      if(length > 0) {
         if(buffer[0] == '#')
            continue;
         if(buffer[length - 1] == '\n') {
            length--;
            buffer[length] = '\0';
         }
      }
      if(length > 0) {
         if(buffer[length - 1] == '\r') {
            length--;
            buffer[length] = '\0';
         }
      } 
      if(length == 0)
         continue;

      if(buffer[length - 1] == '\\') {
		 if(length < strlen(buffer)) {
			 if(buffer[length] == '\\') {
				 buffer[length-1] = '\\';
				 length++;
			 }
			 else {
				buffer[length - 1] = '\0';
			 }
		 }
         string_buffer.push_back(new_strdup(buffer));
         memset(buffer, 0, BUFFER_SIZE);
         continue;
      }
      else {
         if(string_buffer.size() > 0) {
            size_t the_size = length;
			list< char * >::iterator p;
            for(p = string_buffer.begin();
                p != string_buffer.end(); p++)
               the_size += strlen(*p);
            char * temp = new char[the_size + 1];
            memset(temp, 0, the_size+1);
            ptr = temp;
            char * ptr2;
            for(p = string_buffer.begin();
                p != string_buffer.end(); p++) {
               ptr2 = (*p);
               while(*ptr2 != '\0')
                  *ptr++ = *ptr2++;
            }
            for(p = string_buffer.begin();
                p != string_buffer.end(); p++)
               delete [] (*p);
            string_buffer = list< char * >();
            //string_buffer.erase(string_buffer.begin(), string_buffer.end());

            for(ptr2 = buffer; *ptr2 != '\0'; ptr2++)
               *ptr++ = *ptr2;

            ptr = temp;
         }
         else 
            ptr = new_strdup(buffer);

         char * p = strchr(ptr, '=');

         if(p == NULL) 
            p_pair = new pair_type(ptr, "");
         else {
            *p = '\0';
            p++;
            p_pair = new pair_type(ptr, p);
         }

         _prop_vec.push_back(p_pair);
      }

      memset(buffer, 0, BUFFER_SIZE);
   }

   if(string_buffer.size() > 0) {
	   for(list< char * >::iterator p = string_buffer.begin(); 
          p != string_buffer.end(); p++) 
         delete [] (*p);
      string_buffer = list< char * >();
      //string_buffer.erase(string_buffer.end(), string_buffer.begin());
   }
   fclose(fin);

   prop_less pred;
   sort(_prop_vec.begin(), _prop_vec.end(), pred);

   return true;
}

const char * 
properties_file::operator[](const char * prop_name) const 
{
   if(_prop_vec.size() == 0)
      return 0;

   int mid;
   pair_ptr_type midvalue;
   int low = 0;
   int high = _prop_vec.size() - 1;
   int rc;

   while(low <= high) {
      mid = (low + high) >> 1; 
      midvalue = _prop_vec[mid];

      if((rc = strcmp(midvalue->first, prop_name)) == 0)
         return midvalue->second;
      else if(rc < 0)
         low = mid + 1;
      else
         high = mid - 1;
   }

   return 0;
}

}
