#include "fieldmap.h"
#include <algorithm>
using namespace std;
namespace {
vector<unsigned int> find_packed_fields(vector<unsigned int> &all_fields) {
sort(all_fields.begin(), all_fields.end());
int last_included = -1;
for (int i = 0, max = all_fields.size(); i < max; ++i) {
if (all_fields[i] < 70) {
last_included = i;
continue;
}
// the load factor also counts the unused "0" entry
int load_factor = (i + 1) * 100 / (all_fields[i] + 1);
if (load_factor > 75) {
last_included = i;
}
}
all_fields.resize(last_included + 1);
return all_fields;
}
}
void gpd::FieldMapImpl::add(pTHX_ SV *name, unsigned int number, void *field) {
PerlString key;
key.fill(aTHX_ name);
by_name[key] = field;
by_number[number] = field;
}
void gpd::FieldMapImpl::optimize_lookup() {
vector<unsigned int> all_ids;
for (typename NumberMap::const_iterator it = by_number.begin(), en = by_number.end(); it != en; ++it)
all_ids.push_back(it->first);
vector<unsigned int> packed_ids = find_packed_fields(all_ids);
if (packed_ids.size() > 0) {
top_packed_field = packed_ids.back();
packed_by_number.resize(top_packed_field + 1);
for (std::vector<unsigned int>::const_iterator it = packed_ids.begin(), en = packed_ids.end(); it != en; ++it) {
packed_by_number[*it] = by_number[*it];
by_number.erase(*it);
}
}
}
void *gpd::FieldMapImpl::find_by_name(pTHX_ SV *name) const {
PerlString key;
key.fill(aTHX_ name);
return find_by_name(key);
}
void *gpd::FieldMapImpl::find_by_name(pTHX_ HE *he) const {
PerlString key;
key.fill(aTHX_ he);
return find_by_name(key);
}
void *gpd::FieldMapImpl::find_by_name(pTHX_ const char *name, STRLEN namelen) const {
PerlString key;
key.fill(aTHX_ name, namelen);
return find_by_name(key);
}