31 class InputError :
public std::runtime_error {
33 explicit InputError(
const std::string& msg) :
std::runtime_error(msg) {}
36 class OutputError :
public std::runtime_error {
38 explicit OutputError(
const std::string& msg) :
std::runtime_error(msg) {}
43 explicit Concatenator(
const po::variables_map& options)
44 : printLineNumbers_(options[
"number"].
as<bool>()) {}
49 bool printLineNumbers()
const {
50 return printLineNumbers_;
54 bool printLineNumbers_;
55 size_t lineNumber_ = 0;
59 [[noreturn]]
void throwOutputError() {
63 [[noreturn]]
void throwInputError() {
69 char* lineBuf =
nullptr;
70 size_t lineBufSize = 0;
76 while ((n =
getline(&lineBuf, &lineBufSize, file)) >= 0) {
78 if ((printLineNumbers_ && printf(
"%6zu ", lineNumber_) < 0) ||
79 fwrite(lineBuf, 1, n, stdout) <
size_t(n)) {
90 auto file = fopen(name.c_str(),
"r");
108 const po::variables_map& options,
109 const std::vector<std::string>& args) {
110 Concatenator concatenator(options);
115 concatenator.cat(stdin);
117 concatenator.cat(name);
119 }
catch (
const InputError& e) {
121 fprintf(stderr,
"cat: %s: %s\n", name.c_str(), e.what());
129 for (
auto& name : args) {
133 }
catch (
const OutputError& e) {
135 1, folly::to<std::string>(
"cat: write error: ", e.what()));
143 const po::variables_map& options,
144 const std::vector<std::string>& args) {
146 const char* sep =
"";
147 for (
auto& arg : args) {
148 if (printf(
"%s%s", sep, arg.c_str()) < 0) {
153 if (!options[
"-n"].as<bool>()) {
154 if (putchar(
'\n') == EOF) {
158 }
catch (
const OutputError& e) {
160 1, folly::to<std::string>(
"echo: write error: ", e.what()));
194 "Concatenate files and print them on standard output",
197 "Concatenate files and print them on standard output.",
202 (
"number,n", po::bool_switch(),
"number all output lines");
209 "Display a line of text",
210 "Display a line of text.",
213 (
",n", po::bool_switch(),
"do not output the trailing newline");
220 return app.
run(argc, argv);
int main(int argc, char *argv[])
void BENCHFUN() getline(size_t iters, size_t arg)
std::string toStdString(const folly::fbstring &s)
boost::program_options::options_description & addCommand(std::string name, std::string argStr, std::string shortHelp, std::string fullHelp, Command command)
GuardImpl guard(ErrorHandler &&handler)
fbstring errnoStr(int err)
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
void addGFlags(ProgramOptionsStyle style=ProgramOptionsStyle::GNU)
int run(int argc, const char *const argv[])
GMockOutputTest ExpectedCall FILE