void SLAB_Free(const struct Allocator* a, void* mem) { if (mem) { struct SMem_Header *header = (struct SMem_Header *) MEM2HEADER(mem); if(header_check(header, SLAB_USED_MAGIC)) { header->smagic = SLAB_FREE_MAGIC; if (header->level) { _atomic_stack_push(&header->level->stk, &header->item); _atomic_cnt_dec(&header->level->used); } else { #ifndef __amigaos4__ FreeVec(header); #else IExec->FreeVec(header); #endif } } } }
/** * Add header line to the `headers' hash for specified field name. * A private copy of the `field' name and of the `text' data is made. */ static void add_header(header_t *o, const char *field, const char *text) { htable_t *ht; str_t *v; header_check(o); ht = header_get_table(o); v = htable_lookup(ht, field); if (v) { /* * Header already exists, according to RFC2616 we need to append * the value, comma-separated. */ STR_CAT(v, ", "); str_cat(v, text); } else { char *key; /* * Create a new header entry in the hash table. */ key = h_strdup(field); v = str_new_from(text); htable_insert(ht, key, v); } }
/** * Take an extra reference on the header object. * @return the header object. */ header_t * header_refcnt_inc(header_t *o) { header_check(o); o->refcnt++; return o; }
static GHashTable * header_get_table(header_t *o) { header_check(o); if (!o->headers) o->headers = g_hash_table_new(ascii_strcase_hash, ascii_strcase_eq); return o->headers; }
/** * Reset header object, for new header parsing. */ void header_reset(header_t *o) { header_check(o); if (o->headers != NULL) { htable_foreach_remove(o->headers, free_header_data, NULL); htable_free_null(&o->headers); } slist_free_all(&o->fields, cast_to_free_fn(hfield_free)); o->flags = o->size = o->num_lines = 0; }
static htable_t * header_get_table(header_t *o) { header_check(o); if (NULL == o->headers) { o->headers = htable_create_any(ascii_strcase_hash, NULL, ascii_strcase_eq); } return o->headers; }
/** * Reset header object, for new header parsing. */ void header_reset(header_t *o) { header_check(o); if (o->headers) { g_hash_table_foreach_remove(o->headers, free_header_data, NULL); gm_hash_table_destroy_null(&o->headers); } slist_free_all(&o->fields, cast_to_slist_destroy(hfield_free)); o->flags = o->size = o->num_lines = 0; }
/** * Add continuation line to the `headers' hash for specified field name. * A private copy of the data is made. */ static void add_continuation(header_t *o, const char *field, const char *text) { str_t *v; header_check(o); g_assert(o->headers); v = htable_lookup(o->headers, field); g_assert(v != NULL); str_putc(v, ' '); str_cat(v, text); }
/** * Dump whole header on specified file, followed by trailer string * (if not NULL) and a final "\n". */ void header_dump(FILE *out, const header_t *o, const char *trailer) { header_check(o); if (!log_file_printable(out)) return; if (o->fields) { slist_foreach(o->fields, header_dump_item, out); } if (trailer) fprintf(out, "%s\n", trailer); }
/** * Get field value, or NULL if not present. The value returned is a * pointer to the internals of the header structure, so it must not be * kept around. */ char * header_get(const header_t *o, const char *field) { str_t *v; header_check(o); if (o->headers) { v = htable_lookup(o->headers, deconstify_char(field)); } else { v = NULL; } return str_2c(v); }
/** * Destroy header object. */ void header_free(header_t *o) { header_check(o); if (o->refcnt > 1) { o->refcnt--; return; } header_reset(o); o->magic = 0; WFREE(o); }
/** * Get field value, or NULL if not present. The value returned is a * pointer to the internals of the header structure, so it must not be * kept around. * * If the len_ptr pointer is not NULL, it is filled with the length * of the header string. */ char * header_get_extended(const header_t *o, const char *field, size_t *len_ptr) { str_t *v; header_check(o); if (o->headers) { v = htable_lookup(o->headers, deconstify_char(field)); } else { v = NULL; } if (v && len_ptr != NULL) { *len_ptr = str_len(v); } return str_2c(v); }
void* SLAB_Alloc(const struct Allocator* s, size_t bytes) { void* res = 0; struct SLAB_Allocator *sa = (struct SLAB_Allocator*)s; if (bytes) { struct SLAB_Level *sl = level_classify(sa, bytes); if (sl) { struct SMem_Header *header; header = (struct SMem_Header*)_atomic_stack_pop(&sl->stk); if (header && header_check(header, SLAB_FREE_MAGIC)) { _atomic_cnt_inc(&sl->used); header->smagic = SLAB_USED_MAGIC; res = HEADER2MEM(header); } else { #ifndef __amigaos4__ header = (struct SMem_Header*)AllocVec(bytes + sizeof(struct SMem_Header), MEMF_PUBLIC); #else header = (struct SMem_Header*)IExec->AllocVec(bytes + sizeof(struct SMem_Header), MEMF_PUBLIC); #endif if(header) { _atomic_item_init(&header->item); header->smagic = SLAB_USED_MAGIC; header->level = 0; res = HEADER2MEM(header); } } } } /* End */ return(res); }
/** * Append a new line of text at the end of the header. * A private copy of the text is made. * * @return an error code, or HEAD_OK if appending was successful. */ int header_append(header_t *o, const char *text, int len) { char buf[MAX_LINE_SIZE]; const char *p = text; uchar c; header_field_t *hf; header_check(o); g_assert(len >= 0); if (o->flags & HEAD_F_EOH) return HEAD_EOH_REACHED; /* * If empty line, we reached EOH. */ if (len == 0) { o->flags |= HEAD_F_EOH; /* Mark we reached EOH */ return HEAD_EOH; } /* * Sanity checks. */ if (o->size >= HEAD_MAX_SIZE) return HEAD_TOO_LARGE; if (++(o->num_lines) >= HEAD_MAX_LINES) return HEAD_MANY_LINES; /* * Detect whether line is a new header or a continuation. */ c = *p; if (is_ascii_space(c)) { /* * It's a continuation. * * Make sure we already have recorded something, or we have * an unexpected continuation line. */ if (NULL == o->fields) return HEAD_CONTINUATION; /* Unexpected continuation */ /* * When a previous header line was malformed, we cannot accept * further continuation lines. */ if (o->flags & HEAD_F_SKIP) return HEAD_SKIPPED; /* * We strip leading spaces of all continuations before storing * them. If we have to dump the header, we will have to put * some spaces, but we don't guarantee we'll put the same amount. */ p++; /* First char is known space */ while ((c = *p)) { if (!is_ascii_space(c)) break; p++; } /* * If we've reached the end of the line, then the continuation * line was made of spaces only. Weird, but we can ignore it. * Note that it's not an EOH mark. */ if (*p == '\0') return HEAD_OK; /* * Save the continuation line by appending into the last header * field we handled. */ hf = slist_tail(o->fields); hfield_append(hf, p); add_continuation(o, hf->name, p); o->size += len - (p - text); /* Count only effective text */ /* * Also append the data in the hash table. */ } else { char *b; bool seen_space = FALSE; /* * It's a new header line. */ o->flags &= ~HEAD_F_SKIP; /* Assume this line will be OK */ /* * Parse header field. Must be composed of ascii chars only. * (no control characters, no space, no ISO Latin or other extension). * The field name ends with ':', after possible white spaces. */ for (b = buf, c = *p; c; c = *(++p)) { if (c == ':') { *b++ = '\0'; /* Reached end of field */ break; /* Done, buf[] holds field name */ } if (is_ascii_space(c)) { seen_space = TRUE; /* Only trailing spaces allowed */ continue; } if ( seen_space || (c != '-' && c != '.' && (!isascii(c) || is_ascii_cntrl(c) || is_ascii_punct(c))) ) { o->flags |= HEAD_F_SKIP; return HEAD_BAD_CHARS; } *b++ = c; } /* * If buf[] does not end with a NUL, we did not fully recognize * the header: we reached the end of the line without encountering * the ':' marker. * * If the buffer starts with a NUL char, it's also clearly malformed. */ g_assert(b > buf || (b == buf && *text == '\0')); if (b == buf || *(b-1) != '\0') { o->flags |= HEAD_F_SKIP; return HEAD_MALFORMED; } /* * We have a valid header field in buf[]. */ hf = hfield_make(buf); /* * Strip leading spaces in the value. */ g_assert(*p == ':'); p++; /* First char is field separator */ p = skip_ascii_spaces(p); /* * Record field value. */ hfield_append(hf, p); add_header(o, buf, p); if (!o->fields) { o->fields = slist_new(); } slist_append(o->fields, hf); o->size += len - (p - text); /* Count only effective text */ } return HEAD_OK; }