/** * Convert the XML input to INFO output. */ int process(FILE* is, FILE* os) { struct state_t state; char buf[4096]; state.parser = XML_ParserCreate(NULL); if (!state.parser) { fprintf(stderr, "Couldn't allocate memory for parser\n"); return -1; } state.depth = -1; state.os = os; state.error = 0; container_alloc(&state.game_map, &state.game_mac, &state.game_max); container_alloc(&state.reference_map, &state.reference_mac, &state.reference_max); XML_SetUserData(state.parser, &state); XML_SetElementHandler(state.parser, start_handler, end_handler); XML_SetCharacterDataHandler(state.parser, data_handler); while (1) { int done; int len; len = fread(buf, 1, sizeof(buf), is); if (ferror(is)) { process_error(&state, "", "read error"); break; } done = feof(is); if (XML_Parse(state.parser, buf, len, done) == XML_STATUS_ERROR) { process_error(&state, "", XML_ErrorString(XML_GetErrorCode(state.parser))); break; } if (done) break; } XML_ParserFree(state.parser); if (state.error) { return -1; } if (check(&state) != 0) { return -1; } container_free(&state.game_map, &state.game_mac, &state.game_max); container_free(&state.reference_map, &state.reference_mac, &state.reference_max); return 0; }
static ssize_t data_container_t_free(data_t *data, fastcall_free *fargs){ // {{{ if(data->ptr == NULL) return -EINVAL; container_free((container_t *)data->ptr); return 0; } // }}}
///////////////// // everything skipped over is freed int32_t ra_advance_until_freeing(roaring_array_t *ra, uint16_t x, int32_t pos) { while (pos < ra->size && ra->keys[pos] < x) { container_free(ra->containers[pos], ra->typecodes[pos]); ++pos; } return pos; }
// Reverse operation of alloc_ptbl. // Removes corresponding page directory entry, // and frees the page for the page table entries (with container_free). void free_ptbl(unsigned int proc_index, unsigned int vadr) { // TODO unsigned int pde; pde = get_pdir_entry_by_va(proc_index, vadr); rmv_pdir_entry_by_va(proc_index, vadr); container_free(proc_index, pde / PAGESIZE); }
void ra_remove_at_index(roaring_array_t *ra, int32_t i) { container_free(ra->containers[i], ra->typecodes[i]); memmove(&(ra->containers[i]), &(ra->containers[i + 1]), sizeof(void *) * (ra->size - i - 1)); memmove(&(ra->keys[i]), &(ra->keys[i + 1]), sizeof(uint16_t) * (ra->size - i - 1)); memmove(&(ra->typecodes[i]), &(ra->typecodes[i + 1]), sizeof(uint8_t) * (ra->size - i - 1)); ra->size--; }
void shared_container_free (shared_container_t * container) { assert(container->counter > 0); container->counter--; if(container->counter == 0) { assert(container->typecode != SHARED_CONTAINER_TYPE_CODE); container_free(container->container,container->typecode); container->container = NULL; // paranoid free(container); } }
static void ra_clear(roaring_array_t *ra) { free(ra->keys); ra->keys = NULL; // paranoid for (int i = 0; i < ra->size; ++i) { container_free(ra->containers[i], ra->typecodes[i]); } free(ra->containers); ra->containers = NULL; // paranoid free(ra->typecodes); ra->typecodes = NULL; // paranoid }
roaring_array_t *ra_copy(roaring_array_t *r, bool copy_on_write) { roaring_array_t *new_ra = malloc(sizeof(roaring_array_t)); if (!new_ra) return NULL; new_ra->keys = NULL; new_ra->containers = NULL; new_ra->typecodes = NULL; const int32_t allocsize = r->allocation_size; new_ra->allocation_size = allocsize; new_ra->keys = malloc(allocsize * sizeof(uint16_t)); new_ra->containers = calloc(allocsize, sizeof(void *)); // setting pointers to zero new_ra->typecodes = malloc(allocsize * sizeof(uint8_t)); if (!new_ra->keys || !new_ra->containers || !new_ra->typecodes ) { free(new_ra); free(new_ra->keys); free(new_ra->containers); free(new_ra->typecodes); return NULL; } int32_t s = r->size; new_ra->size = s; memcpy(new_ra->keys, r->keys, s * sizeof(uint16_t)); // we go through the containers, turning them into shared containers... if(copy_on_write) { for(int32_t i = 0; i < s; ++i) { r->containers[i] = get_copy_of_container(r->containers[i], &r->typecodes[i], copy_on_write); } // we do a shallow copy to the other bitmap memcpy(new_ra->containers, r->containers, s * sizeof(void *)); memcpy(new_ra->typecodes, r->typecodes, s * sizeof(uint8_t)); } else { memcpy(new_ra->typecodes, r->typecodes, s * sizeof(uint8_t)); for (int32_t i = 0; i < s; i++) { new_ra->containers[i] = container_clone(r->containers[i], r->typecodes[i]); if (new_ra->containers[i] == NULL) { for (int32_t j = 0; j < i; j++) { container_free(r->containers[j], r->typecodes[j]); } free(new_ra); free(new_ra->keys); free(new_ra->containers); free(new_ra->typecodes); return NULL; } } } return new_ra; }
// this function consumes and frees the inputs static roaring_bitmap_t *lazy_or_from_lazy_inputs(roaring_bitmap_t *x1, roaring_bitmap_t *x2) { uint8_t container_result_type = 0; const int length1 = ra_get_size(&x1->high_low_container), length2 = ra_get_size(&x2->high_low_container); if (0 == length1) { roaring_bitmap_free(x1); return x2; } if (0 == length2) { roaring_bitmap_free(x2); return x1; } uint32_t neededcap = length1 > length2 ? length2 : length1; roaring_bitmap_t *answer = roaring_bitmap_create_with_capacity(neededcap); int pos1 = 0, pos2 = 0; uint8_t container_type_1, container_type_2; uint16_t s1 = ra_get_key_at_index(&x1->high_low_container, pos1); uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, pos2); while (true) { if (s1 == s2) { // todo: unsharing can be inefficient as it may create a clone where // none // is needed, but it has the benefit of being easy to reason about. ra_unshare_container_at_index(&x1->high_low_container, pos1); void *c1 = ra_get_container_at_index(&x1->high_low_container, pos1, &container_type_1); assert(container_type_1 != SHARED_CONTAINER_TYPE_CODE); ra_unshare_container_at_index(&x2->high_low_container, pos2); void *c2 = ra_get_container_at_index(&x2->high_low_container, pos2, &container_type_2); assert(container_type_2 != SHARED_CONTAINER_TYPE_CODE); void *c; if ((container_type_2 == BITSET_CONTAINER_TYPE_CODE) && (container_type_1 != BITSET_CONTAINER_TYPE_CODE)) { c = container_lazy_ior(c2, container_type_2, c1, container_type_1, &container_result_type); container_free(c1, container_type_1); if (c != c2) { container_free(c2, container_type_2); } } else { c = container_lazy_ior(c1, container_type_1, c2, container_type_2, &container_result_type); container_free(c2, container_type_2); if (c != c1) { container_free(c1, container_type_1); } } // since we assume that the initial containers are non-empty, the // result here // can only be non-empty ra_append(&answer->high_low_container, s1, c, container_result_type); ++pos1; ++pos2; if (pos1 == length1) break; if (pos2 == length2) break; s1 = ra_get_key_at_index(&x1->high_low_container, pos1); s2 = ra_get_key_at_index(&x2->high_low_container, pos2); } else if (s1 < s2) { // s1 < s2 void *c1 = ra_get_container_at_index(&x1->high_low_container, pos1, &container_type_1); ra_append(&answer->high_low_container, s1, c1, container_type_1); pos1++; if (pos1 == length1) break; s1 = ra_get_key_at_index(&x1->high_low_container, pos1); } else { // s1 > s2 void *c2 = ra_get_container_at_index(&x2->high_low_container, pos2, &container_type_2); ra_append(&answer->high_low_container, s2, c2, container_type_2); pos2++; if (pos2 == length2) break; s2 = ra_get_key_at_index(&x2->high_low_container, pos2); } } if (pos1 == length1) { ra_append_move_range(&answer->high_low_container, &x2->high_low_container, pos2, length2); } else if (pos2 == length2) { ra_append_move_range(&answer->high_low_container, &x1->high_low_container, pos1, length1); } ra_clear_without_containers(&x1->high_low_container); ra_clear_without_containers(&x2->high_low_container); free(x1); free(x2); return answer; }
roaring_array_t *ra_deserialize(const void *buf, uint32_t buf_len) { int32_t size; const char *bufaschar = (const char *)buf; memcpy(&size, bufaschar, sizeof(int32_t)); roaring_array_t *ra_copy; uint32_t off, l; uint32_t expected_len = sizeof(roaring_array_t) + size * (sizeof(uint16_t) + sizeof(void *) + sizeof(uint8_t)); if (buf_len < expected_len) return (NULL); if ((ra_copy = (roaring_array_t *)malloc(sizeof(roaring_array_t))) == NULL) return (NULL); memcpy(ra_copy, bufaschar, off = sizeof(roaring_array_t)); if ((ra_copy->keys = malloc(size * sizeof(uint16_t))) == NULL) { free(ra_copy); return (NULL); } if ((ra_copy->containers = malloc(size * sizeof(void *))) == NULL) { free(ra_copy->keys); free(ra_copy); return (NULL); } if ((ra_copy->typecodes = malloc(size * sizeof(uint8_t))) == NULL) { free(ra_copy->containers); free(ra_copy->keys); free(ra_copy); return (NULL); } l = size * sizeof(uint16_t); memcpy(ra_copy->keys, &bufaschar[off], l); off += l; l = size * sizeof(void *); memcpy(ra_copy->containers, &bufaschar[off], l); off += l; l = size * sizeof(uint8_t); memcpy(ra_copy->typecodes, &bufaschar[off], l); off += l; for (int32_t i = 0; i < size; i++) { uint16_t len; memcpy(&len, &bufaschar[off], sizeof(len)); off += sizeof(len); ra_copy->containers[i] = container_deserialize(ra_copy->typecodes[i], &bufaschar[off], len); if (ra_copy->containers[i] == NULL) { for (int32_t j = 0; j < i; j++) container_free(ra_copy->containers[j], ra_copy->typecodes[j]); free(ra_copy->containers); free(ra_copy->keys); free(ra_copy); return (NULL); } off += len; } return (ra_copy); }
char *ra_serialize(roaring_array_t *ra, uint32_t *serialize_len, uint8_t *retry_with_array) { uint32_t off, l, cardinality = 0, tot_len = 1 /* initial byte type */ +4 /* tot_len */ + sizeof(roaring_array_t) + ra->size * (sizeof(uint16_t) + sizeof(void *) + sizeof(uint8_t)); char *out; uint16_t *lens; (*retry_with_array) = 0; /* [ 32 bit length ] [ serialization bytes ] */ if ((lens = (uint16_t *)malloc(sizeof(int16_t) * ra->size)) == NULL) { *serialize_len = 0; return (NULL); } for (int32_t i = 0; i < ra->size; i++) { lens[i] = container_serialization_len(ra->containers[i], ra->typecodes[i]); assert(lens[i] != 0); tot_len += (lens[i] + sizeof(lens[i])); cardinality += container_get_cardinality(ra->containers[i], ra->typecodes[i]); } if ((cardinality * sizeof(uint32_t)) < tot_len) { *retry_with_array = 1; free(lens); return (NULL); } out = (char *)malloc(tot_len); if (out == NULL) { free(lens); *serialize_len = 0; return (NULL); } else *serialize_len = tot_len; /* Leave room for the first byte */ out[0] = SERIALIZATION_CONTAINER, off = 1; /* Total lenght (first 4 bytes of the serialization) */ memcpy(out + off, &tot_len, 4), off += 4; l = sizeof(roaring_array_t); uint32_t saved_allocation_size = ra->allocation_size; ra->allocation_size = ra->size; memcpy(&out[off], ra, l); ra->allocation_size = saved_allocation_size; off += l; l = ra->size * sizeof(uint16_t); memcpy(&out[off], ra->keys, l); off += l; l = ra->size * sizeof(void *); memcpy(&out[off], ra->containers, l); off += l; l = ra->size * sizeof(uint8_t); memcpy(&out[off], ra->typecodes, l); off += l; for (int32_t i = 0; i < ra->size; i++) { int32_t serialized_bytes; memcpy(&out[off], &lens[i], sizeof(lens[i])); off += sizeof(lens[i]); serialized_bytes = container_serialize(ra->containers[i], ra->typecodes[i], &out[off]); if (serialized_bytes != lens[i]) { for (int32_t j = 0; j <= i; j++) container_free(ra->containers[j], ra->typecodes[j]); free(lens); free(out); assert(serialized_bytes != lens[i]); return (NULL); } off += serialized_bytes; } if (tot_len != off) { assert(tot_len != off); } free(lens); return (out); }