<commit_before>#include "main.h"

/* example constructor, sets some options */
Histogram::Histogram()
{
    // declare options, keep options as uppercase
    vector<string> temp;
    temp.push_back("INPUTFILE");
    temp.push_back("OUTPUTFILE");
	temp.push_back("BLOCKSIZE");
	temp.push_back("CHARSETSIZE");
	temp.push_back("SORTED");
	temp.push_back("SHOWFREQUENCY");
    set_opts(temp);

    // set default values, option must exist or error will printed
    set_opt_value("OUTPUTFILE", "histogram");
	set_opt_value("BLOCKSIZE", "1");
	set_opt_value("CHARSETSIZE", "256");
	set_opt_value("SORTED", "0");
	set_opt_value("SHOWFREQUENCY", "0");
}

/* helper function that doesn't really do anything */
void Histogram::test()
{
    cout << "example test" << endl;
}

/* I am overriding the default module function
 * for displaying the description text
 */
void Histogram::disp_desc()
{
	cout << "Module: attacks/histogram\n\tThis module aids in the generation of character distribution histograms.\n\tOutput is generated in a CSV format of \"VALUE,OCCURENCES;\"\n\tThe BLOCKSIZE option is used to generate a set of histograms, one for each character in a block.\n\tThe CHARSETSIZE option is used to set the maximum range of the histogram(s).\n\t" << endl;
    disp_opts();
    cout << endl;
}

int Histogram::run()
{
    // perform error checking on options first
    if (options["INPUTFILE"].empty()) {
        cout << "[-] Please specify an input file" << endl;
        return 1;
    }

    if (options["OUTPUTFILE"].empty()) {
        cout << "[-] Please specify an output file" << endl;
        return 2;
    }

	const int blockSize = stoi(options["BLOCKSIZE"]);
	const int charSetSize = stoi(options["CHARSETSIZE"]);

	if (blockSize < 1){
		cout << "[-] Block size should be greater than 0" << endl;
		return 3;
	}

	vector< vector<int> > charCounts;
	charCounts.resize(blockSize);
	for (unsigned int index = 0; index < charCounts.size(); index++){
		charCounts[index].resize(charSetSize);
	}

	ifstream in;
    ofstream out;
    string buff;

	if (process_input(&in, &charCounts, blockSize, charSetSize) != 0) {
		return 4;
	}

	vector<int> charTotal(blockSize), maxLength(blockSize), maxCount(blockSize);
	analyze_input(&charCounts, &charTotal, &maxLength, &maxCount);
	
	process_output(&out, &charCounts, &charTotal, &maxLength);

    cout << "[*] Closing files" << endl;
    in.close();
    out.close();

    return 0;
}

int Histogram::process_input(ifstream* in, vector< vector<int> >* charCounts, const int blockSize, const int charSetSize) {
	cout << "[*] Opening file: " << options["INPUTFILE"] << endl;
	in->open(options["INPUTFILE"]);


	cout << "[*] Processing input file..." << endl;
	char inChar;
	int blockIndex = 0, charIndex;
	while (!in->eof()) {
		in->get(inChar);
		charIndex = ((inChar < 0) ? (charSetSize + (int)inChar) : (int)inChar);
		if (inChar < 0 || inChar > charSetSize) {
			cout << "[-] Character set size option is smaller than actual size." << endl;
			return 4;
		}
		(*charCounts)[blockIndex][charIndex]++;
		blockIndex = (blockIndex + 1) % blockSize;
	}

	return 0;
}

int Histogram::analyze_input(vector< vector<int> >* charCounts, vector<int>* charTotal, vector<int>* maxLength, vector<int>* maxCount) {
	cout << "[*] Analyzing input..." << endl;

	for (unsigned int blockIndex = 0; blockIndex < charCounts->size(); blockIndex++) {
		for (unsigned int charIndex = 0; charIndex < (*charCounts)[blockIndex].size(); charIndex++) {
			int temp = (*charCounts)[blockIndex][charIndex];
			(*charTotal)[blockIndex] += temp;
			if (temp > (*maxCount)[blockIndex]) (*maxCount)[blockIndex] = temp;
		}

		int maxCtCopy = (*maxCount)[blockIndex];
		while (maxCtCopy /= 10) (*maxLength)[blockIndex]++;
	}

	return 0;<commit_msg>Small fix with histogram generation, it used the incorrect variable during boundchecking<commit_after>#include "main.h"

/* example constructor, sets some options */
Histogram::Histogram()
{
    // declare options, keep options as uppercase
    vector<string> temp;
    temp.push_back("INPUTFILE");
    temp.push_back("OUTPUTFILE");
	temp.push_back("BLOCKSIZE");
	temp.push_back("CHARSETSIZE");
	temp.push_back("SORTED");
	temp.push_back("SHOWFREQUENCY");
    set_opts(temp);

    // set default values, option must exist or error will printed
    set_opt_value("OUTPUTFILE", "histogram");
	set_opt_value("BLOCKSIZE", "1");
	set_opt_value("CHARSETSIZE", "256");
	set_opt_value("SORTED", "0");
	set_opt_value("SHOWFREQUENCY", "0");
}

/* helper function that doesn't really do anything */
void Histogram::test()
{
    cout << "example test" << endl;
}

/* I am overriding the default module function
 * for displaying the description text
 */
void Histogram::disp_desc()
{
	cout << "Module: attacks/histogram\n\tThis module aids in the generation of character distribution histograms.\n\tOutput is generated in a CSV format of \"VALUE,OCCURENCES;\"\n\tThe BLOCKSIZE option is used to generate a set of histograms, one for each character in a block.\n\tThe CHARSETSIZE option is used to set the maximum range of the histogram(s).\n\t" << endl;
    disp_opts();
    cout << endl;
}

int Histogram::run()
{
    // perform error checking on options first
    if (options["INPUTFILE"].empty()) {
        cout << "[-] Please specify an input file" << endl;
        return 1;
    }

    if (options["OUTPUTFILE"].empty()) {
        cout << "[-] Please specify an output file" << endl;
        return 2;
    }

	const int blockSize = stoi(options["BLOCKSIZE"]);
	const int charSetSize = stoi(options["CHARSETSIZE"]);

	if (blockSize < 1){
		cout << "[-] Block size should be greater than 0" << endl;
		return 3;
	}

	vector< vector<int> > charCounts;
	charCounts.resize(blockSize);
	for (unsigned int index = 0; index < charCounts.size(); index++){
		charCounts[index].resize(charSetSize);
	}

	ifstream in;
    ofstream out;
    string buff;

	if (process_input(&in, &charCounts, blockSize, charSetSize) != 0) {
		return 4;
	}

	vector<int> charTotal(blockSize), maxLength(blockSize), maxCount(blockSize);
	analyze_input(&charCounts, &charTotal, &maxLength, &maxCount);
	
	process_output(&out, &charCounts, &charTotal, &maxLength);

    cout << "[*] Closing files" << endl;
    in.close();
    out.close();

    return 0;
}

int Histogram::process_input(ifstream* in, vector< vector<int> >* charCounts, const int blockSize, const int charSetSize) {
	cout << "[*] Opening file: " << options["INPUTFILE"] << endl;
	in->open(options["INPUTFILE"]);


	cout << "[*] Processing input file..." << endl;
	char inChar;
	int blockIndex = 0, charIndex;
	while (!in->eof()) {
		in->get(inChar);
		charIndex = ((inChar < 0) ? (charSetSize + (int)inChar) : (int)inChar);
		if (charIndex < 0 || charIndex > charSetSize) {
			cout << "[-] Character set size option is smaller than actual size." << endl;
			return 4;
		}
		(*charCounts)[blockIndex][charIndex]++;
		blockIndex = (blockIndex + 1) % blockSize;
	}

	return 0;
}

int Histogram::analyze_input(vector< vector<int> >* charCounts, vector<int>* charTotal, vector<int>* maxLength, vector<int>* maxCount) {
	cout << "[*] Analyzing input..." << endl;

	for (unsigned int blockIndex = 0; blockIndex < charCounts->size(); blockIndex++) {
		for (unsigned int charIndex = 0; charIndex < (*charCounts)[blockIndex].size(); charIndex++) {
			int temp = (*charCounts)[blockIndex][charIndex];
			(*charTotal)[blockIndex] += temp;
			if (temp > (*maxCount)[blockIndex]) (*maxCount)[blockIndex] = temp;
		}

		int maxCtCopy = (*maxCount)[blockIndex];
		while (maxCtCopy /= 10) (*maxLength)[blockIndex]++;
	}

	return 0;
{'fraction_non_alphanumeric': 0.15677241016190602, 'fraction_numerical': 0.006844807160721338, 'mean_word_length': 4.298465829846583, 'pattern_counts': {'":': 0, '<': 125, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '208623', 'n_tokens_mistral': 2628, 'n_tokens_neox': 2456, 'n_words': 678}