Guest User

Untitled

a guest
Jul 20th, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.26 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #define _CRT_NONSTDC_NO_DEPRECATE
  3. #include <string>
  4. #include <vector>
  5. #include <stdio.h>
  6. #include <io.h>
  7. #include <fcntl.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <errno.h>
  11.  
  12. using std::string, std::string_view, std::vector;
  13.  
  14. struct Config {
  15. const char *markdownLabel = "markdown";
  16. const char *codeLabel = "cpp";
  17. const char *markdownExt = ".md";
  18. const char *codeExt = ".cpp";
  19. const char *openCodeBlock = "```";
  20. const char *closeCodeBlock = "````\n";
  21. const char *openCommentBlock = "/***";
  22. const char *closeCommentBlock = "****/\n";
  23. };
  24.  
  25. string readFile(const string &path) {
  26. string result;
  27. if (int fileDescriptor; (fileDescriptor = open(path.data(), _O_RDONLY | _O_TEXT)) != -1) {
  28. if (struct stat fileStat; fstat(fileDescriptor, &fileStat) == 0) {
  29. result.resize(fileStat.st_size);
  30. result.resize(read(fileDescriptor, &result[0], (int)result.size()));
  31. }
  32. close(fileDescriptor);
  33. }
  34. return result;
  35. }
  36.  
  37. bool writeFile(const string &path, const string &text) {
  38. int fileDescriptor = open(path.data(), O_WRONLY | O_CREAT | O_TRUNC | _O_TEXT, 0640);
  39. if (fileDescriptor == -1)
  40. return false;
  41. int written = write(fileDescriptor, &text[0], (int)text.size());
  42. int closeResult = close(fileDescriptor);
  43. return written == text.size() && closeResult != -1;
  44. }
  45.  
  46. string join(const vector<string_view> &spans, const char *openBlock, const char *sourceLanguage, const char *closeBlock) {
  47. auto joinInto = [](char *dest, const vector<string_view> &spans, const char *openBlock, const char *sourceLanguage, const char *closeBlock) {
  48. size_t totalSize = 0;
  49. char *cursor = dest;
  50. size_t maxSize = dest == nullptr ? 0 : size_t(-1);
  51. bool comment = true;
  52. for (auto span : spans) {
  53. if (dest != nullptr)
  54. cursor = dest + totalSize;
  55. if (span.size() > 0) {
  56. if (comment)
  57. totalSize += snprintf(cursor, maxSize, "%s %s\n%.*s%s", openBlock, sourceLanguage, (int)span.size(), span.data(), closeBlock);
  58. else
  59. totalSize += snprintf(cursor, maxSize, "%.*s", (int)span.size(), span.data());
  60. }
  61. comment = !comment;
  62. }
  63. return totalSize;
  64. };
  65. size_t totalSize = joinInto(nullptr, spans, openBlock, sourceLanguage, closeBlock);
  66. string result(totalSize, '\0');
  67. joinInto(&result[0], spans, openBlock, sourceLanguage, closeBlock);
  68. return result;
  69. }
  70.  
  71. string convert(const string &source,
  72. const char *destLanguage, const char *sourceLanguage,
  73. const char *destOpenBlock, const char *destCloseBlock,
  74. const char *srcOpenBlock, const char *srcCloseBlock) {
  75. vector<string_view> spans;
  76. const char *token = srcOpenBlock;
  77. const string::size_type strlenSrcCloseBlock = strlen(srcCloseBlock);
  78. const string::size_type sourceSize = source.size();
  79. for (string::size_type spanStart = 0, spanEnd = 0; spanEnd < sourceSize;) {
  80. spanEnd = source.find(token, spanStart);
  81. if (spanEnd == string::npos)
  82. spanEnd = sourceSize;
  83. if (token == srcCloseBlock)
  84. spanStart = source.find('\n', spanStart) + 1;
  85. string_view span = string_view(&source[spanStart], spanEnd - spanStart);
  86. spans.push_back(span);
  87.  
  88. if (token == srcCloseBlock)
  89. spanEnd += strlenSrcCloseBlock;
  90. token = token == srcOpenBlock ? srcCloseBlock : srcOpenBlock;
  91. spanStart = spanEnd;
  92. }
  93. string result = join(spans, destOpenBlock, sourceLanguage, destCloseBlock);
  94. return result;
  95. }
  96.  
  97. string codeFromMarkdown(const string &markdown, const Config &config) {
  98. return convert(markdown,
  99. config.codeLabel, config.markdownLabel,
  100. config.openCommentBlock, config.closeCommentBlock,
  101. config.openCodeBlock, config.closeCodeBlock);
  102. }
  103.  
  104. string markdownFromCode(const string &code, const Config &config) {
  105. return convert(code,
  106. config.markdownLabel, config.codeLabel,
  107. config.openCodeBlock, config.closeCodeBlock,
  108. config.openCommentBlock, config.closeCommentBlock);
  109. }
  110.  
  111. bool endsWith(const string s, const char *x) { return s.rfind(x) == (s.size() - strlen(x)); }
  112.  
  113. int main(int argc, char *argv[]) {
  114. Config config;
  115. int errors = 0;
  116. for (int arg = 1; arg < argc; arg++) {
  117. string srcPath(argv[arg]);
  118. const char *mdExt = config.markdownExt, *codeExt = config.codeExt;
  119. const char *srcExt = endsWith(srcPath, mdExt) ? mdExt : codeExt;
  120. const char *dstExt = srcExt == mdExt ? codeExt : mdExt;
  121. string srcText = readFile(srcPath.data());
  122. string dstText = dstExt == mdExt ? markdownFromCode(srcText, config)
  123. : codeFromMarkdown(srcText, config);
  124. if (dstText.empty()) {
  125. errors++;
  126. fprintf(stderr, "Failed to convert %.*s\n", (int)srcPath.size(), srcPath.data());
  127. }
  128. else {
  129. string dstPath = srcPath.replace(srcPath.rfind(srcExt), strlen(srcExt), dstExt);
  130. if (!writeFile(dstPath.data(), dstText)) {
  131. errors++;
  132. fprintf(stderr, "Failed to write %.*s\n", (int)dstPath.size(), dstPath.data());
  133. }
  134. }
  135. }
  136. return errors;
  137. }
Add Comment
Please, Sign In to add comment