diff --git a/ts2panda/ts2abc/main.cpp b/ts2panda/ts2abc/main.cpp index 724a6536d26de45f8b9f5638ddd96c2d2cee7141..2fef9f1b9082d16b0dff511d59a1351e01698dd9 100644 --- a/ts2panda/ts2abc/main.cpp +++ b/ts2panda/ts2abc/main.cpp @@ -20,37 +20,31 @@ #include "ts2abc_options.h" #include "ts2abc.h" -int Preprocess(const panda::ts2abc::Options &options, const panda::PandArgParser &argParser, std::string &output, - std::string &data, std::string &usage) +static constexpr int PIPE_FILE_NO = 3; + + +FILE* Preprocess(const panda::ts2abc::Options &options, std::string &output, const panda::PandArgParser &argParser, std::string &usage) { - std::string input; + std::string input{}; + FILE *fp {nullptr}; + if (!options.GetCompileByPipeArg()) { input = options.GetTailArg1(); output = options.GetTailArg2(); - if (input.empty() || output.empty()) { + if (input.empty()) { std::cerr << "Incorrect args number" << std::endl; std::cerr << "Usage example: ts2abc test.json test.abc"<< std::endl; std::cerr << usage << std::endl; std::cerr << argParser.GetHelpString(); - return RETURN_FAILED; + return nullptr; } - if (!HandleJsonFile(input, data)) { - return RETURN_FAILED; - } + fp = fopen(input.c_str(), "r"); } else { output = options.GetTailArg1(); - if (output.empty()) { - std::cerr << usage << std::endl; - std::cerr << argParser.GetHelpString(); - return RETURN_FAILED; - } - - if (!ReadFromPipe(data)) { - return RETURN_FAILED; - } + fp = fdopen(PIPE_FILE_NO, "r"); } - return RETURN_SUCCESS; + return fp; } int main(int argc, const char *argv[]) @@ -88,14 +82,15 @@ int main(int argc, const char *argv[]) return RETURN_FAILED; } - std::string output; - std::string data = ""; + std::string output {}; - if (Preprocess(options, argParser, output, data, usage) == RETURN_FAILED) { + FILE *fp {nullptr}; + fp = Preprocess(options, output, argParser, usage); + if (fp == nullptr) { return RETURN_FAILED; } - if (!GenerateProgram(data, output, options.GetOptLevelArg(), options.GetOptLogLevelArg())) { + if (!GenerateProgram(fp, output, options.GetOptLevelArg(), options.GetOptLogLevelArg())) { std::cerr << "call GenerateProgram fail" << std::endl; return RETURN_FAILED; } diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 1b049e42697342597fd3599f0fdc7b3f56a25a85..c8489571b169d4ae7e078b61fbaec9e159c67579 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "assembly-type.h" #include "assembly-program.h" @@ -877,16 +878,16 @@ static void ParseOptLogLevel(const Json::Value &rootValue) } } -static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue) -{ - for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) { - if ((pos = str.find(oldValue, pos)) != std::string::npos) { - str.replace(pos, oldValue.length(), newValue); - } else { - break; - } - } -} +//static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue) +//{ +// for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) { +// if ((pos = str.find(oldValue, pos)) != std::string::npos) { +// str.replace(pos, oldValue.length(), newValue); +// } else { +// break; +// } +// } +//} static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program &prog) { @@ -980,42 +981,78 @@ static int ParseSmallPieceJson(const std::string &subJson, panda::pandasm::Progr return RETURN_SUCCESS; } -static bool ParseData(const std::string &data, panda::pandasm::Program &prog) -{ - if (data.empty()) { - std::cerr << "the stringify json is empty" << std::endl; - return false; +class BufferedPipe { +public: + explicit BufferedPipe(FILE * pipe): + pipe_(pipe), curPos_(0), curRdSize_(0) {}; + + char GetChar(); + bool Eof(); +private: + static constexpr size_t BUFFER_SIZE = 1024; + FILE *pipe_{nullptr}; + size_t curPos_{0}; + size_t curRdSize_{0}; + char buffer_[BUFFER_SIZE]{0}; +}; + +char BufferedPipe::GetChar() { + if (curPos_ >= curRdSize_) { + curRdSize_ = fread(buffer_, sizeof(char), sizeof(buffer_), pipe_); + curPos_ = 0; } + return buffer_[curPos_++]; +} - size_t pos = 0; - bool isStartDollar = true; +bool BufferedPipe::Eof() { + if (!feof(pipe_)) { + return false; + } + if (curPos_ < curRdSize_) { + return false; + } + return true; +} - for (size_t idx = 0; idx < data.size(); idx++) { - if (data[idx] == '$' && (idx ==0 || data[idx - 1] != '#')) { - if (isStartDollar) { - pos = idx + 1; - isStartDollar = false; - continue; +static bool ParseData(FILE *fp, panda::pandasm::Program &prog) { + bool statementState {true}; + char preCh{'\0'}; + std::string subJson{}; + BufferedPipe bp(fp); + + while (!bp.Eof()) { + char ch = bp.GetChar(); + if (ch == '$' && preCh != '#') { + if (!subJson.empty()) { + if (ParseSmallPieceJson(subJson, prog)) { + std::cerr << "fail to parse stringify json" << std::endl; + return false; + } + subJson.clear(); + statementState = false; + } else { + statementState = true; } + continue; + } - std::string subJson = data.substr(pos, idx - pos); - ReplaceAllDistinct(subJson, "#$", "$"); - if (ParseSmallPieceJson(subJson, prog)) { - std::cerr << "fail to parse stringify json" << std::endl; - return false; - } - isStartDollar = true; + if (ch == '$' && preCh == '#') { + subJson.pop_back(); } - } + if (statementState) { + subJson += (ch); + preCh = ch; + } + } return true; } -bool GenerateProgram(const std::string &data, std::string output, int optLevel, std::string optLogLevel) +bool GenerateProgram(FILE* fp, std::string output, int optLevel, std::string optLogLevel) { panda::pandasm::Program prog = panda::pandasm::Program(); prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT; - if (!ParseData(data, prog)) { + if (!ParseData(fp, prog)) { std::cerr << "fail to parse Data!" << std::endl; return false; } @@ -1057,68 +1094,3 @@ bool GenerateProgram(const std::string &data, std::string output, int optLevel, Logd("Successfully generated: %s\n", output.c_str()); return true; } - -bool HandleJsonFile(const std::string &input, std::string &data) -{ - auto inputAbs = panda::os::file::File::GetAbsolutePath(input); - if (!inputAbs) { - std::cerr << "Input file does not exist" << std::endl; - return false; - } - auto fpath = inputAbs.Value(); - if (panda::os::file::File::IsRegularFile(fpath) == false) { - std::cerr << "Input must be either a regular file or a directory" << std::endl; - return false; - } - - std::ifstream file; - file.open(fpath); - if (file.fail()) { - std::cerr << "failed to open:" << fpath << std::endl; - return false; - } - - file.seekg(0, std::ios::end); - int64_t fileSize = file.tellg(); - if (fileSize == -1) { - std::cerr << "failed to get position in input sequence: " << fpath << std::endl; - return false; - } - file.seekg(0, std::ios::beg); - auto buf = std::vector(fileSize); - file.read(reinterpret_cast(buf.data()), fileSize); - data = buf.data(); - buf.clear(); - file.close(); - Logd(data.c_str()); - Logd("----------------------------------"); - - return true; -} - -bool ReadFromPipe(std::string &data) -{ - const size_t bufSize = 4096; - // the parent process open a pipe to this child process with fd of 3 - const size_t fd = 3; - - char buff[bufSize + 1]; - int ret = 0; - - while ((ret = read(fd, buff, bufSize)) != 0) { - if (ret < 0) { - std::cerr << "Read pipe error" << std::endl; - return false; - } - buff[ret] = '\0'; - data += buff; - } - - if (data.empty()) { - std::cerr << "Nothing has been read from pipe" << std::endl; - return false; - } - - Logd("finish reading from pipe"); - return true; -} diff --git a/ts2panda/ts2abc/ts2abc.h b/ts2panda/ts2abc/ts2abc.h index 691e87a0de11bf81af137d734610d46d65c92005..392b5cb48903759ed6c7bcd86e434887fe3b3317 100644 --- a/ts2panda/ts2abc/ts2abc.h +++ b/ts2panda/ts2abc/ts2abc.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "assembly-type.h" #include "assembly-program.h" @@ -47,7 +48,7 @@ enum class OptLevel { bool HandleJsonFile(const std::string &input, std::string &data); bool ReadFromPipe(std::string &data); -bool GenerateProgram(const std::string &data, std::string output, +bool GenerateProgram(FILE *fp, std::string output, int optLevel, std::string optLogLevel); bool GetDebugLog();