#define MEGABYTE 1048576
#define FIELD_BUFFER_SIZE 1024
-// 2048 KB in bytes + 1
-//#define TEXT_BUFFER_SIZE 2097153
-//#define TEXT_BUFFER_SIZE 10485760
+
+// this can be changed at runtime if we encounter an article larger than 10mb
+size_t text_buffer_size = 10 * MEGABYTE;
enum elements {
TITLE, ARTICLEID, REVISION, REVID, TIMESTAMP, CONTRIBUTOR,
static void
init_data(revisionData *data, outtype output_type)
{
- data->text = (char*) malloc(4 * MEGABYTE); // 2MB is the article length limit, 4MB is 'safe'?
+ data->text = (char*) malloc(text_buffer_size);
data->comment = (char*) malloc(FIELD_BUFFER_SIZE);
data->title = (char*) malloc(FIELD_BUFFER_SIZE);
data->articleid = (char*) malloc(FIELD_BUFFER_SIZE);
vector<bool> regex_matches_adds;
vector<bool> regex_matches_dels;
- if (!data->last_text_tokens.empty()) {
+ if (data->last_text_tokens.empty()) {
+ additions = data->text;
+ } else {
// do the diff
dtl::Diff< string, vector<string> > d(data->last_text_tokens, text_tokens);
break;
}
}
-
- if (!additions.empty()) {
- //cout << "ADD: " << additions << endl;
- for (vector<pcrecpp::RE>::iterator r = data->regexes.begin(); r != data->regexes.end(); ++r) {
- pcrecpp::RE& regex = *r;
- regex_matches_adds.push_back(regex.PartialMatch(additions));
- }
+ }
+
+ if (!additions.empty()) {
+ //cout << "ADD: " << additions << endl;
+ for (vector<pcrecpp::RE>::iterator r = data->regexes.begin(); r != data->regexes.end(); ++r) {
+ pcrecpp::RE& regex = *r;
+ regex_matches_adds.push_back(regex.PartialMatch(additions));
}
+ }
- if (!deletions.empty()) {
- //cout << "DEL: " << deletions << endl;
- for (vector<pcrecpp::RE>::iterator r = data->regexes.begin(); r != data->regexes.end(); ++r) {
- pcrecpp::RE& regex = *r;
- regex_matches_dels.push_back(regex.PartialMatch(deletions));
- }
+ if (!deletions.empty()) {
+ //cout << "DEL: " << deletions << endl;
+ for (vector<pcrecpp::RE>::iterator r = data->regexes.begin(); r != data->regexes.end(); ++r) {
+ pcrecpp::RE& regex = *r;
+ regex_matches_dels.push_back(regex.PartialMatch(deletions));
}
-
- // apply regex to the diff
-
}
data->last_text_tokens = text_tokens;
char*
strlcatn(char *dest, const char *src, size_t dest_len, size_t n)
{
- //size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
charhndl(void* vdata, const XML_Char* s, int len)
{
revisionData* data = (revisionData*) vdata;
+ size_t bufsz;
if (data->element != UNUSED && data->position != SKIP) {
- //char t[len];
- //strncpy(t,s,len);
- //t[len] = '\0'; // makes t a well-formed string
switch (data->element) {
case TEXT:
- // printf("buffer length = %i, text: %s\n", len, t);
+ // check if we'd overflow our buffer
+ bufsz = data->text_size + len;
+ if (bufsz + 1 > text_buffer_size) {
+ data->text = (char*) realloc(data->text, bufsz + 1);
+ text_buffer_size = bufsz + 1;
+ }
strlcatn(data->text, s, data->text_size, len);
- data->text_size += len;
+ data->text_size = bufsz;
break;
case COMMENT:
strlcatn(data->comment, s, data->comment_size, len);
<< "Takes a wikimedia data dump XML stream on standard in, and produces" << endl
<< "a tab-separated stream of revisions on standard out:" << endl
<< endl
- << "title, articleid, revid, timestamp, anon, editor, editorid, minor, revlength, reventropy, revmd5" << endl
+ << "title, articleid, revid, timestamp, anon, editor, editorid, minor," << endl
+ << "text_length, text_entropy, text_md5, reversion, additions_size, deletions_size" << endl
<< ".... and additional fields for each regex executed against add/delete diffs" << endl
<< endl
+ << "Boolean fields are TRUE/FALSE except in the case of reversion, which is blank" << endl
+ << "unless the article is a revert to a previous revision, in which case, it" << endl
+ << "contains the revision ID of the revision which was reverted to." << endl
+ << endl
<< "author: Erik Garrison <erik@hypervolu.me>" << endl;
}
// passes the buffer of data to the parser and checks for error
// (this is where the callbacks are invoked)
if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
- cerr << XML_ErrorString(XML_GetErrorCode(parser)) << " at line "
+ cerr << "XML ERROR: " << XML_ErrorString(XML_GetErrorCode(parser)) << " at line "
<< (int) XML_GetCurrentLineNumber(parser) << endl;
return 1;
}