sav

Sorting Algorithms Visualized
Index Commits Files Refs README LICENSE
commit a6b64c306862bb9c28ace0137833170204d6dbcb
parent 6663dcd6c28d26681d8363b1f84febff26b96ae2
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Sat, 16 Apr 2022 01:16:54 -0300

Fixed high memory usage, added UNHEX macro

The high memory usage was caused by not freeing the surface and texture
of the status bar text; now in every main loop iteration the a surface
and texture is created to draw the statusbar then its freen and
reallocated in the next iteration.

Minor updates on the code has been done as well.

Diffstat:
MMakefile | 11+++++------
Mdrw.c | 95+++++++++++++++++++++++++++++++++++--------------------------------------------
Mmain.c | 9+++++++--
Msort.c | 84++++++++++++++++++++++++++++---------------------------------------------------
Mutil.h | 6++++++
5 files changed, 90 insertions(+), 115 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,9 +1,8 @@
-CC := cc
-CLIBS := `sdl2-config --libs --cflags`
-CFLAGS := -lSDL2_ttf -lm -Werror -pedantic -ansi -std=c99 -pthread
-SRCS := main.c sav.c util.c sort.c drw.c sdl_extra.c array.c
+CC := gcc
+CLIBS := `sdl2-config --libs` -lSDL2_ttf -lm
+CFLAGS := `sdl2-config --cflags` -Wall -Wshadow -pedantic -ansi -std=c99 -pthread
+SRCS := $(wildcard *.c)
 OBJS := $(SRCS:.c=.o)
-LIBS := array.h status.h
 
 TARGET := sav
 
@@ -11,7 +10,7 @@ TARGET := sav
 
 all: $(TARGET) clean
 
-$(TARGET): $(OBJS) $(HEADERS) $(LIBS)
+$(TARGET): $(OBJS) $(HEADERS)
     $(CC) $(CLIBS) $(CFLAGS) -o $@ $^
 
 %.o: %.c
diff --git a/drw.c b/drw.c
@@ -1,46 +1,37 @@
 #include "drw.h"
 
-void drw_element_color(Drw *drw, int x, int y, int h, unsigned int col) {
-    SDL_Rect rect;
-    unsigned char r, g, b, a;
+static SDL_Rect rect;
 
+void drw_element_color(Drw *drw, int x, int y, int h, unsigned int col) {
     rect.x = x + drw->x_border; /* bottom left + x */
     rect.y = y - drw->y_border; /* bottom */
     rect.w = RECT_WIDTH; /* fixed width */
     rect.h = -h;
 
-    r = (char)(col >> 24) & 0xFF;
-    g = (char)(col >> 16) & 0xFF;
-    b = (char)(col >> 8) & 0xFF;
-    a = (char)(col) & 0xFF;
-
-    SDL_RenderDrawRect(drw->rend, &rect);
-    SDL_SetRenderDrawColor(drw->rend, r, g, b, a);
+    /* SDL_RenderDrawRect(drw->rend, &rect); */
+    SDL_SetRenderDrawColor(drw->rend, UNHEX(col));
     SDL_RenderFillRect(drw->rend, &rect);
 
-    SDL_SetRenderDrawColor(drw->rend, 0, 0, 0, 0);
-    SDL_RenderDrawLine(drw->rend, x + drw->x_border, y - drw->y_border, x + drw->x_border, y - drw->y_border - h);
+    /* printf("INFO: color: #%02X%02X%02X%02X\n", UNHEX(col)); */
+
+    SDL_SetRenderDrawColor(drw->rend, UNHEX(0x000000FF));
+    SDL_RenderDrawLine(drw->rend,
+                        x + drw->x_border, y - drw->y_border,
+                        x + drw->x_border, y - drw->y_border - h);
 }
 
 void drw_array_graph(Drw *drw, SAV *sav) {
-    int x, w, h;
-
-    SDL_GetWindowSize(drw->win, &w, &h);
-
-    SDL_SetRenderDrawColor(drw->rend, 29, 28, 28, 0);
-    SDL_RenderClear(drw->rend);
+    int x;
 
     size_t i;
     for(i = x = 0; i < sav->arr->len; i++, x += RECT_WIDTH) {
-        if(i == sav->sel) drw_element_color(drw, x, h, sav->arr->v[i], SEL_COLOR);
-        else if(i == sav->cmp) drw_element_color(drw, x, h, sav->arr->v[i], CMP_COLOR);
-        else drw_element_color(drw, x, h, sav->arr->v[i], NORM_COLOR);
+        if(i == sav->sel) drw_element_color(drw, x, drw->h, sav->arr->v[i], SEL_COLOR);
+        else if(i == sav->cmp) drw_element_color(drw, x, drw->h, sav->arr->v[i], CMP_COLOR);
+        else drw_element_color(drw, x, drw->h, sav->arr->v[i], NORM_COLOR);
     }
-    drw_status_bar(drw, sav);
 }
 
 void drw_status_bar(Drw *drw, SAV *sav) {
-    SDL_Rect rect;
     int bar_border = 2;
 
     rect.x = bar_border; /* top left + x */
@@ -48,44 +39,39 @@ void drw_status_bar(Drw *drw, SAV *sav) {
     rect.w = drw->w - (2 * bar_border); /* fixed width */
     rect.h = -BAR_HEIGHT;
 
-    SDL_RenderDrawRect(drw->rend, &rect);
+    /* SDL_RenderDrawRect(drw->rend, &rect); */
 
     /* TODO: Make a variable to store statusbar background color */
-    SDL_SetRenderDrawColor(drw->rend, 0, 0, 0, 0); /* RGBA */
+    SDL_SetRenderDrawColor(drw->rend, UNHEX(0x000000FF)); /* RGBA */
     SDL_RenderFillRect(drw->rend, &rect);
 
-    if((sav->status == RUN) || (sav->status == UPDATE) || (sav->status == START) || sav->status == WELCOME) {
-        if(sav->sort_status == SORTED) {
+    /* TODO: create a function which fetchs the status text to be drawn based on the status */
+    if(sav->sort_status == SORTED) {
+        snprintf(drw->bar_text, drw->bar_text_len - 2,
+                "SORTED [%s sort] done in %.2fs, L: %ld, C: %ld, S: %ld, extra storage used: %ld Bytes",
+                algo_strings[sav->sort_algo],
+                (double)(sav->tf - sav->ti) / CLOCKS_PER_SEC,
+                sav->arr->len, sav->cmps, sav->swps, sav->B_used);
+    } else if(sav->sort_status == PAUSE) {
+        if(sav->status == START) {
             snprintf(drw->bar_text, drw->bar_text_len - 2,
-                    "SORTED (%s sort) done in %.2fs, L: %ld, C: %ld, S: %ld, extra storage used: %ld Bytes",
-                    algo_strings[sav->sort_algo],
-                    (double)(sav->tf - sav->ti) / CLOCKS_PER_SEC,
-                    sav->arr->len, sav->cmps, sav->swps, sav->B_used);
-        } else if(sav->sort_status == PAUSE) {
-            if(sav->status == START) {
-                snprintf(drw->bar_text, drw->bar_text_len - 2,
-                        "(%s sort selected) press SPACE to start sorting",
-                        algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
-                        sav->swps);
-            } else if(sav->status == WELCOME) {
-                snprintf(drw->bar_text, drw->bar_text_len - 2,
-                        "Welcome to sorting algorithms visualized - (%s sort selected) press SPACE to start sorting",
-                        algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
-                        sav->swps);
-            } else {
-                snprintf(drw->bar_text, drw->bar_text_len - 2,
-                        "PAUSED (%s sort) press SPACE to resume",
-                        algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
-                        sav->swps);
-            }
+                    "[%s sort selected] press SPACE to start sorting",
+                    algo_strings[sav->sort_algo]);
+        } else if(sav->status == WELCOME) {
+            snprintf(drw->bar_text, drw->bar_text_len - 2,
+                    "Welcome to sorting algorithms visualized - [%s sort selected] press SPACE to start sorting",
+                    algo_strings[sav->sort_algo]);
         } else {
             snprintf(drw->bar_text, drw->bar_text_len - 2,
-                    "SORTING (%s sort)     L: %ld, C: %ld, S: %ld",
-                    algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
-                    sav->swps);
+                    "PAUSED [%s sort] press SPACE to resume", algo_strings[sav->sort_algo]);
         }
-        drw_text(drw, drw->bar_text, 0, drw->h - drw->font_size - 5);
+    } else {
+        snprintf(drw->bar_text, drw->bar_text_len - 2,
+                "SORTING [%s sort]     L: %ld, C: %ld, S: %ld",
+                algo_strings[sav->sort_algo], sav->arr->len, sav->cmps,
+                sav->swps);
     }
+    drw_text(drw, drw->bar_text, 0, drw->h - drw->font_size - 5);
     memset(drw->bar_text, 0, sizeof(char) * drw->bar_text_len);
 }
 
@@ -99,6 +85,8 @@ void drw_text(Drw *drw, char *text, int x, int y) {
     drw->bar_text_rect.h = drw->text_surface->h;
 
     SDL_RenderCopy(drw->rend, drw->text_texture, NULL, &drw->bar_text_rect);
+    SDL_DestroyTexture(drw->text_texture);
+    SDL_FreeSurface(drw->text_surface);
 }
 
 status_t Drw_new(Drw **drw) {
@@ -110,6 +98,7 @@ status_t Drw_new(Drw **drw) {
         return ERROR_MEMORY_ALLOC;
 
     SDL_setup(&win, &rend);
+
     (*drw)->rend = rend;
     (*drw)->win = win;
 
@@ -148,7 +137,7 @@ status_t Drw_new(Drw **drw) {
     {
         int w_text, h_text;
         TTF_SizeText(font,
-                "SORTED (XXXXXXXXXXs sort) done in XXX.Xs, L: XXXXX,\
+                "SORTED [XXXXXXXXXXs sort] done in XXX.Xs, L: XXXXX,\
                 C: XXXXXX, S: XXXXXX, I: XXXXXX, storage used: XXXXXX Bytes",
                 &w_text, &h_text);
 
diff --git a/main.c b/main.c
@@ -9,6 +9,7 @@
 
 #define WELCOME_MSG_TIME 5
 
+/* TODO: sorting algorithms should only keep track of sav->sort_status and not sav->status */
 /* TODO: support restart even if the sorting algorithm didn't finish */
 
 void check_events(Drw *, SAV *);
@@ -39,7 +40,7 @@ int main (void) {
     /* assigns random values to array */
     shuffle(sav->arr);
 
-    /* selecting the sorting algorithms */
+    /* selecting the sorting algorithm */
     sav->sort_algo = QUICK_SORT;
 
     /* TODO: this thread should be called if the user wants to begin sorting the array */
@@ -53,6 +54,10 @@ int main (void) {
     /* main loop */
     while(sav->status != STOP) {
         check_events(drw, sav);
+
+        SDL_SetRenderDrawColor(drw->rend, 29, 28, 28, 0);
+        SDL_RenderClear(drw->rend);
+
         drw_array_graph(drw, sav);
         drw_status_bar(drw, sav);
         SDL_RenderPresent(drw->rend);
@@ -82,6 +87,7 @@ int main (void) {
 
 void check_events(Drw *drw, SAV *sav) {
     SDL_Event event;
+
     while (SDL_PollEvent(&event)) {
         switch(event.type) {
         case SDL_QUIT:
@@ -117,4 +123,3 @@ void check_events(Drw *drw, SAV *sav) {
         }
     }
 }
-
diff --git a/sort.c b/sort.c
@@ -6,14 +6,33 @@
 
 #define DELAY    5
 
+status_t sort_wait(SAV *sav) {
+    size_t i;
+
+    /* Delay */
+    for(i = 0; i < DELAY; i++) {
+        if((sav->sort_status == STOP) || (sav->status == STOP))
+            return STOP;
+
+        SDL_Delay(1);
+    }
+
+    while(sav->sort_status == PAUSE);
+
+    return OK;
+}
+
 void insertion_sort(SAV *sav) {
     int key;
     size_t i, j;
 
+    if(sav == NULL) return;
+
     if((sav->sort_status == STOP) || (sav->status == STOP)) return;
     while(sav->sort_status == PAUSE);
 
     sav->ti = clock();
+
     for(i = 1; i < sav->arr->len; i++, sav->its++) {
         sav->cmps += 1;
         key = sav->arr->v[i];
@@ -26,31 +45,14 @@ void insertion_sort(SAV *sav) {
             sav->sel = i;
             sav->cmp = j;
             sav->its++;
-
-            /* Delay */
-            for(size_t i = 0; i < DELAY; i++) {
-                if((sav->sort_status == STOP) || (sav->status == STOP))
-                    goto end;
-
-                SDL_Delay(1);
-            }
-            while(sav->sort_status == PAUSE);
         }
         sav->arr->v[j + 1] = key;
         sav->sel = i;
         sav->cmp = j;
         sav->swps += 1;
 
-        /* Delay */
-        for(size_t i = 0; i < DELAY; i++) {
-            if((sav->sort_status == STOP) || (sav->status == STOP))
-                goto end;
-
-            SDL_Delay(1);
-        }
-        while(sav->sort_status == PAUSE);
+        if(sort_wait(sav) == STOP) break;
     }
-    end:
 
     sav->tf = clock();
 
@@ -60,6 +62,8 @@ void insertion_sort(SAV *sav) {
 void bubble_sort(SAV *sav) {
     size_t i, j;
 
+    if(sav == NULL) return;
+
     if((sav->sort_status == STOP) || (sav->status == STOP)) return;
     while(sav->sort_status == PAUSE);
 
@@ -73,25 +77,9 @@ void bubble_sort(SAV *sav) {
                 swap(sav->arr->v + j, sav->arr->v+j+1);
                 sav->swps += 1;
             }
-
-            /* Delay */
-            for(size_t i = 0; i < DELAY; i++) {
-                if((sav->sort_status == STOP) || (sav->status == STOP))
-                    goto end;
-
-                SDL_Delay(1);
-            }
-            while(sav->sort_status == PAUSE);
+            if(sort_wait(sav) == STOP) goto end;
         }
-
-        /* Delay */
-        for(size_t i = 0; i < DELAY; i++) {
-            if((sav->sort_status == STOP) || (sav->status == STOP))
-                goto end;
-
-            SDL_Delay(1);
-        }
-        while(sav->sort_status == PAUSE);
+        if(sort_wait(sav) == STOP) goto end;
     }
     end:
 
@@ -130,15 +118,7 @@ void merge(SAV *sav, int low, int middle, int high) {
         sav->cmps += 1;
         sav->its += 1;
 
-        while(sav->sort_status == PAUSE);
-
-        /* Delay */
-        for(size_t i = 0; i < DELAY; i++) {
-            if((sav->sort_status == STOP) || (sav->status == STOP))
-                goto end;
-
-            SDL_Delay(1);
-        }
+        if(sort_wait(sav) == STOP) goto end;
     }
     end:
 
@@ -147,8 +127,6 @@ void merge(SAV *sav, int low, int middle, int high) {
 }
 
 void merge_sort(SAV *sav, int low, int high) {
-    if(sav == NULL) return;
-
     if((sav->sort_status == STOP) || (sav->status == STOP))
         return;
 
@@ -172,6 +150,8 @@ void merge_sort(SAV *sav, int low, int high) {
 }
 
 void merge_sort_wrapper(SAV *sav) {
+    if(sav == NULL) return;
+
     sav->ti = clock();
     merge_sort(sav, 0, sav->arr->len);
     sav->tf = clock();
@@ -192,13 +172,7 @@ void quick_sort_partition(SAV *sav, int low, int *middle, int high) {
             sav->swps += 1;
         }
 
-        if(sav->status != STOP) sav->status = UPDATE;
-        while(sav->sort_status == PAUSE);
-
-        for(size_t i = 0; i < 5; i++) {
-            if(sav->sort_status == STOP) goto end;
-            SDL_Delay(1);
-        }
+        if(sort_wait(sav) == STOP) goto end;
     }
     end:
 
@@ -221,6 +195,8 @@ void quick_sort(SAV *sav, int low, int high) {
 }
 
 void quick_sort_wrapper(SAV *sav) {
+    if(sav == NULL) return;
+
     sav->ti = clock();
     quick_sort(sav, 0, sav->arr->len - 1);
     printf("SORT: sorting array done\n");
diff --git a/util.h b/util.h
@@ -6,6 +6,12 @@
 
 #include "status.h"
 
+#define UNHEX(color) \
+    ((color) >> (8 * 3)) & 0xFF, \
+    ((color) >> (8 * 2)) & 0xFF, \
+    ((color) >> (8 * 1)) & 0xFF, \
+    ((color) >> (8 * 0)) & 0xFF
+
 void end(const char *msg);
 void swap(int *a, int *b);
 void wait_main_thread(status_t *st);