Mercurial
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 */ |