简体   繁体   English

std::codecvt do_out 在 1:N 转换后跳过字符

[英]std::codecvt do_out skipping characters after 1:N conversions

I've tried to write an automatic indenter, however - it's skipping characters when it added new characters to the stream.但是,我尝试编写一个自动缩进器 - 它在向流中添加新字符时跳过字符。 I've tried debugging it and verified that from_next and to_next as well as from and to are working correctly.我试过调试它并验证 from_next 和 to_next 以及 from 和 to 工作正常。

Surely I've missed something in the specs but here is my code, maybe you an help me:当然,我错过了规范中的某些内容,但这是我的代码,也许您能帮帮我:

  virtual result_t do_out(state_type& state, const intern_type* from, const intern_type* from_end, const intern_type*& from_next,
     extern_type* to, extern_type* to_end, extern_type*& to_next) const override
  {
    auto result = std::codecvt_base::noconv;

    while (from < from_end && to < to_end)
    {
      if (getState(state).missingWhitespaces > 0u && *from != '\n')
      {
        while (getState(state).missingWhitespaces > 0u && to < to_end)
        {
          *to = ' ';
          to++;
          getState(state).missingWhitespaces--;
        }
        
        if (to < to_end)
        {
          result = std::codecvt_base::partial;
        }
        else
        {
          result = std::codecvt_base::partial;
          break;
        }
      }
      else
      {
        *to = *from;
         
        if (*from == '\n')
        {
          getState(state).missingWhitespaces = tabSize * indentLevel;
        }
        
        to++;
        from++;
      }
    }

    from_next = from;
    to_next = to;
   
    return result;
  };

The state object is also working properly.状态对象也正常工作。 The problem only occurs in between function calls.问题只发生在函数调用之间。

Edit: Changing the result after if (to < to_end) to std::codecvt_base::ok doesn't solve the problem either.编辑:将if (to < to_end)后的结果更改为std::codecvt_base::ok也不能解决问题。

After some more digging I found the solution to my problem.经过更多挖掘,我找到了解决问题的方法。 I got a detailed explanation of std::codecvt from this website: http://stdcxx.apache.org/doc/stdlibref/codecvt.html我从这个网站得到了std::codecvt的详细解释: http std::codecvt

It turned out, that I forgot to override these two methods:原来,我忘了覆盖这两个方法:

virtual int do_length(state_type& state, const extern_type *from, const extern_type *end, size_t max) const;
Determines and returns n , where n is the number of elements of extern_type in the source range [from,end) that can be converted to max or fewer characters of intern_type , as if by a call to in(state, from, from_end, from_next, to, to_end, to_next) where to_end == to + max .确定并返回n ,其中n是源范围[from,end)extern_type的元素数,这些元素可以转换为intern_type max或更少字符,就像通过调用in(state, from, from_end, from_next, to, to_end, to_next)其中to_end == to + max

Sets the value of state to correspond to the shift state of the sequence starting at from + n .将 state 的值设置为对应于from + n开始的序列的移位状态。

Function do_length must be called under the following preconditions:必须在以下前提条件下调用函数do_length

state is either initialized to the beginning of a sequence or equal to the result of the previous conversion on the sequence. state要么初始化为序列的开头,要么等于序列上一次转换的结果。

from <= end is well-defined and true. from <= end定义明确且为真。

Note that this function does not behave similarly to the C Standard Library function mbsrtowcs() .请注意,此函数的行为与 C 标准库函数mbsrtowcs() See the mbsrtowcs.cpp example program for an implementation of this function using the codecvt facet.请参阅 mbsrtowcs.cpp 示例程序以了解使用 codecvt 方面的此函数的实现。

virtual int do_max_length() const throw();

Returns the maximum value that do_length() can return for any valid combination of its first three arguments, with the fourth argument max set to 1.返回do_length()可以为其前三个参数的任何有效组合返回的最大值,第四个参数max设置为 1。

I implemented them this way and it worked:我以这种方式实现它们并且它起作用了:

  virtual int do_length(state_type& state, const extern_type* from, const extern_type* end, size_t max) const override
  { 
    auto numberOfCharsAbleToCopy = max;
    
    numberOfCharsAbleToCopy -= std::min(static_cast<unsigned int>(numberOfCharsAbleToCopy), getState(state).missingWhitespaces);
    
    bool newLineToAppend = false;
    for (auto c = from + getState(state).missingWhitespaces; c < end && numberOfCharsAbleToCopy > 0u; c++)
    {
      if (*c == '\n' && !newLineToAppend)
      {
        newLineToAppend = true;
      }
      else if (*c != '\n' && newLineToAppend)
      {
        numberOfCharsAbleToCopy -= std::min(tabSize * indentLevel, numberOfCharsAbleToCopy);
        
        if (numberOfCharsAbleToCopy == 0u)
        {
          break;
        }
        
        newLineToAppend = false;
      }
    }
    
    return numberOfCharsAbleToCopy;
  }
  
  virtual int do_max_length() const throw() override
  {
    return tabSize * indentLevel;
  }
  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何编写 std::codecvt 方面? - How do I write a std::codecvt facet? std :: codecvt :: do_in方法重载与其余的基本方法 - std::codecvt::do_in method overloading vs the rest of base methods codecvt不是std头吗? - Is codecvt not a std header? std :: codecvt和std :: codecvt_utf8有什么区别 - what's the difference between std::codecvt and std::codecvt_utf8 使用std :: codecvt_utf8方面的问题 - trouble with std::codecvt_utf8 facet function 指针地址在转换后是否保持不变? - Do function pointer addresses hold after conversions? 在抛出 'std::out_of_range' 的实例后调用终止 what(): basic_string::at: __n 错误 - terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::at: __n error streams,stream_bufs,codecvt facets和\\ n到\\ r \\ n的翻译 - streams, stream_bufs, codecvt facets and \n to \r\n translation 在抛出 &#39;std::out_of_range&#39; what(): array::at: __n (即 1990878449) &gt;= _Nm (即 5) 的实例后调用终止 - terminate called after throwing an instance of 'std::out_of_range' what(): array::at: __n (which is 1990878449) >= _Nm (which is 5) 比较二进制数输入的字符时,在抛出 'std::out_of_range 的实例后调用终止 - Terminate called after throwing an instance of 'std::out_of_range when comparing characters of binary number input
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM