Advertisement
Guest User

dynamic21

a guest
May 22nd, 2019
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.17 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <array>
  5. #include <random>
  6. #include <functional>
  7. #include <time.h>
  8.  
  9. // Мини логгер
  10.  
  11. template <typename T>
  12. void log(T&& val) {
  13.     std::cout << val;
  14. }
  15.  
  16. template <typename T, typename... Ts>
  17. void log(T&& arg, Ts&&... args) {
  18.     log(arg);
  19.     log(args...);
  20. }
  21.  
  22.  
  23. // Ассерт
  24. void assert_impl(bool cond, const char* msg, const char* file, const char* func, int line) {
  25.     if (!cond) {
  26.         std::cerr << "Fatal error:\n" << file << ":" << line << " " << func << "(): ";
  27.         std::cerr << "\t" << msg << std::endl;
  28.         exit(1);
  29.     }
  30. }
  31.  
  32. #define ASSERT(condition, message) assert_impl(condition, message, __FILE__, __FUNCTION__, __LINE__)
  33.  
  34.  
  35.  
  36.  
  37. // Класс для просмотра строк. (Не владеет ресурсом, только предоставляет к нему доступ)
  38. class StringViewer {
  39.     friend class CircularQueue;
  40.    
  41. public:
  42.     // Методы взятия одного символа по индексу
  43.     virtual       char& at(unsigned pos)       { return ptr[pos]; }  
  44.     virtual const char& at(unsigned pos) const { return ptr[pos]; }
  45.    
  46.     // Метод получения размера строки
  47.     virtual unsigned length() const { return size; }
  48.    
  49.     // Метод вывода на экран
  50.     virtual void print(std::ostream& os = std::cout) const { os << ptr; }
  51.    
  52.     // Оператор << ostream
  53.     friend std::ostream& operator<<(std::ostream& os, const StringViewer& sv) { sv.print(os); }
  54.    
  55. protected:
  56.     // Конструктор объявлен защищенным, т.к. объект может быть создан только в friend классе CircularQueue
  57.     StringViewer(char* iPtr, unsigned iSize): ptr(iPtr), size(iSize) {}
  58.    
  59.     char*    ptr;  // Начало строки
  60.     unsigned size; // Размер строки
  61. };
  62.  
  63. // Класс для просмотра разорванных в памяти строк. Наследник StringViewer
  64. class StringViewerDivide : public StringViewer {
  65.     friend class CircularQueue;
  66.    
  67. public:
  68.     // Методы взятия одного символа по индексу
  69.     virtual char& at(unsigned pos) {
  70.         return pos < size ? ptr[pos] : ptr2[pos - size];
  71.     }
  72.     virtual const char& at(unsigned pos) const {
  73.         return pos < size ? ptr[pos] : ptr2[pos - size];
  74.     }
  75.    
  76.     // Метод получения размера строки
  77.     virtual unsigned length() const { return size + size2; }
  78.    
  79.     // Метод вывода на экран
  80.     virtual void print(std::ostream& os = std::cout) const {
  81.         os << ptr << ptr2;
  82.     }
  83.    
  84. protected:
  85.     // Конструктор объявлен защищенным, т.к. объект может быть создан только в friend классе CircularQueue
  86.     StringViewerDivide(char* ptr1, unsigned size1, char* iptr2, unsigned isize2):
  87.             StringViewer(ptr1, size1), ptr2(iptr2), size2(isize2) {}
  88.            
  89.     char*    ptr2;  // Начало второй части строки
  90.     unsigned size2; // Размер второй части
  91. };
  92.  
  93.  
  94. // Кольцевая очередь
  95. class CircularQueue {
  96. private:
  97.     struct Node {
  98.         Node(char* iPtr, unsigned iSize): ptr(iPtr), size(iSize) {}
  99.                
  100.         Node*    next = nullptr;
  101.         Node*    prev = nullptr;
  102.        
  103.         char*    ptr;
  104.         unsigned size;
  105.     };
  106.    
  107.     unsigned max_size;     // Размер выделенного блока памяти
  108.     char*    mem;          // Начало блока
  109.     char*    mem_end;      // Конец блока
  110.     char*    space_start;  // Начало свободного пространства
  111.     char*    space_end;    // Конец свободного пространства
  112.     unsigned space_size;   // Размер свободного пространства в байтах
  113.    
  114.     Node*    head = nullptr;    // Голова очереди
  115.     Node*    tail = nullptr;    // Хвост очереди
  116.     unsigned missed_nodes = 0;  // Количество потерянный узлов
  117.    
  118.    
  119.     // Уменьшает свободное пространство на заданную величину
  120.     void incrSpaceStart(unsigned value) {
  121.         space_start += value;
  122.         if (space_start >= mem_end)
  123.             space_start = mem + (space_start - mem_end);
  124.         space_size -= value;
  125.     }
  126.    
  127.     // Увеличивает свободное пространство на заданную величину
  128.     void incrSpaceEnd(unsigned value) {
  129.         space_end += value;
  130.         if (space_end > mem_end)
  131.             space_end = mem + (space_end - mem_end);
  132.         space_size += value;
  133.     }
  134.    
  135.     // Возвращает объект StringViewer или StringViewerDivide в зависимости от того, разорвана ли строка
  136.     StringViewer unpack_node(Node* node) {
  137.         if (node) {
  138.             if (node->ptr + node->size > mem_end)
  139.                 return StringViewerDivide(node->ptr, mem_end - node->ptr, mem, node->size - (mem_end - node->ptr));
  140.             else
  141.                 return StringViewer(node->ptr, node->size);
  142.         } else
  143.             return StringViewer(nullptr, 0);
  144.     }
  145.    
  146. public:    
  147.     CircularQueue(unsigned bytes_size):
  148.             max_size   (bytes_size),
  149.             mem        (new char[max_size + 1]), // +1 for null-terminator
  150.             mem_end    (mem + max_size),
  151.             space_start(mem),
  152.             space_end  (mem_end),
  153.             space_size (max_size)
  154.     {
  155.         ASSERT(max_size != 0, "Попытка задания нулевого размера.");
  156.         mem[max_size] = '\0';
  157.     }
  158.            
  159.            
  160.     ~CircularQueue() {
  161.         clear();
  162.         delete [] mem;
  163.     }
  164.    
  165.    
  166.     // Добавляет элемент в конец очереди
  167.     void push(const char* str) {
  168.         unsigned strSize = strlen(str) + 1; // null terminator
  169.        
  170.         ASSERT(strSize <= max_size, "Попытка добавления элемента большего, чем выделенный участок памяти");
  171.            
  172.         // Удаляем элементы, пока не хватит памяти
  173.         while (space_size < strSize) {
  174.             log("[[FORCE]]");
  175.             ++missed_nodes;
  176.             pop();
  177.         }
  178.        
  179.         Node* node = nullptr;
  180.        
  181.         if (space_start + strSize > mem_end) {
  182.             log("[push divided element]: ", "strsize = ", strSize, " freeMemory = ", space_size, "\n");
  183.             unsigned  backSize = mem_end - space_start;
  184.             unsigned frontSize = strSize - backSize;
  185.            
  186.             memcpy(space_start, str, backSize);
  187.             node = new Node(space_start, strSize);
  188.             incrSpaceStart(backSize);
  189.            
  190.             memcpy(space_start, str + backSize, frontSize);
  191.             incrSpaceStart(frontSize);
  192.            
  193.         } else {
  194.             log("[push element]:         ", "strsize = ", strSize, " freeMemory = ", space_size, "\n");
  195.             memcpy(space_start, str, strSize);
  196.             node = new Node(space_start, strSize);
  197.             incrSpaceStart(strSize);
  198.         }
  199.        
  200.         node->next = tail;
  201.         if (tail)
  202.             tail->prev = node;
  203.         tail = node;
  204.        
  205.         if (head == nullptr)
  206.             head = tail;
  207.     }
  208.    
  209.     // Удаляет первый элемент очереди
  210.     void pop() {
  211.         if (head) {
  212.             log("[pop element]:          ", "strsize = ", head->size, " freeMemory = ", space_size, "\n");
  213.             incrSpaceEnd(head->size);
  214.            
  215.             Node* prev = head->prev;
  216.            
  217.             if (prev)
  218.                 prev->next = nullptr;
  219.            
  220.             delete head;
  221.             head = prev;
  222.            
  223.             if (!head)
  224.                 tail = nullptr;
  225.         }
  226.     }
  227.    
  228.     // Очистит очередь
  229.     void clear() { while(head) pop(); }
  230.    
  231.     // Вернет первый элемент в очереди
  232.     StringViewer front() { return unpack_node(head); }
  233.    
  234.     // Вернет последний элемент в очереди
  235.     StringViewer back () { return unpack_node(tail); }
  236.    
  237.     // Вернет количество элементов в очереди
  238.     unsigned size() {
  239.         unsigned res = 0;
  240.         Node* node   = head;
  241.        
  242.         while (node) {
  243.             ++res;
  244.             node = node->prev;
  245.         }
  246.        
  247.         return res;
  248.     }
  249.    
  250.     // Вернет кол-во потерянных элементов
  251.     unsigned missed() { return missed_nodes; }
  252.    
  253.    
  254.     // Выведет на экран представление строк в памяти
  255.     // # - это space_start
  256.     // $ - это space_end
  257.     // @ - когда вся память свободна и они совпадают
  258.     // . - терминирующий ноль у строк
  259.     void memdump() {
  260.         char* memstr = new char[max_size + 2];
  261.         memset(memstr, '_', max_size + 1);
  262.         memstr[max_size + 1] = '\0';
  263.        
  264.         Node* node = head;
  265.        
  266.         while (node) {
  267.             if (node->ptr + node->size > mem_end) {
  268.                 memcpy(memstr + (node->ptr - mem), node->ptr, mem_end - node->ptr);
  269.                 memcpy(memstr, mem, node->size - (mem_end - node->ptr));
  270.             } else {
  271.                 memcpy(memstr + (node->ptr - mem), node->ptr, node->size);
  272.             }
  273.             node = node->prev;
  274.         }
  275.        
  276.         if (space_start == space_end)
  277.             memstr[space_start - mem] = '@';
  278.         else {
  279.             memstr[space_start - mem] = '#';
  280.             memstr[space_end - mem] = '$';
  281.         }
  282.            
  283.         for (int i = 0; i < max_size; ++i)
  284.             if (memstr[i] == '\0')
  285.                 memstr[i] = '.';
  286.            
  287.         std::cout << memstr << std::endl;
  288.         delete [] memstr;
  289.     }
  290. };
  291.  
  292.  
  293.  
  294.  
  295. // Random Strings
  296.  
  297. std::array<const char*, 11> strings = {
  298.     "AAAAAAAAAAAAAA",
  299.     "BBBBBBBBBBBB",
  300.     "CCCCCCCCC",
  301.     "DDDDDDDDDDDDDDDDDDDDDD",
  302.     "EEEEEEEEEEEEEEEEEE",
  303.     "FFFFFFFFFFFFFFFF",
  304.     "GGGGGGGGGGGG",
  305.     "HHHHHHHHHHHHHHHHH",
  306.     "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
  307.     "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ",
  308.     "KKK"
  309. };
  310.  
  311.  
  312. std::mt19937 mt(clock());
  313. std::uniform_int_distribution<unsigned> uid(0, 10); // Кол-во строк
  314. auto gen = std::bind(uid, mt);
  315.  
  316. const char* random_string() {
  317.     return strings[gen()];
  318. }
  319.  
  320.  
  321.  
  322.  
  323. int main() {
  324.     CircularQueue queue(1024);    
  325.     unsigned test_iter = 200;
  326.    
  327.    
  328.     for (int i = 0; i < test_iter; ++i) {
  329.         queue.push(random_string());
  330.         queue.memdump();
  331.         queue.pop();
  332.     }
  333.    
  334.     for (int i = 0; i < test_iter; ++i) {
  335.         queue.memdump();
  336.         queue.push(random_string());
  337.     }
  338.    
  339.     for (int i = 0; i < test_iter; ++i)
  340.         queue.pop();
  341.    
  342.     queue.memdump();
  343.    
  344.     return 0;
  345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement