home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / jikes-1.02 / src / tuple.h < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-05  |  12.6 KB  |  469 lines

  1. // $Id: tuple.h,v 1.6 1999/08/26 15:34:10 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #ifndef TUPLE_INCLUDED
  11. #define TUPLE_INCLUDED
  12.  
  13. #ifdef WIN32_FILE_SYSTEM
  14. #include <windows.h>
  15. #endif
  16.  
  17. #include "config.h"
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <assert.h>
  22.  
  23. class OutputBuffer;
  24.  
  25. //
  26. // This Tuple template class can be used to construct a dynamic
  27. // array of arbitrary objects. The space for the array is allocated in
  28. // blocks of size 2**LOG_BLKSIZE. In declaring a tuple the user
  29. // may specify an estimate of how many elements he expects.
  30. // Based on that estimate, suitable value will be calsulated log_blksize
  31. // and base_increment. If these estimates are off, more space will be
  32. // allocated.
  33. //
  34. template <class T>
  35. class Tuple
  36. {
  37. protected:
  38.  
  39.     friend class OutputBuffer;
  40.  
  41.     enum { DEFAULT_LOG_BLKSIZE = 3, DEFAULT_BASE_INCREMENT = 4 };
  42.  
  43.     T **base;
  44.     int base_size,
  45.         top,
  46.         size;
  47.  
  48.     int log_blksize,
  49.         base_increment;
  50.  
  51.     inline int Blksize() { return (1 << log_blksize); }
  52.  
  53.     //
  54.     // Allocate another block of storage for the dynamic array.
  55.     //
  56.     inline void AllocateMoreSpace()
  57.     {
  58.         //
  59.         // The variable size always indicates the maximum number of
  60.         // elements that has been allocated for the array.
  61.         // Initially, it is set to 0 to indicate that the array is empty.
  62.         // The pool of available elements is divided into segments of size
  63.         // 2**log_blksize each. Each segment is pointed to by a slot in
  64.         // the array base.
  65.         //
  66.         // By dividing size by the size of the segment we obtain the
  67.         // index for the next segment in base. If base is full, it is
  68.         // reallocated.
  69.         //
  70.         //
  71.         int k = size >> log_blksize; /* which segment? */
  72.  
  73.         //
  74.         // If the base is overflowed, reallocate it and initialize the new elements to NULL.
  75.         //
  76.         if (k == base_size)
  77.         {
  78.             int old_base_size = base_size;
  79.             T **old_base = base;
  80.  
  81.             base_size += base_increment;
  82.             base = new T*[base_size];
  83.  
  84.             if (old_base != NULL)
  85.             {
  86.                 memmove(base, old_base, old_base_size * sizeof(T *));
  87.                 delete [] old_base;
  88.             }
  89.             memset(&base[old_base_size], 0, (base_size - old_base_size) * sizeof(T *));
  90.         }
  91.  
  92.         //
  93.         // We allocate a new segment and place its adjusted address in
  94.         // base[k]. The adjustment allows us to index the segment directly,
  95.         // instead of having to perform a subtraction for each reference.
  96.         // See operator[] below.
  97.         //
  98.         base[k] = new T[Blksize()];
  99.         base[k] -= size;
  100.  
  101.         //
  102.         // Finally, we update SIZE.
  103.         //
  104.         size += Blksize();
  105.  
  106.         return;
  107.     }
  108.  
  109. public:
  110.  
  111.     //
  112.     // This function is invoked with an integer argument n. It ensures
  113.     // that enough space is allocated for n elements in the dynamic array.
  114.     // I.e., that the array will be indexable in the range  (0..n-1)
  115.     //
  116.     // Note that this function can be used as a garbage collector.  When
  117.     // invoked with no argument(or 0), it frees up all dynamic space that
  118.     // was allocated for the array.
  119.     //
  120.     inline void Resize(const int n = 0)
  121.     {
  122.         //
  123.         // If array did not previously contain enough space, allocate
  124.         // the necessary additional space. Otherwise, if the array had
  125.         // more blocks than are needed, release the extra blocks.
  126.         //
  127.         if (n > size)
  128.         {
  129.             do
  130.             {
  131.                 AllocateMoreSpace();
  132.             } while (n > size);
  133.         }
  134.         else if (n < size)
  135.         {
  136.             // slot is the index of the base element whose block
  137.             // will contain the (n-1)th element.
  138.             int slot = (n <= 0 ? -1 : (n - 1) >> log_blksize);
  139.  
  140.             for (int k = (size >> log_blksize) - 1; k > slot; k--)
  141.             {
  142.                 size -= Blksize();
  143.                 base[k] += size;
  144.                 delete [] base[k];
  145.                 base[k] = NULL;
  146.             }
  147.  
  148.             if (slot < 0)
  149.             {
  150.                 delete [] base;
  151.                 base = NULL;
  152.                 base_size = 0;
  153.             }
  154.         }
  155.  
  156.         top  = n;
  157.     }
  158.  
  159.     //
  160.     // This function is used to reset the size of a dynamic array without
  161.     // allocating or deallocting space. It may be invoked with an integer
  162.     // argument n which indicates the new size or with no argument which
  163.     // indicates that the size should be reset to 0.
  164.     //
  165.     inline void Reset(const int n = 0)
  166.     {
  167.         assert(n >= 0 && n <= size);
  168.  
  169.         top = n;
  170.     }
  171.  
  172.     //
  173.     // Return length of the dynamic array.
  174.     //
  175.     inline int Length() { return top; }
  176.  
  177.     //
  178.     // Return a reference to the ith element of the dynamic array.
  179.     //
  180.     // Note that no check is made here to ensure that 0 <= i < top.
  181.     // Such a check might be useful for debugging and a range exception
  182.     // should be thrown if it yields true.
  183.     //
  184.     inline T& operator[](const int i)
  185.     {
  186.         assert(i >= 0 && i < top);
  187.  
  188.         return base[i >> log_blksize][i];
  189.     }
  190.  
  191.     //
  192.     // Add an element to the dynamic array and return the top index.
  193.     //
  194.     inline int NextIndex()
  195.     {
  196.         int i = top++;
  197.         if (i == size)
  198.             AllocateMoreSpace();
  199.         return i;
  200.     }
  201.  
  202.     //
  203.     // Add an element to the dynamic array and return a reference to
  204.     // that new element.
  205.     //
  206.     inline T& Next() { int i = NextIndex(); return base[i >> log_blksize][i]; }
  207.  
  208.     //
  209.     // Assignment of a dynamic array to another.
  210.     //
  211.     inline Tuple<T>& operator=(const Tuple<T>& rhs)
  212.     {
  213.         if (this != &rhs)
  214.         {
  215.             Resize(rhs.top);
  216.             for (int i = 0; i < rhs.top; i++)
  217.                 base[i >> log_blksize][i] = rhs.base[i >> log_blksize][i];
  218.         }
  219.  
  220.         return *this;
  221.     }
  222.  
  223.     //
  224.     // Constructor of a Tuple
  225.     //
  226.     Tuple(unsigned estimate = 0)
  227.     {
  228.         if (estimate == 0)
  229.         {
  230.             log_blksize = DEFAULT_LOG_BLKSIZE;
  231.             base_increment = DEFAULT_BASE_INCREMENT;
  232.         }
  233.         else
  234.         {
  235.             for (log_blksize = 1; (((unsigned) 1 << log_blksize) < estimate) && (log_blksize < 31); log_blksize++)
  236.                 ;
  237.             if (log_blksize <= DEFAULT_LOG_BLKSIZE)
  238.                 base_increment = 1;
  239.             else if (log_blksize < 13)
  240.             {
  241.                 base_increment = (unsigned) 1 << (log_blksize - 4);
  242.                 log_blksize = 4;
  243.             }
  244.             else
  245.             {
  246.                 base_increment = (unsigned) 1 << (log_blksize - 8);
  247.                 log_blksize = 8;
  248.             }
  249.             base_increment++; // add a little margin to avoid reallocating the base.
  250.         }
  251.  
  252.         base_size = 0;
  253.         size = 0;
  254.         top = 0;
  255.         base = NULL;
  256.     }
  257.  
  258.     //
  259.     // Constructor of a Tuple
  260.     //
  261.     Tuple(int log_blksize_, int base_increment_) : log_blksize(log_blksize_),
  262.                                                    base_increment(base_increment_)
  263.     {
  264.         base_size = 0;
  265.         size = 0;
  266.         top = 0;
  267.         base = NULL;
  268.     }
  269.  
  270.     //
  271.     // Initialization of a dynamic array.
  272.     //
  273.     Tuple(const Tuple<T>& rhs) : log_blksize(rhs.log_blksize),
  274.                                  base_increment(rhs.base_increment)
  275.     {
  276.         base_size = 0;
  277.         size = 0;
  278.         base = NULL;
  279.         *this = rhs;
  280.     }
  281.  
  282.     //
  283.     // Destructor of a dynamic array.
  284.     //
  285.     ~Tuple() { Resize(0); }
  286.  
  287.     // ********************************************************************************************** //
  288.  
  289.     //
  290.     // Return the total size of temporary space allocated.
  291.     //
  292.     inline size_t SpaceAllocated(void)
  293.     {
  294.         return ((base_size * sizeof(T **)) + (size * sizeof(T)));
  295.     }
  296.  
  297.     //
  298.     // Return the total size of temporary space used.
  299.     //
  300.     inline size_t SpaceUsed(void)
  301.     {
  302.         return (((size >> log_blksize) * sizeof(T **)) + (top * sizeof(T)));
  303.     }
  304. };
  305.  
  306.  
  307. //
  308. //
  309. //
  310. template <class T>
  311. class ConvertibleArray : public Tuple<T>
  312. {
  313. public:
  314.  
  315.     ConvertibleArray(int estimate = 0) : Tuple<T>(estimate),
  316.                                          array(NULL)
  317.     {}
  318.  
  319.     ConvertibleArray(int log_blksize, int base_increment) : Tuple<T>(log_blksize, base_increment),
  320.                                                             array(NULL)
  321.     {}
  322.  
  323.     ~ConvertibleArray() { delete [] array; }
  324.  
  325.     //
  326.     // This function converts a tuple into a regular array and destroys the
  327.     // original tuple.
  328.     //
  329.     inline T *&Array()
  330.     {
  331.         if ((! array) && Tuple<T>::top > 0)
  332.         {
  333.             array = new T[Tuple<T>::top];
  334.  
  335.             int i = 0,
  336.                 processed_size = 0,
  337.                 n = (Tuple<T>::top - 1) >> Tuple<T>::log_blksize; // the last non-empty slot!
  338.             while (i < n)
  339.             {
  340.                 memmove(&array[processed_size], Tuple<T>::base[i] + processed_size, Tuple<T>::Blksize() * sizeof(T));
  341.                 delete [] (Tuple<T>::base[i] + processed_size);
  342.                 i++;
  343.                 processed_size += Tuple<T>::Blksize();
  344.             }
  345.             memmove(&array[processed_size], Tuple<T>::base[n] + processed_size, (Tuple<T>::top - processed_size) * sizeof(T));
  346.             delete [] (Tuple<T>::base[n] + processed_size);
  347.             delete [] Tuple<T>::base;
  348.             Tuple<T>::base = NULL;
  349.             Tuple<T>::size = 0;
  350.         }
  351.  
  352.         return array;
  353.     }
  354.  
  355.     inline T& operator[](const int i)
  356.     {
  357.         assert(i >= 0 && i < Tuple<T>::top);
  358.  
  359.         return (array ? array[i] : Tuple<T>::base[i >> Tuple<T>::log_blksize][i]);
  360.     }
  361.  
  362.     inline void Resize(const int n = 0) { assert(false); }
  363.     inline void Reset(const int n = 0) { assert(false); }
  364.     inline T& Next()
  365.     {
  366.         assert(! array);
  367.  
  368.         int i = Tuple<T>::NextIndex();
  369.         return Tuple<T>::base[i >> Tuple<T>::log_blksize][i];
  370.     }
  371.     inline Tuple<T>& operator=(const Tuple<T>& rhs)
  372.     {
  373.         assert(false);
  374.         return *this;
  375.     }
  376.  
  377. private:
  378.  
  379.     T *array;
  380. };
  381.  
  382.  
  383. //
  384. //
  385. //
  386. class OutputBuffer
  387. {
  388. public:
  389.  
  390.     OutputBuffer(int log_blksize = 13, int base_increment = 128) : buffer(log_blksize, base_increment) {}
  391.  
  392.     inline void PutB1(u1 u) { buffer.Next() = u; }
  393.  
  394.     inline void PutB2(u2 u)
  395.     {
  396.         buffer.Next() = u >> 8;
  397.         buffer.Next() = u & 0xff;
  398.     }
  399.  
  400.     inline void PutB4(u4 u)
  401.     {
  402.         buffer.Next() = u >> 24;
  403.         buffer.Next() = (u >> 16) & 0xff;
  404.         buffer.Next() = (u >> 8)  & 0xff;
  405.         buffer.Next() = u & 0xff;
  406.     }
  407.  
  408.     inline void put_n(u1 *u, int n)
  409.     {
  410.         for (int i = 0; i < n; i++)
  411.             buffer.Next() = u[i];
  412.     }
  413.  
  414.     inline bool WriteToFile(char *file_name)
  415.     {
  416. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  417.         FILE *file = ::SystemFopen(file_name, "wb");
  418.         if (file  ==  (FILE *) NULL)
  419.             return false;
  420.  
  421.         int i = 0,
  422.             size = 0,
  423.             n = (buffer.top - 1) >> buffer.log_blksize; // the last non-empty slot!
  424.         while (i < n)
  425.         {
  426.             fwrite(buffer.base[i] + size, sizeof(u1), buffer.Blksize(), file);
  427.             i++;
  428.             size += buffer.Blksize();
  429.         }
  430.         fwrite(buffer.base[n] + size, sizeof(u1), (buffer.top - size), file);
  431.  
  432.         fclose(file);
  433. #elif defined(WIN32_FILE_SYSTEM)
  434.         HANDLE file = CreateFile(file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  435.         HANDLE mapfile = (file == INVALID_HANDLE_VALUE
  436.                                      ? file
  437.                                      : CreateFileMapping(file, NULL, PAGE_READWRITE, 0, buffer.top, NULL));
  438.         if (mapfile == INVALID_HANDLE_VALUE)
  439.             return false;
  440.         u1 *string_buffer = (u1 *) MapViewOfFile(mapfile, FILE_MAP_WRITE, 0, 0, buffer.top);
  441.  
  442.         assert(string_buffer);
  443.  
  444.         int i = 0,
  445.             size = 0,
  446.             n = (buffer.top - 1) >> buffer.log_blksize; // the last non-empty slot!
  447.         while (i < n)
  448.         {
  449.             memmove(&string_buffer[size], buffer.base[i] + size, buffer.Blksize() * sizeof(u1));
  450.             i++;
  451.             size += buffer.Blksize();
  452.         }
  453.         memmove(&string_buffer[size], buffer.base[n] + size, (buffer.top - size) * sizeof(u1));
  454.  
  455.         UnmapViewOfFile(string_buffer);
  456.         CloseHandle(mapfile);
  457.         CloseHandle(file);
  458. #endif
  459.  
  460.         return true;
  461.     }
  462.  
  463. private:
  464.  
  465.     Tuple<u1> buffer;
  466. };
  467.  
  468. #endif /* #ifndef TUPLE_INCLUDED */
  469.