diff --git a/main.cpp b/main.cpp index c3fbad7..8737578 100644 --- a/main.cpp +++ b/main.cpp @@ -1,16 +1,20 @@ +// C library headers #include #include -#include -#include +// C++ standard library headers #include -#include +#include +#include +#include + +// Third-party headers #include using json = nlohmann::json; -// used to have a dynamic string -typedef struct Response +// Structure to hold dynamic string response from CURL +struct Response { char *string; size_t size; @@ -23,12 +27,9 @@ struct TestCaseResponse }; size_t write_chunk(void *data, size_t size, size_t nmemb, void *userData); - void formatResponse(char *response); std::string FormatHTMLToString(const std::string &response); TestCaseResponse GetTestCases(const std::string &content); - -std::pair GetParamName(const std::string ¶m); void CreateJSON(json *response, const TestCaseResponse &testCases); int main() @@ -53,7 +54,7 @@ int main() } Response response; - response.string = (char *)malloc(1); + response.string = static_cast(malloc(1)); response.size = 0; // Set options for the HTTP request @@ -87,7 +88,7 @@ int main() curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_chunk); // Address of response string is passed in write_chunk as userData - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast(&response)); // Perform the HTTP request result = curl_easy_perform(curl); @@ -105,43 +106,40 @@ int main() return 0; } -// returns number of bytes in the chunk -// data is set to a ptr that points to block of data recieved in this chunk -// nmemb is the number of bytes in the block of data -// userData points to what we want (points to where the response string is stored) +// Returns number of bytes in the chunk +// data: pointer to block of data received in this chunk +// nmemb: number of bytes in the block of data +// userData: pointer to where the response string is stored size_t write_chunk(void *data, size_t size, size_t nmemb, void *userData) { // size is always 1 size_t real_size = size * nmemb; - Response *response = (Response *)userData; - // allocate more space for chunk that was recieved - // response->size is size of existing mem and real_size is the size recieved and +1 accounts for null - char *ptr = (char *)realloc(response->string, response->size + real_size + 1); + Response *response = static_cast(userData); + // Allocate more space for chunk that was received + // response->size is size of existing mem and real_size is the size received and +1 accounts for null + char *ptr = static_cast(realloc(response->string, response->size + real_size + 1)); if (ptr == nullptr) { - std::cerr << "Problem reallocating space for chunk recieved" << std::endl; + std::cerr << "Problem reallocating space for chunk received" << std::endl; return 0; } - // set response string to the new (larger) memory address + // Set response string to the new (larger) memory address response->string = ptr; - // append new porition onto existing string + // Append new portion onto existing string memcpy(&(response->string[response->size]), data, real_size); - // update strings size + // Update string size response->size += real_size; - // append null character + // Append null character response->string[response->size] = '\0'; return real_size; } /** - * Returns a map containing the following tags stored as keys - * and their description as their value. - * - * title content difficulty topicTags { name } hints - * - * Assumes json response will use the tags in the given order above. + * Formats the JSON response from LeetCode's GraphQL API. + * Processes tags: title, content, difficulty, topicTags, hints + * Extracts test cases from content and creates output JSON file. */ void formatResponse(char *response) { @@ -195,7 +193,7 @@ void formatResponse(char *response) } } -// check for tag +// Converts HTML content to plain text by removing HTML tags and converting HTML entities std::string FormatHTMLToString(const std::string &response) { int i = 0; @@ -203,7 +201,7 @@ std::string FormatHTMLToString(const std::string &response) while (i < response.length()) { - // check for HTML elements + // Check for HTML elements if (response[i] == '<') { while (response[i] != '>') @@ -214,7 +212,7 @@ std::string FormatHTMLToString(const std::string &response) continue; } - // check for < (<) , > (>); + // Check for < (<), > (>) if (i < response.length() - 4 && (response.substr(i, 4) == "<" || response.substr(i, 4) == ">")) { std::string expression = response.substr(i, 4); @@ -230,7 +228,7 @@ std::string FormatHTMLToString(const std::string &response) continue; } - // check for & (&) + // Check for & (&) if (i < response.length() - 5 && (response.substr(i, 5) == "&")) { result += "&"; @@ -238,22 +236,22 @@ std::string FormatHTMLToString(const std::string &response) continue; } - // check for 's + // Check for 's if (i < response.length() - 6 && response.substr(i, 6) == "'s") { i += 6; continue; } - // check for   tags + // Check for   tags if (i < response.length() - 6 && response.substr(i, 6) == " ") { i += 6; continue; } - // check for multiple whitespace characters - // want to keep 1 where there are multiple + // Check for multiple whitespace characters + // Keep only one where there are multiple if (response[i] == '\n') { result += "\n"; @@ -282,9 +280,9 @@ std::string FormatHTMLToString(const std::string &response) } /** - * Basic test cases given by leetcode are given in a string of the form. Example case & output. - * Should always be at least 2 test cases given. - * @returns array of oxpected outputs for the test cases. + * Extracts test cases from LeetCode problem content. + * Parses Example sections to extract input parameters and expected outputs. + * @returns TestCaseResponse containing test cases and their parameters */ TestCaseResponse GetTestCases(const std::string &content) { @@ -307,7 +305,7 @@ TestCaseResponse GetTestCases(const std::string &content) int j = -1; while (i < content.length() - 7 && content.substr(i, 7) != "\nOutput") { - // check if new param is being searched + // Check if new param is being searched if (i < content.length() - 1 && (content[i] == ',' && content[i + 1] == ' ')) { tests.testCaseParams.push_back({paramName, paramRes}); @@ -317,7 +315,7 @@ TestCaseResponse GetTestCases(const std::string &content) i++; continue; } - // now looking for paramResult so set j (flag for where = is) + // Now looking for paramResult so set j (flag for where = is) if (content[i] == '=') { j = i; @@ -339,7 +337,6 @@ TestCaseResponse GetTestCases(const std::string &content) { tests.testCaseParams.push_back({paramName, paramRes}); } - // std::cout << paramName << " " << paramRes << std::endl; } if (i <= content.length() - 6 && content.substr(i, 6) == "Output") @@ -371,7 +368,7 @@ TestCaseResponse GetTestCases(const std::string &content) void CreateJSON(json *response, const TestCaseResponse &tests) { - // filter out invalid characters from title + // Filter out invalid characters from title std::string title = (*response)["title"]; const std::string invalid_chars = "\\/:*?\"<>|"; for (char c : invalid_chars) @@ -382,7 +379,7 @@ void CreateJSON(json *response, const TestCaseResponse &tests) std::ofstream outputJSON; outputJSON.open(jsonName); - // should have to create the file so always should open + // Should be able to create the file if (!outputJSON.is_open()) { std::cerr << "Error creating output file for JSON response" << std::endl; @@ -390,25 +387,23 @@ void CreateJSON(json *response, const TestCaseResponse &tests) } outputJSON << "{\n"; - // iterates through json response inserting key and value as pair into output file + // Iterate through JSON response inserting key and value pairs into output file for (auto it = (*response).begin(); it != (*response).end(); ++it) { outputJSON << "\"" << it.key() << "\"" << ": " << it.value() << ',' << "\n"; } - // handle situation where testCases might not generate - - // Insert testcases + // Insert test cases outputJSON << "\"testCases\"" << ": [" << "\n"; int j = 0; int size = tests.testCases.size(); for (int i = 0; i < size; i++) { - // start inserting new object into array inside json file + // Start inserting new object into array inside JSON file outputJSON << "{\n"; - std::string expectedResult = tests.testCases[i]; // testcase expected outputs + std::string expectedResult = tests.testCases[i]; // Test case expected outputs outputJSON << "\"expectedResult\": " << "\"" << expectedResult << "\",\n"; int numParams = tests.testCaseParams.size() / tests.testCases.size(); @@ -425,7 +420,7 @@ void CreateJSON(json *response, const TestCaseResponse &tests) } } - // if i is at the end then we need to close off the obj + // If at the end, close off the object without comma if (i == size - 1) { outputJSON << "}\n"; @@ -440,35 +435,4 @@ void CreateJSON(json *response, const TestCaseResponse &tests) outputJSON << "}"; outputJSON.close(); -} - -/** - * params are taken from the json as a string containing 'paramName'='param' - * This function splits the paramName and param seperately to label them in the output JSON easier. - * (the problem function calls explicility used by the users will contain the same paramNames so makes using them easier as well) - */ -std::pair GetParamName(const std::string ¶m) -{ - std::string paramName = ""; - std::string paramResult = ""; - bool nameParsed = false; - for (int i = 0; i < param.length(); i++) - { - - if (param[i] == '=') - { - nameParsed = true; - continue; - } - - if (param[i] != ' ' && !nameParsed) - { - paramName += param[i]; - } - else if (param[i] != ' ' && nameParsed) - { - paramResult += param[i]; - } - } - return {paramName, paramResult}; } \ No newline at end of file