Finish C++ impl

This commit is contained in:
Stephen Seo 2021-05-10 15:15:33 +09:00
parent aa49e41a80
commit 28b93305cf
6 changed files with 210 additions and 88 deletions

View file

@ -7,7 +7,7 @@ endif
OBJECTS = \
src/main.o \
src/argparse.o
src/helpers.o
all: GreedyTextJustification

View file

@ -1,67 +0,0 @@
#include "argparse.hpp"
#include <cstring>
#include <stdexcept>
std::unordered_map<std::string, std::string> ArgParse::parseArgs(
int argc,
char **argv,
const std::vector<std::string> &simpleArgs,
const std::vector<std::string> &pairedArgs) {
std::unordered_map<std::string, std::string> mapping;
--argc; ++argv;
std::string temp;
bool mappingFound;
while(argc > 0) {
mappingFound = false;
for(const auto &s : simpleArgs) {
if(s.size() == 1) {
temp = std::string("-") + s;
} else {
temp = std::string("--") + s;
}
if(std::strcmp(temp.c_str(), argv[0]) == 0) {
mapping.insert({s, ""});
mappingFound = true;
break;
}
}
if(mappingFound) {
--argc; ++argv;
continue;
}
for(const auto &s : pairedArgs) {
if(s.size() == 1) {
temp = std::string("-") + s;
} else {
temp = std::string("--") + s;
}
if(std::strncmp(temp.c_str(), argv[0], temp.size()) == 0) {
std::string arg;
if(argv[0][temp.size()] == '=') {
arg = argv[0] + temp.size() + 1;
} else {
if(argc > 1) {
--argc;
++argv;
arg = argv[0];
} else {
throw std::invalid_argument("Paired arg missing pair");
}
}
mapping.insert({s, arg});
mappingFound = true;
break;
}
}
if(!mappingFound) {
throw std::invalid_argument("Got invalid arg");
}
--argc; ++argv;
}
return mapping;
}

View file

@ -1,16 +0,0 @@
#ifndef GREEDY_TEXT_JUSTIFICATION_ARG_PARSE_HPP
#define GREEDY_TEXT_JUSTIFICATION_ARG_PARSE_HPP
#include <string>
#include <unordered_map>
#include <vector>
namespace ArgParse {
std::unordered_map<std::string, std::string> parseArgs(
int argc,
char **argv,
const std::vector<std::string> &simpleArgs,
const std::vector<std::string> &pairedArgs);
} // namespace ArgParse
#endif

152
cpp_impl/src/helpers.cpp Normal file
View file

@ -0,0 +1,152 @@
#include "helpers.hpp"
#include <cstring>
#include <stdexcept>
#include <algorithm>
#include <iostream>
std::unordered_map<std::string, std::string> Helpers::parseArgs(
int argc,
char **argv,
const std::vector<std::string> &simpleArgs,
const std::vector<std::string> &pairedArgs) {
std::unordered_map<std::string, std::string> mapping;
--argc; ++argv;
std::string temp;
bool mappingFound;
while(argc > 0) {
mappingFound = false;
for(const auto &s : simpleArgs) {
if(s.size() == 1) {
temp = std::string("-") + s;
} else {
temp = std::string("--") + s;
}
if(std::strcmp(temp.c_str(), argv[0]) == 0) {
mapping.insert({s, ""});
mappingFound = true;
break;
}
}
if(mappingFound) {
--argc; ++argv;
continue;
}
for(const auto &s : pairedArgs) {
if(s.size() == 1) {
temp = std::string("-") + s;
} else {
temp = std::string("--") + s;
}
if(std::strncmp(temp.c_str(), argv[0], temp.size()) == 0) {
std::string arg;
if(argv[0][temp.size()] == '=') {
arg = argv[0] + temp.size() + 1;
} else {
if(argc > 1) {
--argc;
++argv;
arg = argv[0];
} else {
throw std::invalid_argument("Paired arg missing pair");
}
}
mapping.insert({s, arg});
mappingFound = true;
break;
}
}
if(!mappingFound) {
throw std::invalid_argument("Got invalid arg");
}
--argc; ++argv;
}
return mapping;
}
std::vector<std::string> Helpers::strSplit(const std::string &s, std::vector<char> delimeters) {
std::vector<std::string> result;
std::string temp;
std::sort(delimeters.begin(), delimeters.end());
for(char c : s) {
if(std::binary_search(delimeters.begin(), delimeters.end(), c)) {
if(!temp.empty()) {
result.push_back(temp);
temp.clear();
}
} else {
temp += c;
}
}
if(!temp.empty()) {
result.push_back(temp);
}
return result;
}
void Helpers::printDividers(unsigned long long width) {
for(unsigned long long i = 0; i < width; ++i) {
if((i + 1) % 5 == 0) {
std::cout << "+";
} else {
std::cout << "-";
}
}
std::cout << std::endl;
}
void Helpers::printGreedyTextJustification(unsigned long long width, const std::vector<std::string> &tokens) {
const auto printCurrentLine = [width] (std::vector<std::string> &words) {
unsigned long long spaces = width;
for(const auto &word : words) {
if(word.size() > spaces) {
spaces = 0;
} else {
spaces -= word.size();
}
}
for(unsigned int i = 0; i < words.size(); ++i) {
std::cout << words.at(i);
for(unsigned int j = 0; j < spaces / words.size(); ++j) {
std::cout << ' ';
}
if(i == words.size() - 1) {
for(unsigned int j = 0; j < spaces % words.size(); ++j) {
std::cout << ' ';
}
}
}
std::cout << std::endl;
words.clear();
};
std::vector<std::string> currentLine;
unsigned long long currentToken = 0;
unsigned long long size = 0;
while(true) {
size += tokens.at(currentToken).size();
if(size + 1 >= width) {
printCurrentLine(currentLine);
size = 0;
continue;
} else {
currentLine.push_back(tokens.at(currentToken));
size += 1;
++currentToken;
if(currentToken >= tokens.size()) {
break;
}
}
}
if(!currentLine.empty()) {
printCurrentLine(currentLine);
}
}

22
cpp_impl/src/helpers.hpp Normal file
View file

@ -0,0 +1,22 @@
#ifndef GREEDY_TEXT_JUSTIFICATION_ARG_HELPERS_HPP
#define GREEDY_TEXT_JUSTIFICATION_ARG_HELPERS_HPP
#include <string>
#include <unordered_map>
#include <vector>
namespace Helpers {
std::unordered_map<std::string, std::string> parseArgs(
int argc,
char **argv,
const std::vector<std::string> &simpleArgs,
const std::vector<std::string> &pairedArgs);
std::vector<std::string> strSplit(const std::string &s, std::vector<char> delimeters);
void printDividers(unsigned long long width);
void printGreedyTextJustification(unsigned long long width, const std::vector<std::string> &tokens);
} // namespace Helpers
#endif

View file

@ -1,13 +1,44 @@
#include <iostream>
#include <string>
#include <vector>
#include "argparse.hpp"
#include "helpers.hpp"
int main(int argc, char **argv) {
auto parsed = ArgParse::parseArgs(argc, argv, {"a", "b"}, {"apple"});
auto parsed = Helpers::parseArgs(argc, argv, {}, {"w", "string"});
for(auto pair : parsed) {
std::cout << pair.first << ", " << pair.second << std::endl;
// for(auto pair : parsed) {
// std::cout << pair.first << ", " << pair.second << std::endl;
// }
unsigned long long width;
if(auto iter = parsed.find("w"); iter != parsed.end()) {
width = std::stoull(iter->second);
std::cout << "Got width == " << width << std::endl;
} else {
return 1;
}
std::string str;
if(auto iter = parsed.find("string"); iter != parsed.end()) {
str = iter->second;
std::cout << "Got string == \"" << str << "\"" << std::endl;
} else {
return 2;
}
Helpers::printDividers(width);
std::vector<std::string> tokens = Helpers::strSplit(str, {' ', '\n', '\r'});
// for(auto token : tokens) {
// std::cout << token << '\n';
// }
// std::cout << std::endl;
Helpers::printGreedyTextJustification(width, tokens);
Helpers::printDividers(width);
return 0;
}