// WordKeyInfo.cc
//
// Part of the ht://Dig package
// Copyright (c) 1999-2004 The ht://Dig Group
// For copyright details, see the file COPYING in your distribution
// or the GNU Library General Public License (LGPL) version 2 or later
//
//
//
#ifdef HAVE_CONFIG_H
#include "htconfig.h"
#endif /* HAVE_CONFIG_H */
#include
#include
#include "WordKeyInfo.h"
#include "StringList.h"
#define WORDKEYFIELD_BITS_MAX 64
//
// WordKeyField implementation
//
int WordKeyField::SetNum(WordKeyField *previous, char *nname, int nbits)
{
type = WORD_ISA_NUMBER;
name.set(nname, strlen(nname));
bits = nbits;
bits_offset = (previous ? previous->bits_offset + previous->bits : 0 );
if(bits_offset < 0 ||
bits_offset > WORDKEYFIELD_BITS_MAX*WORD_KEY_MAX_NFIELDS) {
fprintf(stderr, "WordKeyField::WordKeyField: bits_offset: %d out of bounds\n", bits_offset);
return EINVAL;
}
bytes_offset = bits_offset / 8;
bytesize = ((bits_offset + bits - 1) / 8) - bytes_offset + 1;
lastbits = (bits_offset + bits) % 8;
lowbits = bits_offset % 8;
return 0;
}
int WordKeyField::SetString()
{
name.set("Word");
type = WORD_ISA_STRING;
return 0;
}
//
// Tabulate for printing
//
static void nprint(char c, int n)
{
for(int i = 0; i < n; i++) {
if(!(i % 4)) {
printf("%c", 'a' + i / 4);
} else {
printf("%c", c);
}
}
}
//
// Print object on standard output
//
void
WordKeyField::Show()
{
if(!name.nocase_compare("Word")) {
printf("Word type: %2d\n", type);
} else {
nprint(' ',bits_offset);
printf("\"%s\" type:%2d lowbits:%2d lastbits:%2d\n",
(char *)name,
type,
lowbits,
lastbits);
nprint(' ',bits_offset);
printf("|---bytesize:%2d bytes_offset:%2d bits:%2d bits_offset:%2d\n", bytesize, bytes_offset, bits, bits_offset);
}
}
//
// WordKeyInfo implementation
//
WordKeyInfo* WordKeyInfo::instance = 0;
WordKeyInfo::WordKeyInfo(const Configuration& config)
{
sort = NULL;
nfields = -1;
num_length = 0;
const String &keydesc = config["wordlist_wordkey_description"];
if(!keydesc.empty()) {
Set(keydesc);
} else {
fprintf(stderr, "WordKeyInfo::WordKeyInfo: didn't find key description in config\n");
}
}
void
WordKeyInfo::Initialize(const Configuration &config_arg)
{
if(instance != 0)
delete instance;
instance = new WordKeyInfo(config_arg);
}
void
WordKeyInfo::InitializeFromString(const String &desc)
{
Configuration config;
config.Add("wordlist_wordkey_description", desc);
Initialize(config);
}
int
WordKeyInfo::Alloc(int nnfields)
{
nfields = nnfields;
if(!(sort = new WordKeyField[nfields])) {
fprintf(stderr, "WordKeyInfo::Alloc: cannot allocate\n");
return ENOMEM;
}
num_length = 0;
return 0;
}
int
WordKeyInfo::Set(const String &desc)
{
int ret = 0;
StringList fields(desc, "/");
if(fields.Count() > WORD_KEY_MAX_NFIELDS) {
fprintf(stderr, "WordKeyInfo::Set: too many fields in %s, max is %d\n", (const char*)desc, WORD_KEY_MAX_NFIELDS);
return EINVAL;
}
if(fields.Count() <= 0) {
fprintf(stderr, "WordKeyInfo::Set: no fields\n");
return EINVAL;
}
if((ret = Alloc(fields.Count())))
return ret;
WordKeyField* previous = 0;
int i;
for(i = 0; i < fields.Count(); i++) {
char* field = fields[i];
WordKeyField& key_field = sort[i];
if(!mystrcasecmp(field, "word")) {
//
// String field
//
if(i != 0) {
fprintf(stderr, "WordKeyInfo::Set: Word field must show in first position %s\n", (const char*)desc);
return EINVAL;
}
key_field.SetString();
} else {
//
// Numerical field
//
StringList pair(field, "\t ");
if(pair.Count() != 2) {
fprintf(stderr, "WordKeyInfo::AddField: there must be exactly two strings separated by a white space (space or tab) in a field description (%s in key description %s)\n", field, (const char*)desc);
return EINVAL;
}
int bits = atoi(pair[1]);
char* name = pair[0];
key_field.SetNum(previous, name, bits);
previous = &key_field;
}
}
//
// Total length in bytes of the numerical fields
//
num_length = sort[i - 1].bytes_offset + sort[i - 1].bytesize;
return ret;
}
void
WordKeyInfo::Show()
{
fprintf(stderr, "-----------------------------------------\n");
fprintf(stderr, "nfields:%3d num_length:%3d\n", nfields, num_length);
int i;
for(i = 0; i < nfields; i++)
sort[i].Show();
char str[WORDKEYFIELD_BITS_MAX*WORD_KEY_MAX_NFIELDS];
memset(str, '_', WORDKEYFIELD_BITS_MAX*WORD_KEY_MAX_NFIELDS);
int last = 0;
int j;
for(j = 0; j < nfields; j++) {
for(i = 0; i < sort[j].bits; i++) {
char c = (j % 10) + '0';
int pos = sort[j].bits_offset + i;
if(str[pos] != '_') {
fprintf(stderr, "WordKeyInfo::Show: overlaping bits (field %d), bit %d\n", j, i);
c='X';
}
str[pos] = c;
if(last < pos) last = pos;
}
}
str[last + 1] = '\0';
fprintf(stderr, "%s (bits)\n",str);
fprintf(stderr, "^0 ^1 ^2 ^3 ^4 ^5 ^6 ^7\n");
fprintf(stderr, "0123456701234567012345670123456701234567012345670123456701234567\n");
}