summaryrefslogtreecommitdiff
path: root/upb_fieldmap.c
blob: 015b2e14f2f522943624b0c5874604dc8314ee4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*
 * upb - a minimalist implementation of protocol buffers.
 *
 * Copyright (c) 2009 Joshua Haberman.  See LICENSE for details.
 */

#include "upb_fieldmap.h"

#include <stdlib.h>

void pbstream_init_fieldmap(struct pbstream_fieldmap *fieldmap,
                            struct pbstream_field *fields,
                            int num_fields)
{
  qsort(fields, num_fields, sizeof(*fields), compare_fields);

  /* Find the largest n for which at least half the fieldnums <n are used.
   * Start at 8 to avoid noise of small numbers. */
  pbstream_field_number_t n = 0, maybe_n;
  for(int i = 0; i < num_fields; i++) {
    maybe_n = fields[i].field_number;
    if(maybe_n > 8 && maybe_n/(i+1) >= 2) break;
    n = maybe_n;
  }

  fieldmap->num_fields = num_fields;
  fieldmap->fields = malloc(sizeof(*fieldmap->fields)*num_fields);
  memcpy(fieldmap->fields, fields, sizeof(*fields)*num_fields);

  fieldmap->array_size = n;
  fieldmap->array = malloc(sizeof(*fieldmap->array)*n);
  memset(fieldmap->array, 0, sizeof(*fieldmap->array)*n);

  for (int i = 0; i < num_fields && fields[i].field_number <= n; i++)
    fieldmap->array[fields[i].field_number-1] = &fieldmap->fields[i];

  /* Until we support the hashtable part... */
  assert(n == fields[num_fields-1].field_number);
}

void pbstream_free_fieldmap(struct pbstream_fieldmap *fieldmap)
{
  free(fieldmap->fields);
  free(fieldmap->array);
}

/* Emit definition for inline function. */
extern void *upb_fieldmap_find(struct upb_fieldmap *fm,
                               pbstream_field_number_t num,
                               size_t info_size);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback