在WTL80中,AppWiz应用程序向导与AppWizMobile应用程序向导一个区别是在AppWizMobile中使用了SplitCode函数,目的是在编写WTL向导模板时只需要提供.h文件,使用SplitCode可以在需要时将类成员函数转换到.cpp文件中,而AppWiz应用程序向导则是编写了.h和.cpp文件,根据[!if WTL_USE_CPP_FILES]/[!endif]进行预处理,相比之下使用SplitCode对于向导模板的编写简单的多。
VisualFC当前版本(0.80.0601)内置的AppWizard和CodeWizard使用与WTL80的AppWiz同样的处理方式,即使用[!if WTL_USE_CPP_FILES]/[!endif]进行预处理。为简化VisualFC向导模板的编写,我们考虑在VisualFC以后版本中模仿WTL80的AppWizMobile向导提供SplitCode函数来进行处理。WTL80向导的SplitCode函数是用JScript完成的,在这里我们可以用boost::regex进行改写,以便在C++程序中直接使用。其中对于C++类及成员函数分析的正则表达式在两种语言中是完全一致的,具体代码如下:
WTL80的AppWizMobile的SplitCode代码 /****************************************************************************** Description: Add the function members body to a .cpp file and remove them from the matching header. Do nothing if no matching .h file. cppPath: Path name to a .cpp file ******************************************************************************/ function SplitCode(cppPath) { var fso = new ActiveXObject('Scripting.FileSystemObject'); var hPath = cppPath.replace(/.cpp$/, ".h"); if (!fso.FileExists(hPath)) return; var cppFile = fso.GetFile(cppPath); var hFile = fso.GetFile(hPath); var tsh = hFile.OpenAsTextStream(1); var hText = tsh.ReadAll(); tsh.Close(); var tscpp = cppFile.OpenAsTextStream(8); var ClassPattern = /^[ /t]*class[ /t]+(/w+)[/s/S]+?(?:^[ /t]*/};$)/mg var ClassInfo = hText.match(ClassPattern); var numClass = ClassInfo.length; for (nc = 0 ; nc < numClass; nc++) { var ClassText = ClassInfo[nc]; ClassText.match(ClassPattern); var ClassName = RegExp.$1; var FnPattern = /(^(?:[ /t]+/w+)*[ /t]+(/w+)/([^/)]*/))([/s]*/{([^/}]*/{[^/}]*/})*[^/}]*/}+?)/mg var FnPatternIf = /(^(?:#if.+/s+)*(?:[ /t]+/w+)*[ /t]+(/w+)/([^/)]*/))([/s]*/{([^/}]*/{[^/}]*/})*[^/}]*/}+?(?:/s+#e(?:ndif|lif|lse)[^/r/n]*)*)/mg var FnInfo = ClassText.match(FnPatternIf); var numFn = FnInfo.length; for (n = 0 ; n < numFn; n++) { var FnTextIf = FnInfo[n]; var FnTextIf = FnTextIf.match(FnPatternIf); var FnDef = RegExp.$1; var FnName = RegExp.$2; var FnBody = RegExp.$3; var FnFullName = ClassName + "::" + FnName; FnDef = FnDef.replace(FnName, FnFullName); FnDef = FnDef.replace(/^/t(?:/s*virtual/s+)*/, ""); FnBody = FnBody.replace(/^/t/mg, ""); tscpp.Write(FnDef); tscpp.Write(FnBody); tscpp.WriteBlankLines(2); var FnText = FnTextIf.input.match(FnPattern); var FnDecl = RegExp.$1 + ";"; ClassText = ClassText.replace(FnText, FnDecl); } hText = hText.replace(ClassInfo[nc], ClassText); } tscpp.Close(); tsh = hFile.OpenAsTextStream(2); tsh.Write(hText); tsh.Close(); } 使用boost::regex改写的代码,代码稍有不同,没有做文件的处理,直接处理字符串。 void process(const std::string & text) { std::string regstr = "^[ /t]*class[ /t]+(//w+)[//s//S]+?(?:^[ /t]*//};$)"; boost::regex expression(regstr,boost::regbase::JavaScript); std::string::const_iterator start, end; start = text.begin(); end = text.end(); boost::match_results<std::string::const_iterator> what; boost::match_flag_type flags = boost::match_default; std::string file_h = text; std::string file_cpp; while(boost::regex_search(start, end, what, expression, flags)) { start = what[0].second; std::string class_name = what[1]; std::string class_text = what[0]; std::string class_h, class_cpp; process_class(class_name,class_text,class_h,class_cpp); file_h = boost::regex_replace(file_h,boost::regex(class_text,boost::regbase::literal),class_h); file_cpp += class_cpp; } } void process_class(const std::string & class_name, const std::string & class_text, std::string & class_h, std::string & class_cpp) { std::string FnPattern = "(^(?:[ /t]+//w+)*[ /t]+(//w+)//([^//)]*//))([//s]*//{([^//}]*//{[^//}]*//})*[^//}]*//}+?)"; std::string FnPatternIf = "(^(?:#if.+//s+)*(?:[ /t]+//w+)*[ /t]+(//w+)//([^//)]*//))([//s]*//{([^//}]*//{[^//}]*//})*[^//}]*//}+?(?://s+#e(?:ndif|lif|lse)[^/r/n]*)*)"; std::string::const_iterator start, end; start = class_text.begin(); end = class_text.end(); boost::match_results<std::string::const_iterator> what; boost::match_flag_type flags = boost::match_default; boost::regex expression(FnPatternIf,boost::regbase::JavaScript); class_h = class_text; class_cpp = "/r/n//class/t"; class_cpp += class_name; class_cpp += _T("/r/n"); while(boost::regex_search(start, end, what, expression, flags)) { start = what[0].second; std::string func_buffer = what[0]; std::string func_def = what[1]; std::string func_name = what[2]; std::string func_body = what[3]; //write cpp function std::string func_fullname = std::string(class_name) + "::" + func_name; func_def = boost::regex_replace(func_def,boost::regex(func_name),func_fullname); func_def = boost::regex_replace(func_def,boost::regex("^/t(?://s*virtual//s+)*"), ""); func_body= boost::regex_replace(func_body,boost::regex("^/t"), ""); class_cpp += _T("/r/n"); class_cpp += func_def; class_cpp += func_body; class_cpp += _T("/r/n/r/n"); boost::regex_search(func_buffer,what,boost::regex(FnPattern),flags); // std::string func_decl = (std::string)(what[1]) + ";"; boost::regex reg(std::string(what.base()),boost::regbase::literal); class_h = boost::regex_replace(class_h,reg,func_decl); } }
通过对比,我们也可以看到,由于C++没有内置regex处理,所以代码要比JScript复杂一些