414 lines
10 KiB
C++
414 lines
10 KiB
C++
void editor::instruction::clear_instruction() {
|
|
/***
|
|
void clear_instruction():
|
|
- Sets instruction to unitialized & clears variables
|
|
***/
|
|
|
|
initialized = false;
|
|
operation = no_operation;
|
|
start_position = -1;
|
|
end_position = -1;
|
|
text_input = "";
|
|
}
|
|
|
|
void editor::instruction::process_special_chars() {
|
|
if (operation == remove_operation || operation == no_operation) {
|
|
return;
|
|
}
|
|
|
|
/* Process \n, \t, and \\ */
|
|
text_input = process_escapedchars(text_input);
|
|
|
|
/* Process \x00 through \xFF */
|
|
text_input = process_bytecodes(text_input);
|
|
|
|
end_position = (start_position + text_input.length());
|
|
|
|
}
|
|
|
|
bool editor::instruction::set_replace_instruction(int64_t start, std::string text) {
|
|
/***
|
|
bool set_replace_instruction():
|
|
- Sets the current instruction to type "replace"
|
|
- Sets relevant variables
|
|
Returns true if successful
|
|
Runs clear_instruction & returns false if failure
|
|
***/
|
|
|
|
/*
|
|
Make sure the start position is valid.
|
|
Meaning:
|
|
- Not less than -1 (-1 is reserved for the 'end' keyword)
|
|
- Not beyond EOF
|
|
*/
|
|
|
|
if (start < -1) {
|
|
error_message = "Invalid start position";
|
|
clear_instruction();
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Set object 'private' info to user-provided parameters
|
|
And then declare the object initialized
|
|
*/
|
|
operation = replace_operation;
|
|
start_position = start;
|
|
end_position = (start + text.length());
|
|
text_input = text;
|
|
initialized = true;
|
|
|
|
/* Clear any earlier error messages */
|
|
error_message = "";
|
|
|
|
return true;
|
|
}
|
|
|
|
bool editor::instruction::set_insert_instruction(int64_t start, std::string text) {
|
|
/***
|
|
bool set_insert_instruction():
|
|
- Sets the current instruction to type "insert"
|
|
- Sets relevant variables
|
|
Returns true if successful
|
|
Runs clear_instruction & returns false if failure
|
|
***/
|
|
|
|
/*
|
|
Make sure the start position is valid
|
|
Meaning:
|
|
- Not less than -1 (-1 is reserved for the 'end' keyword)
|
|
- Not beyond EOF
|
|
*/
|
|
if (start < -1) {
|
|
error_message = "Invalid start position";
|
|
clear_instruction();
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Set object 'private' info to user-provided parameters
|
|
And then declare the object initialized
|
|
*/
|
|
operation = insert_operation;
|
|
start_position = start;
|
|
end_position = (start + text.length());
|
|
text_input = text;
|
|
initialized = true;
|
|
|
|
/* Clear any earlier error messages */
|
|
error_message = "";
|
|
|
|
return true;
|
|
}
|
|
|
|
bool editor::instruction::set_remove_instruction(int64_t start, int64_t end) {
|
|
/***
|
|
bool set_remove_instruction():
|
|
- Sets the current instruction to type "remove"
|
|
- Sets relevant variables
|
|
Returns true if successful
|
|
Runs clear_instruction & returns false if failure
|
|
***/
|
|
|
|
/*
|
|
Make sure the start position is valid
|
|
Meaning:
|
|
- Not less than -1 (-1 is reserved for the 'end' keyword)
|
|
*/
|
|
if (start < -1) {
|
|
error_message = "Invalid start position";
|
|
clear_instruction();
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Make sure the end position is valid
|
|
Meaning:
|
|
- Not less than the start position
|
|
*/
|
|
if ( (end < start) && (end != -1) ) {
|
|
error_message = "Invalid end position";
|
|
clear_instruction();
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Set object 'private' info to user-provided parameters
|
|
And then declare the object initialized
|
|
*/
|
|
operation = remove_operation;
|
|
start_position = start;
|
|
end_position = end + 1;
|
|
initialized = true;
|
|
|
|
/* Clear any earlier error messages */
|
|
error_message = "";
|
|
|
|
return true;
|
|
}
|
|
|
|
void editor::instruction::set_error_message(std::string message) {
|
|
/***
|
|
void set_error_message(std::string message):
|
|
Set the instruction's "error_message" to the inputted string
|
|
***/
|
|
|
|
error_message = message;
|
|
}
|
|
|
|
std::string editor::instruction::get_error_message() {
|
|
return error_message;
|
|
}
|
|
|
|
void editor::instruction::update_start_position(int64_t start) {
|
|
start_position = start;
|
|
}
|
|
|
|
void editor::instruction::update_end_position(int64_t end) {
|
|
end_position = end;
|
|
}
|
|
|
|
bool editor::instruction::is_initialized() {
|
|
return initialized;
|
|
}
|
|
|
|
int editor::instruction::get_operation_type() {
|
|
return operation;
|
|
}
|
|
|
|
int64_t editor::instruction::get_start_position() {
|
|
return start_position;
|
|
}
|
|
|
|
int64_t editor::instruction::get_end_position() {
|
|
return end_position;
|
|
}
|
|
|
|
std::string editor::instruction::get_text() {
|
|
return text_input;
|
|
}
|
|
|
|
editor::instruction create_replace_instruction(int64_t start_position, std::string text) {
|
|
editor::instruction new_instruction;
|
|
|
|
new_instruction.set_replace_instruction(start_position, text);
|
|
|
|
return new_instruction;
|
|
}
|
|
|
|
editor::instruction create_insert_instruction(int64_t start_position, std::string text) {
|
|
editor::instruction new_instruction;
|
|
|
|
new_instruction.set_insert_instruction(start_position, text);
|
|
|
|
return new_instruction;
|
|
}
|
|
|
|
editor::instruction create_remove_instruction(int64_t start_position, int end_position) {
|
|
editor::instruction new_instruction;
|
|
|
|
new_instruction.set_remove_instruction(start_position, end_position);
|
|
|
|
return new_instruction;
|
|
}
|
|
|
|
|
|
editor::instruction parse_instruction_string(std::string instruction_string) {
|
|
/*
|
|
instruction parse_instruction_string(std::string instruction_string):
|
|
Create an 'instruction' object from a properly-formatted string
|
|
|
|
The std::string must be formatted in one of the following ways:
|
|
1.
|
|
REPLACE 5 hello
|
|
(
|
|
This would replace characters #5 - #9 with "hello"
|
|
Example:
|
|
Original file:
|
|
01234567890123
|
|
New file:
|
|
01234hello0123
|
|
)
|
|
2.
|
|
INSERT 6 ni hao
|
|
(
|
|
This would shift characters #6 - EOF rightward and insert "ni hao" at position #6 without replacing
|
|
(Or, if #6 is EOF, this would insert "ni hao" at the end of the file)
|
|
Example:
|
|
Original file:
|
|
01234567890123
|
|
New file:
|
|
012345ni hao67890123
|
|
)
|
|
3.
|
|
REMOVE 7 10
|
|
(
|
|
This would remove characters #7 - #10 and shift the remaining characters leftward
|
|
Example:
|
|
Original file:
|
|
01234567890123
|
|
New file:
|
|
0123456123
|
|
)
|
|
That is, the std::string must be formatted with these rules:
|
|
- Space-delimited
|
|
- The first key is the instruction name (REPLACE, INSERT, or REMOVE)
|
|
- The second key is the start position
|
|
- The third key is either:
|
|
- A std::string (in the case of REPLACE or INSERT)
|
|
- The end position (in the case of REMOVE)
|
|
*/
|
|
|
|
/*
|
|
Remove leading whitespace
|
|
*/
|
|
|
|
instruction_string = remove_leading_whitespace(instruction_string);
|
|
|
|
/*
|
|
Split the std::string into a std::vector<std::string> delimited by spaces
|
|
See: shared_functions/explode.cpp
|
|
*/
|
|
std::vector<std::string> instruction_vector = explode(instruction_string, ' ', 3);
|
|
|
|
/*
|
|
Set up an 'instruction' object marked invalid to return if there's a problem
|
|
*/
|
|
editor::instruction invalid_instruction;
|
|
|
|
/*
|
|
Make sure we have exactly 3 elements
|
|
*/
|
|
if (instruction_vector.size() != 3) {
|
|
invalid_instruction.set_error_message("Invalid instruction: " + instruction_string);
|
|
return invalid_instruction;
|
|
}
|
|
|
|
std::string first_element = "";
|
|
std::string second_element = "";
|
|
std::string third_element = "";
|
|
|
|
bool second_element_is_end = false;
|
|
bool third_element_is_end = false;
|
|
|
|
/*
|
|
Make sure the first element is either "replace," "insert," or "remove"
|
|
*/
|
|
first_element = to_lower(instruction_vector[0]);
|
|
bool is_replace_instruction = (first_element == "replace");
|
|
bool is_insert_instruction = (first_element == "insert");
|
|
bool is_remove_instruction = (first_element == "remove");
|
|
|
|
bool instruction_type_is_valid = (is_replace_instruction || is_insert_instruction || is_remove_instruction);
|
|
|
|
if (!instruction_type_is_valid) {
|
|
invalid_instruction.set_error_message("Invalid instruction type: '" + instruction_vector[0] + "'");
|
|
return invalid_instruction;
|
|
}
|
|
|
|
/*
|
|
The second element should ALWAYS be either an integer or the keyword "end"
|
|
See: shared_functions/is_number.cpp
|
|
*/
|
|
second_element = to_lower(instruction_vector[1]);
|
|
|
|
second_element_is_end = (second_element == "end");
|
|
|
|
if ( ! (is_number(second_element) || (second_element_is_end)) ) {
|
|
invalid_instruction.set_error_message("Invalid instruction: '" + instruction_vector[1] + "' is not a positive integer");
|
|
return invalid_instruction;
|
|
}
|
|
|
|
/*
|
|
If it's a remove instruction, the third element should also be either an integer or the keyword "end"
|
|
*/
|
|
if (is_remove_instruction) {
|
|
third_element = to_lower(instruction_vector[2]);
|
|
|
|
third_element_is_end = (third_element == "end");
|
|
|
|
if ( ! (is_number(instruction_vector[2]) || (third_element_is_end) )) {
|
|
invalid_instruction.set_error_message("Invalid REMOVE instruction: '" + instruction_vector[2] + "' is not a positive integer");
|
|
return invalid_instruction;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Now, to actually create the 'instruction' object
|
|
*/
|
|
|
|
int64_t start_position;
|
|
int64_t end_position;
|
|
|
|
if (is_replace_instruction) {
|
|
|
|
if (second_element_is_end) {
|
|
start_position = -1;
|
|
} else {
|
|
start_position = (int64_t)stoll(instruction_vector[1]);
|
|
}
|
|
|
|
return create_replace_instruction(start_position, instruction_vector[2]);
|
|
}
|
|
|
|
if (is_insert_instruction) {
|
|
|
|
if (second_element_is_end) {
|
|
start_position = -1;
|
|
} else {
|
|
start_position = (int64_t)stoll(instruction_vector[1]);
|
|
}
|
|
|
|
return create_insert_instruction(start_position, instruction_vector[2]);
|
|
}
|
|
|
|
if (is_remove_instruction) {
|
|
|
|
if (second_element_is_end) {
|
|
start_position = -1;
|
|
} else {
|
|
start_position = (int64_t)stoll(instruction_vector[1]);
|
|
}
|
|
|
|
if (third_element_is_end) {
|
|
end_position = -1;
|
|
} else {
|
|
end_position = (int64_t)stoll(instruction_vector[2]);
|
|
}
|
|
|
|
return create_remove_instruction(start_position, end_position);
|
|
}
|
|
|
|
// If we've made it this far, something terrible has happened
|
|
invalid_instruction.set_error_message("I must suck at programming");
|
|
return invalid_instruction;
|
|
}
|
|
|
|
|
|
std::vector<editor::instruction> parse_instruction_set_string(std::string instruction_set_string) {
|
|
/***
|
|
std::vector<instruction> parse_instruction_set_string(std::string instruction_set_string):
|
|
Create a std::vector of 'instruction' objects from a newline-delimited std::string of properly-formatted instructions
|
|
|
|
Example of ONE properly-formatted "instruction set" string:
|
|
REPLACE 5 hello
|
|
INSERT 6 ni hao
|
|
REMOVE 7 10
|
|
|
|
Each line must follow the normal rules for properly-formatted instructions
|
|
See: parse_instruction_string(std::string instruction_string)
|
|
|
|
The "instruction set" itself must be newline-delimited
|
|
That is, each individual instruction must be on its own line
|
|
***/
|
|
std::vector<editor::instruction> output_instruction_set;
|
|
|
|
std::vector<std::string> instruction_strings = explode(instruction_set_string, '\n');
|
|
|
|
for (std::string i : instruction_strings) {
|
|
output_instruction_set.push_back( parse_instruction_string(i) );
|
|
}
|
|
|
|
return output_instruction_set;
|
|
}
|