You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 6 месеци
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
  5. *
  6. * Use of this source code is governed by MIT license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include <stdlib.h>
  11. #include <memory.h>
  12. #if !defined(_WIN32)
  13. #include <dirent.h>
  14. #endif //!defined(_WIN32)
  15. #include <set>
  16. #include "Util/CMD.h"
  17. #include "Util/util.h"
  18. #include "Util/logger.h"
  19. #include "Util/File.h"
  20. #include "Util/uv_errno.h"
  21. using namespace std;
  22. using namespace toolkit;
  23. class CMD_main : public CMD {
  24. public:
  25. CMD_main() {
  26. _parser.reset(new OptionParser(nullptr));
  27. (*_parser) << Option('r',/*该选项简称,如果是\x00则说明无简称*/
  28. "rm",/*该选项全称,每个选项必须有全称;不得为null或空字符串*/
  29. Option::ArgNone,/*该选项后面必须跟值*/
  30. nullptr,/*该选项默认值*/
  31. false,/*该选项是否必须赋值,如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
  32. "是否删除或添加bom,默认添加bom头",/*该选项说明文字*/
  33. nullptr);
  34. (*_parser) << Option('f',/*该选项简称,如果是\x00则说明无简称*/
  35. "filter",/*该选项全称,每个选项必须有全称;不得为null或空字符串*/
  36. Option::ArgRequired,/*该选项后面必须跟值*/
  37. "c,cpp,cxx,c,h,hpp",/*该选项默认值*/
  38. true,/*该选项是否必须赋值,如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
  39. "文件后缀过滤器",/*该选项说明文字*/
  40. nullptr);
  41. (*_parser) << Option('i',/*该选项简称,如果是\x00则说明无简称*/
  42. "in",/*该选项全称,每个选项必须有全称;不得为null或空字符串*/
  43. Option::ArgRequired,/*该选项后面必须跟值*/
  44. nullptr,/*该选项默认值*/
  45. true,/*该选项是否必须赋值,如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
  46. "文件夹或文件",/*该选项说明文字*/
  47. nullptr);
  48. }
  49. virtual ~CMD_main() {}
  50. virtual const char *description() const {
  51. return "添加或删除bom";
  52. }
  53. };
  54. static const char s_bom[] = "\xEF\xBB\xBF";
  55. void add_or_rm_bom(const char *file,bool rm_bom){
  56. auto file_str = File::loadFile(file);
  57. if(rm_bom){
  58. file_str.erase(0, sizeof(s_bom) - 1);
  59. }else{
  60. file_str.insert(0,s_bom,sizeof(s_bom) - 1);
  61. }
  62. File::saveFile(file_str,file);
  63. }
  64. void process_file(const char *file,bool rm_bom){
  65. std::shared_ptr<FILE> fp(fopen(file, "rb+"), [](FILE *fp) {
  66. if (fp) {
  67. fclose(fp);
  68. }
  69. });
  70. if (!fp) {
  71. WarnL << "打开文件失败:" << file << " " << get_uv_errmsg();
  72. return;
  73. }
  74. bool have_bom = rm_bom;
  75. char buf[sizeof(s_bom) - 1] = {0};
  76. if (sizeof(buf) == fread(buf,1,sizeof(buf),fp.get())) {
  77. have_bom = (memcmp(s_bom, buf, sizeof(s_bom) - 1) == 0);
  78. }
  79. if (have_bom == !rm_bom) {
  80. // DebugL << "无需" << (rm_bom ? "删除" : "添加") << "bom:" << file;
  81. return;
  82. }
  83. fp = nullptr;
  84. add_or_rm_bom(file,rm_bom);
  85. InfoL << (rm_bom ? "删除" : "添加") << "bom:" << file;
  86. }
  87. /// 这个程序是为了统一添加或删除utf-8 bom头
  88. int main(int argc, char *argv[]) {
  89. CMD_main cmd_main;
  90. try {
  91. cmd_main.operator()(argc, argv);
  92. } catch (std::exception &ex) {
  93. cout << ex.what() << endl;
  94. return -1;
  95. }
  96. bool rm_bom = cmd_main.hasKey("rm");
  97. string path = cmd_main["in"];
  98. string filter = cmd_main["filter"];
  99. auto vec = split(filter,",");
  100. set<string> filter_set;
  101. for(auto ext : vec){
  102. filter_set.emplace(ext);
  103. }
  104. bool no_filter = filter_set.find("*") != filter_set.end();
  105. //设置日志
  106. Logger::Instance().add(std::make_shared<ConsoleChannel>());
  107. File::scanDir(path, [&](const string &path, bool isDir) {
  108. if (isDir) {
  109. return true;
  110. }
  111. if (!no_filter) {
  112. //开启了过滤器
  113. auto pos = strstr(path.data(), ".");
  114. if (pos == nullptr) {
  115. //没有后缀
  116. return true;
  117. }
  118. auto ext = pos + 1;
  119. if (filter_set.find(ext) == filter_set.end()) {
  120. //后缀不匹配
  121. return true;
  122. }
  123. }
  124. //该文件匹配
  125. process_file(path.data(), rm_bom);
  126. return true;
  127. }, true);
  128. return 0;
  129. }