many helper functions

This commit is contained in:
amannb 2011-10-25 11:47:23 -07:00 committed by Bernhard Amann
parent 3654060246
commit d7a3b85fcd
6 changed files with 245 additions and 31 deletions

View file

@ -100,31 +100,62 @@ InputReader* InputMgr::CreateReader(EnumVal* reader, RecordVal* description)
void InputMgr::Error(InputReader* reader, const char* msg)
{
reporter->Error(fmt("error with input reader for %s: %s",
reader->Source().c_str(), msg));
reporter->Error("error with input reader for %s: %s", reader->Source().c_str(), msg);
}
/*
TODO:
void InputMgr::SendEvent(string name) {
//EventHandler* handler = event_registry->Lookup(eventName.c_str());
//if ( handler == 0 ) {
// reporter->Error("Event %s not found", eventName.c_str());
// return false;
//}
//val_list* vl = new val_list;
//vl->append(new Val(12, TYPE_COUNT));
//mgr.Dispatch(new Event(handler, vl));
void InputMgr::SendEvent(const string& name, const int num_vals, const LogVal* const *vals)
{
EventHandler* handler = event_registry->Lookup(name.c_str());
if ( handler == 0 ) {
reporter->Error("Event %s not found", name.c_str());
return;
}
val_list* vl = new val_list;
for ( int i = 0; i < num_vals; i++) {
vl->append(LogValToVal(vals[i]));
}
mgr.Dispatch(new Event(handler, vl));
}
*/
Val* InputMgr::LogValToVal(const LogVal* val) {
switch ( val->type ) {
case TYPE_BOOL:
case TYPE_INT:
return new Val(val->val.int_val, val->type);
break;
case TYPE_COUNT:
case TYPE_COUNTER:
return new Val(val->val.uint_val, val->type);
break;
case TYPE_DOUBLE:
case TYPE_TIME:
case TYPE_INTERVAL:
return new Val(val->val.double_val, val->type);
break;
case TYPE_STRING:
{
BroString *s = new BroString(*(val->val.string_val));
return new StringVal(s);
break;
}
case TYPE_PORT:
return new PortVal(val->val.uint_val);
break;
default:
reporter->InternalError("unsupported type for input_read");
}
reporter->InternalError("Impossible error");
return NULL;
}

View file

@ -13,7 +13,6 @@
class InputReader;
class InputMgr {
public:
InputMgr();
@ -29,6 +28,9 @@ protected:
private:
// required functionality
// InputValsToRecord to convert received inputvals back to bro records / tables / whatever
Val* LogValToVal(const LogVal* val);
void SendEvent(const string& name, const int num_vals, const LogVal* const *vals);
};

View file

@ -33,3 +33,34 @@ bool InputReader::Init(string arg_source, int arg_num_fields,
void InputReader::Finish() {
DoFinish();
}
bool InputReader::Update() {
return DoUpdate();
}
// stolen from logwriter
const char* InputReader::Fmt(const char* format, ...)
{
if ( ! buf )
buf = (char*) malloc(buf_len);
va_list al;
va_start(al, format);
int n = safe_vsnprintf(buf, buf_len, format, al);
va_end(al);
if ( (unsigned int) n >= buf_len )
{ // Not enough room, grow the buffer.
buf_len = n + 32;
buf = (char*) realloc(buf, buf_len);
// Is it portable to restart?
va_start(al, format);
n = safe_vsnprintf(buf, buf_len, format, al);
va_end(al);
}
return buf;
}

View file

@ -19,18 +19,26 @@ public:
void Finish();
bool Update();
protected:
// Methods that have to be overwritten by the individual readers
virtual bool DoInit(string arg_source, int num_fields, const LogField* const * fields) = 0;
virtual void DoFinish() = 0;
// update file contents to logmgr
virtual bool DoUpdate() = 0;
// Reports an error to the user.
void Error(const char *msg);
// The following methods return the information as passed to Init().
const string Source() const { return source; }
// A thread-safe version of fmt(). (stolen from logwriter)
const char* Fmt(const char* format, ...);
private:
friend class InputMgr;
@ -44,6 +52,10 @@ private:
bool disabled;
bool Disabled() { return disabled; }
// For implementing Fmt().
char* buf;
unsigned int buf_len;
};

View file

@ -1,9 +1,22 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "InputReaderAscii.h"
#include "DebugLogger.h"
#include <sstream>
FieldMapping::FieldMapping(const string& arg_name, const TypeTag& arg_type, int arg_position)
: name(arg_name), type(arg_type)
{
position = arg_position;
}
FieldMapping::FieldMapping(const FieldMapping& arg)
: name(arg.name), type(arg.type)
{
position = arg.position;
}
InputReaderAscii::InputReaderAscii()
{
//DBG_LOG(DBG_LOGGING, "input reader initialized");
@ -18,31 +31,134 @@ void InputReaderAscii::DoFinish()
{
}
bool InputReaderAscii::DoInit(string path, int num_fields,
const LogField* const * fields)
bool InputReaderAscii::DoInit(string path, int num_fields, const LogField* const * fields)
{
fname = path;
file = new ifstream(path.c_str());
if ( !file->is_open() ) {
Error(Fmt("cannot open %s", path.c_str()));
return false;
}
// try to read the header line...
string line;
if ( !getline(*file, line) )
if ( !getline(*file, line) ) {
Error("could not read first line");
return false;
}
// split on tabs...
istringstream ss(line);
while ( ss ) {
istringstream splitstream(line);
unsigned int currTab = 0;
int wantFields = 0;
while ( splitstream ) {
string s;
if ( !getline(ss, s, '\t'))
if ( !getline(splitstream, s, '\t'))
break;
// current found heading in s... compare if we want it
for ( int i = 0; i < num_fields; i++ ) {
const LogField* field = fields[i];
if ( field->name == s ) {
// cool, found field. note position
FieldMapping f(field->name, field->type, i);
columnMap.push_back(f);
wantFields++;
break; // done with searching
}
}
// look if we did push something...
if ( columnMap.size() == currTab ) {
// no, we didn't. note that...
FieldMapping empty;
columnMap.push_back(empty);
}
// done
currTab++;
}
if ( wantFields != num_fields ) {
// we did not find all fields?
// :(
Error("wantFields != num_fields");
return false;
}
return false;
this->num_fields = num_fields;
// well, that seems to have worked...
return true;
}
// read the entire file and send appropriate thingies back to InputMgr
bool InputReaderAscii::DoUpdate() {
// TODO: all the stuff we need for a second reading.
// *cough*
//
string line;
while ( getline(*file, line ) ) {
// split on tabs
istringstream splitstream(line);
string s;
LogVal fields[num_fields];
unsigned int currTab = 0;
unsigned int currField = 0;
while ( splitstream ) {
if ( !getline(splitstream, s, '\t') )
break;
if ( currTab >= columnMap.size() ) {
Error("Tabs in heading do not match tabs in data?");
//disabled = true;
return false;
}
FieldMapping currMapping = columnMap[currTab];
currTab++;
if ( currMapping.IsEmpty() ) {
// well, that was easy
continue;
}
if ( currField >= num_fields ) {
Error("internal error - fieldnum greater as possible");
return false;
}
LogVal val(currMapping.type, true);
switch ( currMapping.type ) {
case TYPE_STRING:
val.val.string_val = new string(s);
default:
Error(Fmt("unsupported field format %d for %s", currMapping.type,
currMapping.name.c_str()));
return false;
}
currField++;
}
if ( currField != num_fields ) {
Error("curr_field != num_fields in DoUpdate");
return false;
}
// ok, now we have built our line. send it back to... whomever.
}
return true;
}

View file

@ -1,3 +1,4 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef INPUTREADERASCII_H
#define INPUTREADERASCII_H
@ -5,6 +6,19 @@
#include "InputReader.h"
#include <fstream>
#include <iostream>
#include <vector>
// Description for input field mapping
struct FieldMapping {
string name;
TypeTag type;
int position;
FieldMapping(const string& arg_name, const TypeTag& arg_type, int arg_position);
FieldMapping(const FieldMapping& arg);
FieldMapping() { position = -1; }
bool IsEmpty() { return position == -1; }
};
class InputReaderAscii : public InputReader {
@ -20,10 +34,18 @@ protected:
const LogField* const * fields);
virtual void DoFinish();
virtual bool DoUpdate();
private:
ifstream* file;
string fname;
unsigned int num_fields;
// map columns in the file to columns to send back to the manager
vector<FieldMapping> columnMap;
};