[译]另一个枚举查看器
By robot-v1.0
本文链接 https://www.kyfws.com/applications/another-enum-viewer-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 7 分钟阅读 - 3387 个词 阅读量 0[译]另一个枚举查看器
原文地址:https://www.codeproject.com/Articles/1487/Another-Enum-Viewer
原文作者:Tim Finer
译文由本站 robot-v1.0 翻译
前言
An article on the usage and design of another Enum Viewer
有关另一个枚举查看器的用法和设计的文章
另一个枚举查看器(Another Enum Viewer)
用法(Usage)
发展历程(Development)
1.问题(1. The problem)
我的日常工作是编写通过Win32通信通道(rs232,rs485,tcp/ip等)与嵌入式设备对话的软件.为了最小化向后兼容性和协议灵活性,我们设计了使用长度和标识符的消息传递协议.消息均在16位中具有唯一标识符(My day job is writing software that talks to embedded devices via Win32 communication channels (rs232, rs485, tcp/ip, etc.). In order to minimize backwards compatibility and protocol flexibility, we designed a message passing protocol using lengths and identifiers. Messages all have a unique identifier in a 16 bit) enum
头文件中定义的值.我正在编写设备模拟器,并希望(value defined in a header file. I am in the process of writing a device simulator and wanted the) enum
查看原始消息时的值.我见过的所有工具都无法处理注释,(values when looking at raw messages. None of the tools I’ve seen handle comments,) #defines
,类内的枚举,(, enums within classes, enums with) enum
分配等Visual C ++ IDE,浏览器和调试器不显示(assignments, etc.The Visual C++ IDE, browser and debugger don’t show) enum
值(调试器一次执行一次,如果(values (the debugger does one at a time if) typedef'
d).(d).)
2.解决方案(2. The solution)
我认为必须有一些C ++解析器可以为枚举查看器提供基础.在Google上进行了快速搜索(I figured that there must be some C++ parser out there somewhere that might provide a basis for an enum viewer. A quick search on google turned up) 约翰基于PCCTS的C ++解析器页面(John’s PCCTS-based C++ Parser Page) .(.)
整齐!一个C ++解析器!我下载并尝试构建代码,但是编译停止,并显示有关STL分配器的错误消息.尝试哄骗解析器使用后(Neat! A C++ parser! I downloaded and attempted to build the code but the compilation stopped with error messages regarding STL allocators. After trying to coax the parser into using) STLPort
,我放弃了使用默认的MSVC STL并进行了全部编译.(, I gave up and used the default MSVC STL and it all compiled.)
然后我转向了文档(你们中有些人可能现在正在窃笑,将其停止).浏览文档后,我有些沮丧,并且对正则表达式进行了简短的调情.考虑到所有声明/定义枚举的方法,这使我回到了解析器中.再次查看目录,我注意到一个名为cpp_test的示例应用程序.我编译并针对带有很多枚举的标头运行它.结果令人鼓舞,所有枚举的名称都与它们的递归值一起显示(Then I turned to the docs (some of you are probably snickering right now, stop it). After looking through the docs I got a little frustrated and had a brief flirtation with regular expressions. Thinking about all ways of declaring / defining enums chased me back to the parser. Looking at the directories again I noticed a sample application called cpp_test. I compiled and ran it against a header with a lot of enums. The results were encouraging, all of the enum’s names were displayed along with their recursive values) eRED = (((10)+1)+1)
.(.)
深入研究代码,由于Joshua C. Jensen出色的Workspace Whiz,我找到了转储函数并查找了各个类成员的定义.(Digging into the code, I found the dumping functions and looked up the definitions of the various class members thanks to Joshua C. Jensen’s very fine Workspace Whiz.)
我只需要派生两个新类,就可以将函数从私有移到受保护,并且我有一个命令行应用程序,可以将标头转换为枚举及其值的ascii文件.(I only had to derive two new classes, move a function from private to protected, and I had a command line app that could turn a header into an ascii file of enums and their values.)
3.显示数据(3. Displaying the data)
那样酷,我仍然想对枚举名称或它们的值进行排序.我想要一个能够以十六进制浏览,排序和显示数据的GUI.嗯…在过去的几年中,我已经使用ListView控件做了很多工作,这似乎很合适(就像当您拿着锤子时一切看起来像钉子一样).我生成了一个AppWizard MFC SDI应用程序,并开始进行逗号分隔值文件的解析.(As cool as that was, I still wanted to sort enum names or their values. I wanted a GUI capable of browsing, sorting and displaying data in hex. Hmm… I’ve done quite a bit of work using ListView controls in the last couple of years and this seemed a good fit (just like everything looks like a nail when you’re holding a hammer).I generated an AppWizard MFC SDI app and started working on the parsing of comma separated value files.)
由于以下三个原因,我决定将ListView虚拟化:(I decided to make the ListView virtual for these three reasons in order:)
- 更加灵活,所有格式都在显示时完成(More flexible, all formatting is done at the time of display)
- 更少的内存使用(Less memory Usage)
- 排序速度更快(Sort works much faster)
虚拟ListView的重点在于使应用程序在内存中维护listview的字符串表示形式.为此,我使用了二维(The whole point of a virtual ListView is so the application maintains the string representations of the listview in memory. In that end, I used a two dimensional)
std::vector
的(of)CString
用于从文档中缓存数据.我用(s to cache data from the document. I use the)WM_NOTIFY
信息(message)LVN_ODCACHEHINT
初始化缓存的大小和内容. ListView响应(to initialize the size and content of the cache. The ListView responds to the)WM_NOTIFY
信息(message)LVN_GETDISPINFO
通过分发指向缓存的指针(by handing out pointers to cached)CString
的缓冲区通过(’s buffers via)GetBuffer()
.我本来可以用(. I could have used)std::string
,但不想使用来将整数转换为十进制和十六进制(, but did not want to convert integers into decimal and hex using)std::stringstream
当一个简单的电话(when a simple call to)CString::Format
可用于.有关更多详细信息,请参见enum_view.cpp中的代码.在解决了视图问题之后,我继续实施文档.(could be used. For more details, see the code in enum_view.cpp.Having settled the view, I moved on to implementing the document.)
虚拟视图所需的两个重要事项是初始化的行数和用于馈送缓存的单个行访问.(Two important things that virtual views need are the row count for initialization and individual row access to feed the cache.)
计数行(Counting Rows)
列表视图中的每一行对应于解析器输出文件中的一行.每行看起来像:(Each row in the listview corresponds to a line in the parser output file. Each line looks like:)
enum name,value\r\n
因此,文档中\ n的数量就是记录的数量.使用C ++标准库的一种简单方法:(Therefore, the number of \n’s in the document is the number of records. An easy way to do this using the C++ standard library:)
size_t lineCount = 0;
// ignore all characters up to '\n', extract '\n', toss it, advance
while ( m_fileIn.ignore(std::numeric_limits<int>::max(), '\n') )
++lineCount;
其中m_fileIn是任何istream.(Where m_fileIn is any istream.)
个人行访问(Individual Row Access)
对于C ++ iostream而言,这是毫无道理的.关于使用的好处之一(This is a no brainer for C++ iostreams. One of the nice things about using) iostream
提取程序的意思是,对提取程序本身进行布尔测试可以隐含提取程序的状态.看到马歇尔`克莱恩(Marshall Cline)的出色表现(extractors is that the status of an extraction can be implied from doing a boolean test on the extraction itself. See Marshall Cline’s excellent) C ++常见问题(C++ FAQ) 有关详细信息.(for details.)
// in case the stream was in an error state (at the end of file for example)
m_fileIn.clear();
// using an index is waaaaay faster.
m_fileIn.seekg( fileOffset );
std::string strName("");
parsed = std::getline(m_fileIn, strName, ',') && m_fileIn >> value;
// Convert std::string into CString
if (parsed)
name = strName.c_str();
第一次获取记录时,我从头开始查找文件,然后递增到请求的索引.这使视图变慢了!我通过建立文件偏移量索引并按需查找文件,大大加快了工作速度.(On my first cut at getting the records, I seeked the file to the beginning, then counted up to the requested index. This made the view pretty slow! I sped things up considerably by making an index of file offsets and seeking to them on demand.)
然后,我将打开文件的请求连接起来,以生成一个新的枚举解析器进程,并为其传递一个临时文件名.(I then wired up the request for open file to spawn a new process of the enum parser passing it a temporary file name.)
排序(Sorting)
我在(I read this really useful tip in the) C/C ++用户杂志(C/C++ Users Journal) 有关通用STL索引创建功能的信息. Herb Sutter在上对代码进行了很好的源代码审查(about a generic STL index creation function. Herb Sutter did a good source code review on the code over at) 本周大师(Guru of the Week) 有很多改进.我实现了其中一些并添加了自己的一个(有关详细信息,请参见代码).功能(with many improvements. I implemented a few of them and added one of my own (see the code for details). The function) create_index
接受_any_迭代器序列,对它们进行排序,并填写排序结果的索引号.该视图围绕这些索引序列之一,并使用它来显示数据.如果当前列已经排序,则索引顺序将简单地颠倒.多亏了精美的正交STL.(takes any sequence of iterators, applies a sort on them, and fills in index numbers of the sort result. The view keeps around one of these index sequences and uses it to display the data. If the current column is already sorted, then the index order is simply reversed. All thanks to the beautifully orthogonal STL.)
最近使用的文件(Most Recently Used File)
自从(Since the) CDocument
使用临时文件,MRU列表将获取所有这些不再存在的临时文件名.该应用会删除这些内容并添加标题名称.(uses temp files, the MRU list gets all these temp file names that no longer exist. The app removes these and adds the header name instead.)
而已.如有任何疑问,请检查代码.如果您发现任何错误,也请告诉我.我什至可以修复它们. =)(That’s it. Please check out the code if you have any questions. If you find any bugs, let me know too. I might even fix them. =))
顺便说一句,如果可以选择使用MFC还是使用标准C ++库方法,我将更喜欢该标准.我的理由是:(As an aside, if given the choice between using an MFC or a standard C++ library method, I’ll prefer the standard. My reasoning is that:)
- 标准库的第三方文档要好得多(我将以Austern,Josuttis等人取代任何MFC作者)(3rd Party documentation for the standard library is much better (I’ll take Austern, Josuttis, et al. over any MFC author))
- 标准库接口更加一致和正交(Standard library interfaces are much more consistent and orthogonal)
- 更灵活的平台/编译器支持(More flexible platform / compiler support)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C++ VC6 Windows MFC Visual-Studio Dev 新闻 翻译