summaryrefslogtreecommitdiff
path: root/ot_vector.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_vector.c')
-rw-r--r--ot_vector.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/ot_vector.c b/ot_vector.c
index 924d468..a56d55b 100644
--- a/ot_vector.c
+++ b/ot_vector.c
@@ -57,34 +57,39 @@ static uint8_t vector_hash_peer(ot_peer const *peer, size_t compare_size, size_t
57*/ 57*/
58void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch) { 58void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch) {
59 uint8_t *match = vector_binary_search(key, vector->data, vector->size, member_size, compare_size, exactmatch); 59 uint8_t *match = vector_binary_search(key, vector->data, vector->size, member_size, compare_size, exactmatch);
60 size_t match_offset, bytes_after;
60 61
61 if (*exactmatch) 62 if (*exactmatch)
62 return match; 63 return match;
63 64
65 /* Hold the insertion point as an offset rather than a pointer: it survives
66 the realloc below, and an empty vector has no data pointer to offset from
67 in the first place */
68 match_offset = vector->size ? (size_t)(match - (uint8_t *)vector->data) : 0;
69 bytes_after = member_size * vector->size - match_offset;
70
64 if (vector->size + 1 > vector->space) { 71 if (vector->size + 1 > vector->space) {
65 size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; 72 size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS;
66 ptrdiff_t match_off = match - (uint8_t *)vector->data; 73 uint8_t *new_data = realloc(vector->data, new_space * member_size);
67 uint8_t *new_data = realloc(vector->data, new_space * member_size);
68 74
69 if (!new_data) 75 if (!new_data)
70 return NULL; 76 return NULL;
71 77
72 /* Adjust pointer if it moved by realloc */
73 match = new_data + match_off;
74
75 vector->data = new_data; 78 vector->data = new_data;
76 vector->space = new_space; 79 vector->space = new_space;
77 } 80 }
78 memmove(match + member_size, match, ((uint8_t *)vector->data) + member_size * vector->size - match); 81
82 match = (uint8_t *)vector->data + match_offset;
83 memmove(match + member_size, match, bytes_after);
79 84
80 vector->size++; 85 vector->size++;
81 return match; 86 return match;
82} 87}
83 88
84ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch) { 89ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch) {
85 ot_peer *match, *end; 90 ot_peer *match;
86 const size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); 91 const size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size);
87 size_t match_to_end; 92 size_t match_offset, bytes_after;
88 93
89 /* If space is zero but size is set, we're dealing with a list of vector->size buckets */ 94 /* If space is zero but size is set, we're dealing with a list of vector->size buckets */
90 if (vector->space < vector->size) 95 if (vector->space < vector->size)
@@ -94,26 +99,26 @@ ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size
94 if (*exactmatch) 99 if (*exactmatch)
95 return match; 100 return match;
96 101
97 /* This is the amount of bytes that needs to be pushed backwards by peer_size bytes to make room for new peer */ 102 /* Hold the insertion point as an offset rather than a pointer: it survives
98 end = (ot_peer *)vector->data + vector->size * peer_size; 103 the realloc below, and an empty vector has no data pointer to offset from
99 match_to_end = end - match; 104 in the first place. bytes_after is what has to move up by peer_size to
105 make room for the new peer */
106 match_offset = vector->size ? (size_t)(match - (ot_peer *)vector->data) : 0;
107 bytes_after = vector->size * peer_size - match_offset;
100 108
101 if (vector->size + 1 > vector->space) { 109 if (vector->size + 1 > vector->space) {
102 ptrdiff_t offset = match - (ot_peer *)vector->data; 110 size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS;
103 size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; 111 ot_peer *new_data = realloc(vector->data, new_space * peer_size);
104 ot_peer *new_data = realloc(vector->data, new_space * peer_size);
105 112
106 if (!new_data) 113 if (!new_data)
107 return NULL; 114 return NULL;
108 /* Adjust pointer if it moved by realloc */
109 match = new_data + offset;
110 115
111 vector->data = new_data; 116 vector->data = new_data;
112 vector->space = new_space; 117 vector->space = new_space;
113 } 118 }
114 119
115 /* Here we're guaranteed to have enough space in vector to move the block of peers after insertion point */ 120 match = (ot_peer *)vector->data + match_offset;
116 memmove(match + peer_size, match, match_to_end); 121 memmove(match + peer_size, match, bytes_after);
117 122
118 vector->size++; 123 vector->size++;
119 return match; 124 return match;
@@ -150,11 +155,13 @@ int vector_remove_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size)
150} 155}
151 156
152void vector_remove_torrent(ot_vector *vector, ot_torrent *match) { 157void vector_remove_torrent(ot_vector *vector, ot_torrent *match) {
153 ot_torrent *end = ((ot_torrent *)vector->data) + vector->size; 158 ot_torrent *end;
154 159
155 if (!vector->size) 160 if (!vector->size)
156 return; 161 return;
157 162
163 end = ((ot_torrent *)vector->data) + vector->size;
164
158 free_peerlist(match->peer_list6); 165 free_peerlist(match->peer_list6);
159 free_peerlist(match->peer_list4); 166 free_peerlist(match->peer_list4);
160 167