使用正则表达式的 Autosar 标准兼容方式

Autosar standard-compilant way to use regex

我需要解析类似 URI 的字符串。此 URI 特定于项目并对应于“scheme://path/to/file”,其中从文件系统的角度来看,路径应该是语法正确的文件路径。为此,std::regex 与模式 R"(^(r[o|w])\:\/\/(((?!$|\~|\.{2,}|\/$).)+)$)".

一起使用

它工作正常,但代码分析器认为它不合规,因为 $ 字符不属于 C++ 语言标准基本源字符集:

AUTOSAR C++14 A2-3-1 (Required) Only those characters specified in the C++ Language Standard basic source character set shall be used in the source code.

此规则的例外情况(根据 Autosar Guidelines):

It is permitted to use other characters inside the text of a wide string and a UTF-8 encoded string literal.

wchar_t 被其他规则禁止,虽然它与 UTF-8 string 一起工作(但它在代码中看起来很难看且不可读,而且我担心它不安全)。

谁能帮我解决这个问题,或者std::regex这不是最好的解决方案,那什么更好?

使用 UTF-8 字符串文字还有其他缺点吗?

P.S。我需要 $ 来确保(在解析阶段)路径不是目录并且它不包含 /../~$ 的 none , 所以我不能跳过它。

我觉得为了满足分析器而让代码变得更糟会适得其反,而且很可能违反了指南的精神,所以我故意忽略了解决涉及构建正则表达式字符串的问题的方法一种令人费解的方式,因为您所做的是构建此类正则表达式字符串的最佳方式。

Could someone help me with workaround or std::regex here is not the best solution, then what would be better?

选项A:编写一个简单的验证函数:

我真的很惊讶如此严格的准则甚至首先允许正则表达式。众所周知,它们很难审计、调试和维护。

你可以很容易地用实际代码表达相同的逻辑,这不仅会满足分析者的需求,而且更符合指南的精神。最重要的是,它会编译得更快,而且可能 运行 也更快。

根据粗略阅读您的正则表达式得出的结论。 (请不要在没有 运行 通过一系列测试的情况下使用它,我确实没有):

bool check_and_remove_path_prefix(std::string_view& path) {
  constexpr std::array<std::string_view, 2> valid_prefixes = { 
    R"(ro://)", 
    R"(rw://)"
  };

  for(auto p: valid_prefixes) {
    if(path.starts_with(p)) {
      path.remove_prefix(p.size());
      return true;
    }
  }
  return false;
}

bool is_valid_path_elem_char(char c) {
  // This matches your regex, but is probably wrong, as it will accept a bunch of control characters.
  // N.B. \x24 is the dollar sign character
  return c != '~' && c != '\x24' && c != '\r' && c != '\n';
}
 
bool is_valid_path(std::string_view path) {
  if(!check_and_remove_path_prefix(path)) { return false; }

  char prev_c = '[=10=]';
  bool current_segment_empty = true;
  for(char c : path) {
    // Disallow two or more consecutive periods
    if( c == '.' && prev_c == '.') { return false; }

    // Disallow empty segments
    if(c == '/') {
      if(current_segment_empty) { return false; }
      current_segment_empty = true;
    }
    else {
      if(!is_valid_path_elem_char(c)) { return false; }
      current_segment_empty = false;
    }
    
    prev_c = c;
  }

  return !current_segment_empty;
}

选项 B: 不要打扰检查

从我们的角度来看,很难确定该选项是否适合您,但对于每一个意图和目的,格式错误的路径和格式正确的路径之间的区别并不指向一个有效的文件是没有实际意义的。

所以只要使用路径就好像它是有效的一样,无论如何你应该处理由错误形成的路径导致的错误。