comparison dowa/d_memory.c @ 72:4532ce6d9eb8

[Seobeo] Added router to the server logic. Few dowa string manipulation logics.
author June Park <parkjune1995@gmail.com>
date Mon, 29 Dec 2025 07:50:07 -0800
parents 75de5903355c
children d39e8860a361
comparison
equal deleted inserted replaced
71:75de5903355c 72:4532ce6d9eb8
24 void *Dowa_Arena_Allocate(Dowa_Arena *p_arena, size_t size) 24 void *Dowa_Arena_Allocate(Dowa_Arena *p_arena, size_t size)
25 { 25 {
26 return Dowa_Arena_Allocate_Aligned(p_arena, size, sizeof(void*) * 2); 26 return Dowa_Arena_Allocate_Aligned(p_arena, size, sizeof(void*) * 2);
27 } 27 }
28 28
29 void Dowa_Arena_Destroy(Dowa_Arena *p_arena) 29 void Dowa_Arena_Free(Dowa_Arena *p_arena)
30 { 30 {
31 if (!p_arena) return; 31 if (!p_arena)
32 return;
32 33
33 if (p_arena->buffer) 34 if (p_arena->buffer)
34 Dowa_Free(p_arena->buffer); 35 Dowa_Free(p_arena->buffer);
35 Dowa_Free(p_arena); 36 Dowa_Free(p_arena);
36 } 37 }
631 return 0; 632 return 0;
632 633
633 Dowa_Hash_Index* p_index = dowa__hashmap_get_index(p_map); 634 Dowa_Hash_Index* p_index = dowa__hashmap_get_index(p_map);
634 return p_index ? p_index->item_count : 0; 635 return p_index ? p_index->item_count : 0;
635 } 636 }
636
637 /*
638 // --- OLD HashMap Implementation (Commented out for migration) --- //
639 Dowa_HashMap *Dowa_HashMap_Create(size_t capacity)
640 {
641 Dowa_HashMap *p_hash_map;
642 p_hash_map = malloc(sizeof(Dowa_HashMap));
643 if (p_hash_map == NULL)
644 {
645 return NULL;
646 }
647 p_hash_map->entries = calloc(capacity, sizeof(*p_hash_map->entries));
648 if (p_hash_map->entries == NULL)
649 {
650 Dowa_Free(p_hash_map);
651 return NULL;
652 }
653 p_hash_map->capacity = capacity;
654 p_hash_map->current_capacity = 0;
655 p_hash_map->p_arena = NULL;
656 return p_hash_map;
657 }
658
659 Dowa_HashMap *Dowa_HashMap_Create_With_Arena(size_t capacity, Dowa_Arena *p_arena)
660 {
661 if (p_arena == NULL)
662 {
663 printf("Arena is NULL\n");
664 return Dowa_HashMap_Create(capacity);
665 }
666
667 Dowa_HashMap *p_hash_map;
668 p_hash_map = Dowa_Arena_Allocate(p_arena, sizeof(Dowa_HashMap));
669 if (p_hash_map == NULL)
670 {
671 return NULL;
672 }
673 p_hash_map->entries = Dowa_Arena_Allocate(p_arena, sizeof(*p_hash_map->entries) * capacity);
674 if (p_hash_map->entries == NULL)
675 {
676 return NULL;
677 }
678 memset(p_hash_map->entries, 0, capacity * sizeof *p_hash_map->entries);
679 p_hash_map->capacity = capacity;
680 p_hash_map->current_capacity = 0;
681 p_hash_map->p_arena = p_arena;
682 return p_hash_map;
683 }
684
685 void Dowa_HashMap_Destroy(Dowa_HashMap *p_hash_map)
686 {
687 if (!p_hash_map) return;
688
689 if (p_hash_map->p_arena)
690 {
691 // Free arena instead of the map...
692 // Dowa_Arena_Destroy(p_hash_map->p_arena);
693 return;
694 }
695 else
696 {
697 Dowa_HashEntry *entry;
698 Dowa_HashEntry *next;
699 if (p_hash_map->entries)
700 {
701 for (int idx=0; idx<p_hash_map->capacity; idx++)
702 {
703 entry = p_hash_map->entries[idx];
704 while (entry)
705 {
706 next = entry->next;
707 Dowa_Free(entry->key);
708 Dowa_Free(entry->buffer);
709 Dowa_Free(entry);
710 entry = next;
711 }
712 }
713 }
714 Dowa_Free(p_hash_map->entries);
715 }
716 Dowa_Free(p_hash_map);
717 }
718
719 int32 Dowa_HashMap_Get_Position(Dowa_HashMap *p_hash_map, const char *key)
720 {
721 if (!p_hash_map || !key)
722 return -1;
723
724 int32 hash_val = HASH_KEY_NUMBER;
725 int32 c;
726 while ((c = *key++))
727 {
728 hash_val = (hash_val << 5) + hash_val + c;
729 }
730 return hash_val % p_hash_map->capacity;
731 }
732
733 void *Dowa_HashMap_Get(Dowa_HashMap *p_hash_map, const char *key)
734 {
735 if (!p_hash_map || !key)
736 return NULL;
737
738 int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
739 Dowa_HashEntry *entry = p_hash_map->entries[idx];
740
741 while (entry)
742 {
743 if (strcmp(entry->key, key) == 0)
744 {
745 return entry->buffer;
746 }
747 entry = entry->next;
748 }
749
750 return NULL;
751 }
752
753
754 int32 Dowa_HashMap_Push_Value_With_Type_NoCopy(Dowa_HashMap *p_hash_map, const char *key,
755 void *value, size_t value_size,
756 Dowa_HashMap_ValueType type)
757 {
758 if (!p_hash_map || !key || !value)
759 return -1;
760
761 int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
762 Dowa_HashEntry *entry = p_hash_map->entries[idx];
763 Dowa_HashEntry *prev = NULL;
764
765 // Old key
766 while (entry)
767 {
768 if (strcmp(entry->key, key) == 0)
769 {
770 // Fails if it the key exists...
771 return -1;
772 }
773 prev = entry;
774 entry = entry->next;
775 }
776
777 // New Key
778 entry = p_hash_map->p_arena ?
779 Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) :
780 malloc(sizeof(Dowa_HashEntry));
781 if (!entry) { perror("malloc or arena alloc"); return -1; }
782
783 entry->key = p_hash_map->p_arena ?
784 Dowa_Arena_Copy(p_hash_map->p_arena, key, strlen(key) + 1) :
785 strdup(key);
786 if (!entry->key)
787 {
788 perror("strdup or arena copy");
789 if (!p_hash_map->p_arena) Dowa_Free(entry);
790 return -1;
791 }
792 entry->buffer = value;
793 entry->capacity = value_size;
794 entry->type = type;
795 entry->next = NULL;
796
797 if (prev)
798 prev->next = entry;
799 else
800 p_hash_map->entries[idx] = entry;
801
802 p_hash_map->current_capacity++;
803 return 0;
804 }
805
806 int32 Dowa_HashMap_Push_Value_With_Type(Dowa_HashMap *p_hash_map, const char *key,
807 void *value, size_t value_size,
808 Dowa_HashMap_ValueType type)
809 {
810 if (!p_hash_map || !key || !value)
811 return -1;
812
813 int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
814 Dowa_HashEntry *entry = p_hash_map->entries[idx];
815 Dowa_HashEntry *prev = NULL;
816
817 // Check for existing key
818 while (entry)
819 {
820 if (strcmp(entry->key, key) == 0)
821 {
822 if (!p_hash_map->p_arena && entry->buffer)
823 Dowa_Free(entry->buffer);
824
825 entry->buffer = p_hash_map->p_arena ?
826 Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) :
827 malloc(value_size);
828 if (!entry->buffer) { perror("malloc or arena alloc"); return -1; }
829
830 memcpy(entry->buffer, value, value_size);
831 entry->capacity = value_size;
832 entry->type = type;
833 return 0;
834 }
835 prev = entry;
836 entry = entry->next;
837 }
838
839 // New Key
840 entry = p_hash_map->p_arena ?
841 Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) :
842 malloc(sizeof(Dowa_HashEntry));
843 if (!entry) { perror("malloc or arena alloc"); return -1; }
844
845 entry->key = p_hash_map->p_arena ?
846 Dowa_Arena_Copy(p_hash_map->p_arena, key, strlen(key) + 1) :
847 strdup(key);
848 if (!entry->key) { perror("strdup"); return -1; }
849
850 entry->buffer = p_hash_map->p_arena ?
851 Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) :
852 malloc(value_size);
853 if (!entry->buffer) { perror("malloc or arena alloc"); return -1; }
854
855 memcpy(entry->buffer, value, value_size);
856 entry->capacity = value_size;
857 entry->type = type;
858 entry->next = NULL;
859
860 if (prev)
861 prev->next = entry;
862 else
863 p_hash_map->entries[idx] = entry;
864
865 p_hash_map->current_capacity++;
866 return 0;
867 }
868
869 void Dowa_HashMap_Push_Value(Dowa_HashMap *p_hash_map, const char *key, void *value, size_t value_size)
870 {
871 Dowa_HashMap_Push_Value_With_Type(p_hash_map, key, value, value_size, DOWA_HASH_MAP_TYPE_BUFFER);
872 }
873
874 void Dowa_HashMap_Pop_Key(Dowa_HashMap *p_hash_map, const char *key)
875 {
876 if (!p_hash_map || !key)
877 return;
878
879 int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
880 Dowa_HashEntry *entry = p_hash_map->entries[idx];
881 Dowa_HashEntry *prev = NULL;
882
883 while (entry)
884 {
885 if (strcmp(entry->key, key) == 0)
886 {
887 if (prev)
888 prev->next = entry->next;
889 else
890 p_hash_map->entries[idx] = entry->next;
891
892 if (!(p_hash_map->p_arena))
893 {
894 Dowa_Free(entry->key);
895 Dowa_Free(entry->buffer);
896 Dowa_Free(entry);
897 }
898
899 if (p_hash_map->current_capacity > 0)
900 p_hash_map->current_capacity--;
901 return;
902 }
903 prev = entry;
904 entry = entry->next;
905 }
906 }
907
908 boolean Dowa_HashMap_Has_Key(Dowa_HashMap *p_hash_map, const char *key)
909 {
910 if (!p_hash_map || !key)
911 return FALSE;
912
913 int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
914 Dowa_HashEntry *entry = p_hash_map->entries[idx];
915
916 while (entry)
917 {
918 if (strcmp(entry->key, key) == 0)
919 return TRUE;
920 entry = entry->next;
921 }
922
923 return FALSE;
924 }
925
926 void Dowa_HashMap_Clear(Dowa_HashMap *p_hash_map)
927 {
928 if (!p_hash_map) return;
929
930 if (p_hash_map->p_arena)
931 {
932 for (int idx=0; idx<p_hash_map->capacity; idx++)
933 p_hash_map->entries[idx] = NULL;
934 }
935 else
936 {
937 Dowa_HashEntry *entry;
938 Dowa_HashEntry *next;
939 if (p_hash_map->entries)
940 {
941 for (int idx=0; idx<p_hash_map->capacity; idx++)
942 {
943 entry = p_hash_map->entries[idx];
944 while (entry)
945 {
946 next = entry->next;
947 Dowa_Free(entry->key);
948 Dowa_Free(entry->buffer);
949 Dowa_Free(entry);
950 entry = next;
951 }
952 p_hash_map->entries[idx] = NULL;
953 }
954 }
955 }
956 p_hash_map->current_capacity = 0;
957 }
958
959 uint32 Dowa_HashMap_Get_Count(Dowa_HashMap *p_hash_map)
960 {
961 if (!p_hash_map) return 0;
962 return p_hash_map->current_capacity;
963 }
964
965 void Dowa_HashMap_Print(Dowa_HashMap *map)
966 {
967 if (!map)
968 {
969 printf("HashMap is NULL\n");
970 return;
971 }
972
973 printf("\n-----------\n\n");
974 for (size_t i = 0; i < map->capacity; ++i)
975 {
976 Dowa_HashEntry *e = map->entries[i];
977 while (e)
978 {
979 if (!e) break;
980 printf("%s: ", e->key);
981 switch (e->type)
982 {
983 case DOWA_HASH_MAP_TYPE_BUFFER:
984 {
985 unsigned char *p = e->buffer;
986 for (size_t j = 0; j < e->capacity; ++j)
987 {
988 printf("%02x", p[j]);
989 }
990 printf("\n");
991 }
992 break;
993 case DOWA_HASH_MAP_TYPE_STRING:
994 {
995 printf("%.*s\n", (int)e->capacity, (char*)e->buffer);
996 }
997 break;
998 case DOWA_HASH_MAP_TYPE_HASHMAP:
999 {
1000 printf("This is a hashmap with size of %zu, and pointer %p\n", e->capacity, (void *)e);
1001 }
1002 break;
1003 case DOWA_HASH_MAP_TYPE_INT:
1004 {
1005 printf("%d\n", *(int32*)e->buffer);
1006 }
1007 break;
1008 default:
1009 {
1010 printf("<unknown type>\n");
1011 }
1012 }
1013 e = e->next;
1014 }
1015 }
1016 printf("-----------\n");
1017 }
1018
1019 // -- Array --//
1020 Dowa_Array *Dowa_Array_Init()
1021 {
1022 Dowa_Array *dowa_array = malloc(sizeof(Dowa_Array));
1023 if (dowa_array == NULL)
1024 {
1025 return NULL;
1026 }
1027
1028 dowa_array->capacity = DOWA_ARRAY_DEFAULT_CAPACITY;
1029 dowa_array->items = (Dowa_Array_Item *)malloc(sizeof(Dowa_Array_Item) * DOWA_ARRAY_DEFAULT_CAPACITY);
1030 if (dowa_array->items == NULL)
1031 {
1032 return NULL;
1033 }
1034
1035 dowa_array->current_length = 0;
1036 return dowa_array;
1037 }
1038
1039 // void Dowa_Array_Push_Value(Dowa_Array *dowa_array, void *buffer, uint32 length)
1040 // {
1041 // if (dowa_array->current_length == dowa_array->capacity)
1042 // {
1043 // dowa_array->items = realloc(dowa_array->items, sizeof(Dowa_Array_Item) * dowa_array->capacity * 2);
1044 // dowa_array->capacity = dowa_array->capacity * 2;
1045 // }
1046 // Dowa_Array_Item *item = &(dowa_array->items[dowa_array->current_length]);
1047 // item->value = malloc(length);
1048 // if (item->value == NULL)
1049 // {
1050 // // didn't alloc should raise an error.
1051 // return;
1052 // }
1053 // memcpy(item->value, buffer, length);
1054 // item->length = length;
1055 // dowa_array->current_length += 1;
1056 // }
1057
1058
1059 #ifdef DIRECTORY
1060 int Dowa_HashMap_Cache_Folder(Dowa_HashMap *p_hash_map, const char *folder_path)
1061 {
1062 if (!p_hash_map || !folder_path)
1063 return -1;
1064
1065 DIR *dir = opendir(folder_path);
1066 if (!dir) { perror("opendir"); return -1; }
1067
1068 struct dirent *entry;
1069 while ((entry = readdir(dir)))
1070 {
1071 // skip "." and ".."
1072 if (entry->d_name[0] == '.' &&
1073 (entry->d_name[1] == '\0' ||
1074 (entry->d_name[1] == '.' && entry->d_name[2] == '\0')))
1075 continue;
1076
1077 char fullpath[PATH_MAX];
1078 snprintf(fullpath, sizeof fullpath, "%s/%s", folder_path, entry->d_name);
1079
1080 struct stat st;
1081 if (stat(fullpath, &st) < 0) { perror("stat"); continue; }
1082
1083 if (S_ISREG(st.st_mode))
1084 {
1085 size_t size = (size_t)st.st_size;
1086 FILE *f = fopen(fullpath, "rb");
1087 if (!f) { perror("fopen"); continue; }
1088
1089 // Allocate exact file size (no extra byte for null terminator)
1090 void *buf = p_hash_map->p_arena ?
1091 Dowa_Arena_Allocate(p_hash_map->p_arena, size) :
1092 malloc(size);
1093 if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; }
1094
1095 if (fread(buf, 1, size, f) != size)
1096 {
1097 perror("fread");
1098 if (!p_hash_map->p_arena) Dowa_Free(buf);
1099 fclose(f);
1100 continue;
1101 }
1102 fclose(f);
1103
1104 // Store file data as-is without null terminator (for binary files like images)
1105 Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING);
1106 if (!p_hash_map->p_arena)
1107 Dowa_Free(buf); // Dowa_HashMap_PushValue made its own copy
1108 }
1109 else if (S_ISDIR(st.st_mode))
1110 {
1111 // TODO: Adjust the sizes of the recursive map?
1112 Dowa_HashMap *p_child_map = Dowa_HashMap_Create_With_Arena(100, p_hash_map->p_arena);
1113 if (!p_child_map)
1114 {
1115 perror("Dowa_HashMap_Create");
1116 return -1;
1117 }
1118 if (Dowa_HashMap_Cache_Folder(p_child_map, fullpath) == -1)
1119 {
1120 perror("Dowa_HashMap_Cache_Folder");
1121 return -1;
1122 }
1123
1124 // Should not copy as we malloced already.
1125 if (Dowa_HashMap_Push_Value_With_Type_NoCopy(p_hash_map, entry->d_name, p_child_map,
1126 sizeof(p_child_map), DOWA_HASH_MAP_TYPE_HASHMAP) == -1)
1127 {
1128 Dowa_HashMap_Destroy(p_child_map);
1129 return -1;
1130 }
1131 }
1132 }
1133 closedir(dir);
1134 return 0;
1135 }
1136 #endif
1137 */