├── .clang-format ├── .clangd ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── CMakeLists.txt ├── README.md ├── c_sharp ├── Program.cs ├── test_cs.csproj └── test_cs.sln ├── compile-proto.bat ├── doc └── images │ └── linux-spt.jpg ├── export_names.cmake ├── fake ├── fake.c └── fake.def ├── java ├── Test.java ├── jna.jar ├── run.bat ├── run.sh └── test.png ├── pb ├── ocr_common.proto ├── ocr_wx3.proto ├── ocr_wx4.proto ├── player_protobuf.proto └── utility_protobuf.proto ├── python ├── run.bat └── test.py ├── spt ├── google │ └── protobuf │ │ ├── any.h │ │ ├── arena.h │ │ ├── arena_impl.h │ │ ├── arenastring.h │ │ ├── arenaz_sampler.h │ │ ├── endian.h │ │ ├── explicitly_constructed.h │ │ ├── extension_set.h │ │ ├── generated_message_util.h │ │ ├── has_bits.h │ │ ├── implicit_weak_message.h │ │ ├── inlined_string_field.h │ │ ├── io │ │ ├── coded_stream.h │ │ ├── zero_copy_stream.h │ │ └── zero_copy_stream_impl_lite.h │ │ ├── message_lite.h │ │ ├── metadata_lite.h │ │ ├── parse_context.h │ │ ├── port.h │ │ ├── port_def.inc │ │ ├── port_undef.inc │ │ ├── repeated_field.h │ │ ├── repeated_ptr_field.h │ │ ├── stubs │ │ ├── bytestream.h │ │ ├── callback.h │ │ ├── casts.h │ │ ├── common.h │ │ ├── hash.h │ │ ├── logging.h │ │ ├── macros.h │ │ ├── once.h │ │ ├── platform_macros.h │ │ ├── port.h │ │ ├── status.h │ │ ├── stl_util.h │ │ ├── stringpiece.h │ │ └── strutil.h │ │ ├── util │ │ └── json_util.h │ │ └── wire_format_lite.h ├── protoc.exe ├── x64 │ ├── libprotobuf-lite.lib │ ├── libprotobuf-lited.lib │ └── mmmojo_64.lib └── x86 │ ├── libprotobuf-lite.lib │ ├── libprotobuf-lited.lib │ └── mmmojo.lib ├── src ├── api.cpp ├── main.cpp ├── mmmojo.h ├── mmmojo_funcs.h ├── mojocall.cpp ├── mojocall.h ├── ocr_common.pb.cc ├── ocr_common.pb.h ├── ocr_wx3.pb.cc ├── ocr_wx3.pb.h ├── ocr_wx4.pb.cc ├── ocr_wx4.pb.h ├── pyspt.cpp ├── pyspt.h ├── wechatocr.cpp └── wechatocr.h └── vs.proj ├── stdafx.cpp ├── stdafx.h ├── wcocr.sln ├── wcocr.vcxproj └── wcocr.vcxproj.filters /.clang-format: -------------------------------------------------------------------------------- 1 | # https://clang.llvm.org/docs/ClangFormatStyleOptions.html 2 | # https://www.bbsmax.com/A/VGzlMjexJb/ 3 | 4 | # 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto 5 | Language: Cpp 6 | 7 | BasedOnStyle: LLVM 8 | 9 | # 访问说明符(public、private等)的偏移 10 | AccessModifierOffset: -4 11 | 12 | # 左括号(左圆括号、左尖括号、左方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在左括号后换行) 13 | AlignAfterOpenBracket: DontAlign 14 | 15 | # 连续赋值时,对齐所有等号 16 | AlignConsecutiveAssignments: false 17 | 18 | # 连续声明时,对齐所有声明的变量名 19 | AlignConsecutiveDeclarations: false 20 | 21 | # 对齐连续位域字段的风格 22 | # AlignConsecutiveBitFields: AcrossEmptyLinesAndComments 23 | 24 | # 对齐连续宏定义的风格 25 | # AlignConsecutiveMacros: Consecutive #clang-format 12 26 | 27 | # 用于在使用反斜杠换行中对齐反斜杠的选项 28 | AlignEscapedNewlines: Left 29 | 30 | # 水平对齐二元和三元表达式的操作数 31 | AlignOperands: Align 32 | 33 | # 对齐连续的尾随的注释 34 | AlignTrailingComments: true 35 | 36 | # 如果函数调用或带括号的初始化列表不适合全部在一行时 37 | # 允许将所有参数放到下一行,即使BinPackArguments为false 38 | AllowAllArgumentsOnNextLine: true 39 | 40 | # 允许构造函数的初始化参数放在下一行 41 | AllowAllConstructorInitializersOnNextLine: true 42 | 43 | # 允许函数声明的所有参数在放在下一行 44 | AllowAllParametersOfDeclarationOnNextLine: true 45 | 46 | # 允许短的块放在同一行(Always 总是将短块合并成一行,Empty 只合并空块) 47 | AllowShortBlocksOnASingleLine: Always 48 | AllowShortEnumsOnASingleLine: true 49 | 50 | # 允许短的case标签放在同一行 51 | AllowShortCaseLabelsOnASingleLine: true 52 | 53 | # 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中/空函数), All 54 | AllowShortFunctionsOnASingleLine: Inline 55 | 56 | # 允许短的if语句保持在同一行 57 | AllowShortIfStatementsOnASingleLine: true 58 | 59 | # 允许短的循环保持在同一行 60 | AllowShortLoopsOnASingleLine: true 61 | 62 | # 总是在定义返回类型后换行(deprecated) 63 | AlwaysBreakAfterDefinitionReturnType: None 64 | 65 | # 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数), 66 | # AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义) 67 | 68 | # 函数声明返回类型后是否换行(None 自动,All全部,TopLevel...) 69 | AlwaysBreakAfterReturnType: None 70 | 71 | # 总是在多行string字面量前换行 72 | AlwaysBreakBeforeMultilineStrings: false 73 | 74 | # 总是在template声明后换行 75 | AlwaysBreakTemplateDeclarations: false 76 | 77 | # false表示函数实参要么都在同一行,要么都各自一行 true: 可以按长度混杂 78 | BinPackArguments: true 79 | 80 | # false表示所有形参要么都在同一行,要么都各自一行 81 | BinPackParameters: true 82 | 83 | # 大括号换行,只有当 BreakBeforeBraces 设置为Custom时才有效 84 | BraceWrapping: 85 | # case 语句后面 86 | AfterCaseLabel: true 87 | # class定义后面 88 | AfterClass: true 89 | # 控制语句后面 Never, MultiLine 90 | AfterControlStatement: Never 91 | # enum定义后面 92 | AfterEnum: true 93 | # 函数定义后面 94 | AfterFunction: true 95 | # 命名空间定义后面 96 | AfterNamespace: true 97 | # ObjC定义后面 98 | AfterObjCDeclaration: false 99 | # struct定义后面 100 | AfterStruct: true 101 | # union定义后面 102 | AfterUnion: true 103 | # extern 导出块后面 104 | AfterExternBlock: false 105 | # catch之前 106 | BeforeCatch: false 107 | # else之前 108 | BeforeElse: false 109 | BeforeLambdaBody: false 110 | BeforeWhile: false 111 | # 缩进大括号(整个大括号框起来的部分都缩进) 112 | IndentBraces: false 113 | # 空函数的大括号是否可以在一行 114 | SplitEmptyFunction: false 115 | # 空记录体(struct/class/union)的大括号是否可以在一行 116 | SplitEmptyRecord: false 117 | # 空名字空间的大括号是否可以在一行 118 | SplitEmptyNamespace: false 119 | 120 | # 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行) 121 | BreakBeforeBinaryOperators: None 122 | 123 | # 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似), 124 | # Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似), 125 | # Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom 126 | # 注:这里认为语句块也属于函数 127 | 128 | # 大括号的换行规则 129 | BreakBeforeBraces: Custom 130 | 131 | # 三元运算操作符换行位置(?和: 在新行还是尾部) 132 | BreakBeforeTernaryOperators: true 133 | 134 | # 在构造函数的初始化列表的逗号前换行 135 | BreakConstructorInitializersBeforeComma: true 136 | 137 | # 要使用的构造函数初始化式样式 138 | BreakConstructorInitializers: BeforeComma 139 | 140 | # 每行字符的限制,0表示没有限制,按照输入来,推荐为0 141 | ColumnLimit: 0 142 | 143 | # 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变 144 | # CommentPragmas: '' 145 | 146 | # 如果为true,则连续的名称空间声明将在同一行上。如果为false,则在新行上声明每个名称空间。 147 | CompactNamespaces: false 148 | 149 | # 构造函数的初始化列表要么都在同一行,要么都各自一行 150 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 151 | 152 | # 构造函数的初始化列表的缩进宽度 153 | ConstructorInitializerIndentWidth: 4 154 | 155 | # 延续的行的缩进宽度 156 | ContinuationIndentWidth: 4 157 | 158 | # 去除C++11的列表初始化的大括号{后和}前的空格 159 | Cpp11BracedListStyle: true 160 | 161 | # 继承最常用的指针和引用的对齐方式 162 | DerivePointerAlignment: false 163 | 164 | # 关闭格式化 165 | DisableFormat: false 166 | 167 | # 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental) 168 | ExperimentalAutoDetectBinPacking: false 169 | 170 | # 如果为true,则clang格式会为短名称空间添加缺少的名称空间结尾注释,并修复无效的现有名称结束注释 171 | FixNamespaceComments: true 172 | 173 | # 需要被解读为foreach循环而不是函数调用的宏 174 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 175 | 176 | # 对#include进行排序,匹配了某正则表达式的#include拥有对应的优先级,匹配不到的则默认优先级为INT_MAX(优先级越小排序越靠前), 177 | # 可以定义负数优先级从而保证某些#include永远在最前面 178 | IncludeCategories: 179 | - Regex: '^"(stdafx|pch)\.h"$' 180 | Priority: 0 181 | - Regex: '^<' 182 | Priority: 20 183 | - Regex: '.*' 184 | Priority: 50 185 | 186 | 187 | # 缩进case标签 188 | IndentCaseLabels: false 189 | # 缩进case里面的内容 190 | IndentCaseBlocks: true 191 | 192 | # 要使用的预处理器指令缩进样式 193 | IndentPPDirectives: AfterHash 194 | PPIndentWidth: 1 195 | 196 | # 缩进宽度 197 | IndentWidth: 4 198 | 199 | # 函数返回类型换行时,缩进函数声明或函数定义的函数名 200 | IndentWrappedFunctionNames: false 201 | 202 | # 保留在块开始处的空行 203 | KeepEmptyLinesAtTheStartOfBlocks: true 204 | 205 | # 开始一个块的宏的正则表达式 206 | MacroBlockBegin: '' 207 | 208 | # 结束一个块的宏的正则表达式 209 | MacroBlockEnd: '' 210 | 211 | # 连续空行的最大数量 212 | MaxEmptyLinesToKeep: 3 213 | 214 | # 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All 215 | NamespaceIndentation: All 216 | 217 | # 使用ObjC块时缩进宽度 218 | ObjCBlockIndentWidth: 4 219 | 220 | # 在ObjC的@property后添加一个空格 221 | ObjCSpaceAfterProperty: false 222 | 223 | # 在ObjC的protocol列表前添加一个空格 224 | ObjCSpaceBeforeProtocolList: true 225 | 226 | # 函数调用的左括号后立即换行的惩罚值 227 | PenaltyBreakBeforeFirstCallParameter: 2 228 | 229 | # 在一个注释中引入换行的惩罚值 230 | PenaltyBreakComment: 300 231 | 232 | # 第一次在<<前换行的惩罚值 233 | PenaltyBreakFirstLessLess: 120 234 | 235 | # 在一个字符串字面量中引入换行的惩罚值 236 | PenaltyBreakString: 1000 237 | 238 | # 对于每个在行字符数限制之外的字符的惩罚值 239 | PenaltyExcessCharacter: 1000 240 | 241 | # 对每一个空格缩进字符的penalty(相对于前导的非空格列计算) 242 | # PenaltyIndentedWhitespace: 0 243 | 244 | # 将函数的返回类型放到它自己的行的penalty 245 | PenaltyReturnTypeOnItsOwnLine: 120 246 | 247 | # 指针和引用的对齐: Left, Right, Middle 248 | PointerAlignment: Left 249 | 250 | # 允许重新排版注释 251 | ReflowComments: true 252 | 253 | # 允许排序#include 254 | SortIncludes: true 255 | 256 | # 允许排序 using 声明顺序 257 | SortUsingDeclarations: true 258 | 259 | # 在C风格类型转换后添加空格 260 | SpaceAfterCStyleCast: false 261 | 262 | # 在逻辑非操作符(!)之后插入一个空格 263 | SpaceAfterLogicalNot: false 264 | 265 | # 在 template 关键字后插入一个空格 266 | SpaceAfterTemplateKeyword: false 267 | 268 | # 定义在什么情况下在指针限定符之前或之后放置空格 269 | # SpaceAroundPointerQualifiers: Before 270 | 271 | # 在赋值运算符之前添加空格 272 | SpaceBeforeAssignmentOperators: true 273 | 274 | # 左圆括号之前添加一个空格: Never, ControlStatements, Always 275 | SpaceBeforeParens: ControlStatements 276 | 277 | # 空格将在基于范围的for循环冒号之前 278 | SpaceBeforeRangeBasedForLoopColon: true 279 | 280 | # [ 前是否添加空格(数组名和[之间,Lambdas不会受到影响) 281 | # 连续多个 [ 只考虑第一个(嵌套数组,多维数组) 282 | SpaceBeforeSquareBrackets: false 283 | 284 | # 在空的圆括号中添加空格 285 | SpaceInEmptyParentheses: false 286 | 287 | # 在尾随的评论前添加的空格数(只适用于//) 288 | SpacesBeforeTrailingComments: 2 289 | 290 | # 在尖括号的<后和>前添加空格 291 | SpacesInAngles: false 292 | 293 | # 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格 294 | SpacesInContainerLiterals: false 295 | 296 | # 在C风格类型转换的括号中添加空格 297 | SpacesInCStyleCastParentheses: false 298 | 299 | # 如果为true,将在If/for/switch/while条件前后插入空格,即()的内部多两空格。 300 | SpacesInConditionalStatement: false 301 | 302 | # 在圆括号的(后和)前添加空格 303 | SpacesInParentheses: false 304 | 305 | # 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响 306 | SpacesInSquareBrackets: false 307 | 308 | # 标准: Cpp03, Cpp11, Auto, Latest 309 | Standard: Latest 310 | 311 | # tab宽度 312 | TabWidth: 4 313 | 314 | # 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always 315 | UseTab: ForIndentation 316 | -------------------------------------------------------------------------------- /.clangd: -------------------------------------------------------------------------------- 1 | CompileFlags: 2 | Add: 3 | - -D__INTELLISENSE__ 4 | - -D__CLANGD__ 5 | - -include stdafx.h 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.obj 3 | *.dll 4 | *.exp 5 | *.pdb 6 | *.lib 7 | *.user 8 | *.pyd 9 | *.class 10 | !/spt/*/*.lib 11 | 12 | .vs/ 13 | /demo*/ 14 | Properties/ 15 | bin/ 16 | obj/ 17 | 18 | compile_commands.json 19 | build*/ 20 | .cache/ 21 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug", 11 | "program": "${workspaceFolder}/build/test_cli", 12 | "args": ["/opt/wechat/wxocr", "/opt/wechat/", "../demo5/test呀哈哟.png"], 13 | "cwd": "${workspaceFolder}/build/" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "clangd.arguments": [ 3 | "--all-scopes-completion", // 全局补全(补全建议会给出在当前作用域不可见的索引,插入后自动补充作用域标识符),例如在main()中直接写cout,即使没有`#include `,也会给出`std::cout`的建议,配合"--header-insertion=iwyu",还可自动插入缺失的头文件 4 | "--background-index", // 后台分析并保存索引文件 5 | "--clang-tidy", // 启用 Clang-Tidy 以提供「静态检查」 6 | "--clang-tidy-checks=performance-*, bugprone-*, misc-*, google-*, modernize-*, readability-*, portability-*", 7 | "--compile-commands-dir=build", // 编译数据库(compile_commands.json 文件)的目录位置 8 | "--completion-parse=auto", // 当 clangd 准备就绪时,用它来分析建议 9 | "--query-driver=/usr/bin/clang++-18", // MAC 上需要设定 clang 编译器的路径,也可以是 /usr/local/opt/llvm/bin/clang++ 10 | // 启用配置文件(YAML格式) 11 | "--enable-config", 12 | "--fallback-style=Microsoft", // 默认格式化风格: 在没找到 .clang-format 文件时采用,可用的有 LLVM, Google, Chromium, Mozilla, Webkit, Microsoft, GNU 13 | "--function-arg-placeholders=true", // 补全函数时,将会给参数提供占位符,键入后按 Tab 可以切换到下一占位符,乃至函数末 14 | "--header-insertion-decorators", // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分 15 | "--header-insertion=iwyu", // 插入建议时自动引入头文件 iwyu 16 | "--include-cleaner-stdlib", // 为标准库头文件启用清理功能(不成熟!!!) 17 | "--log=verbose", // 让 Clangd 生成更详细的日志 18 | "--pch-storage=memory", // pch 优化的位置(Memory 或 Disk,前者会增加内存开销,但会提升性能) 19 | "--pretty", // 输出的 JSON 文件更美观 20 | "--ranking-model=decision_forest", // 建议的排序方案:hueristics (启发式), decision_forest (决策树) 21 | "-j=2", // 同时开启的任务数量 22 | ], 23 | "clangd.checkUpdates": true, // 自动检测 clangd 更新 24 | "clangd.serverCompletionRanking": true, // 借助网上的信息排序建议 25 | "clangd.detectExtensionConflicts": true, // 当其它拓展与 clangd 冲突时警告并建议禁用 26 | } 27 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | # 项目名称 4 | project(wechat-ocr) 5 | 6 | # 设置 C++ 标准 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 9 | 10 | # 生成 compile_commands.json 11 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 12 | 13 | # 添加头文件搜索路径 14 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/vs.proj") 15 | 16 | if (WIN32) 17 | # add _CRT_SECURE_NO_WARNINGS 18 | add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -D_UNICODE -DUNICODE -EHsc) 19 | # find_package(Protobuf REQUIRED) 20 | link_directories("${CMAKE_CURRENT_SOURCE_DIR}/spt/x64") 21 | set(Protobuf_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/spt" CACHE INTERNAL "") 22 | set(Protobuf_LIBRARIES "libprotobuf-lite.lib" CACHE INTERNAL "") 23 | else() 24 | # 查找或下载并编译 Google Protobuf 25 | include(FetchContent) 26 | FetchContent_Declare(protobuf 27 | GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git 28 | GIT_TAG v3.21.0 29 | ) 30 | set(protobuf_BUILD_TESTS OFF CACHE BOOL "" FORCE) 31 | set(protobuf_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) 32 | set(protobuf_BUILD_PROTOC_BINARIES OFF CACHE BOOL "" FORCE) 33 | set(protobuf_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) 34 | set(protobuf_INSTALL OFF CACHE BOOL "" FORCE) 35 | set(protobuf_WITH_ZLIB OFF CACHE BOOL "" FORCE) 36 | set(ABSL_PROPAGATE_CXX_STD ON) 37 | FetchContent_MakeAvailable(protobuf) 38 | target_compile_options(libprotobuf-lite PRIVATE -fPIC) 39 | set(Protobuf_INCLUDE_DIR "${protobuf_SOURCE_DIR}/src" CACHE INTERNAL "") 40 | set(Protobuf_LIBRARIES libprotobuf-lite CACHE INTERNAL "") 41 | endif() 42 | 43 | # 查找所有源文件,排除 src/main.cpp 44 | file(GLOB SRC_FILES 45 | "src/*.cpp" 46 | "src/*.cc" 47 | ) 48 | list(REMOVE_ITEM SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp") 49 | list(REMOVE_ITEM SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/pyspt.cpp") 50 | 51 | include(export_names.cmake) 52 | # 添加共享库目标 53 | add_library(wcocr SHARED ${SRC_FILES}) 54 | target_include_directories(wcocr SYSTEM PRIVATE ${Protobuf_INCLUDE_DIR}) 55 | target_link_libraries(wcocr ${Protobuf_LIBRARIES}) 56 | configure_export_symbols("L" wcocr "wechat_ocr" "stop_ocr" "_ZN10CWeChatOCR*" "_ZN9CMojoCall*" "_ZT?10CWeChatOCR") 57 | 58 | find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED) 59 | add_library(pywcocr MODULE ${SRC_FILES} src/pyspt.cpp) 60 | target_include_directories(pywcocr PRIVATE ${Protobuf_INCLUDE_DIR} ${Python_INCLUDE_DIRS}) 61 | target_compile_definitions(pywcocr PRIVATE EXPORTED_API=) 62 | configure_export_symbols("LW" pywcocr "PyInit_wcocr") 63 | target_link_libraries(pywcocr PRIVATE ${Protobuf_LIBRARIES} ${Python_LIBRARIES}) 64 | target_link_directories(pywcocr PRIVATE ${Python_LIBRARY_DIRS}) 65 | if(WIN32) 66 | set(PYTHON_MODULE_EXTENSION ".pyd") 67 | else() 68 | set(PYTHON_MODULE_EXTENSION "${CMAKE_SHARED_LIBRARY_SUFFIX}") 69 | endif() 70 | set_target_properties(pywcocr PROPERTIES 71 | PREFIX "" # 移除 lib 前缀 72 | OUTPUT_NAME "wcocr" # 设置基本名称 73 | SUFFIX ".${Python_SOABI}${PYTHON_MODULE_EXTENSION}" # 添加 Python 特定的后缀 74 | ) 75 | 76 | 77 | # 添加可执行目标 test_cli 78 | add_executable(test_cli src/main.cpp) 79 | target_link_libraries(test_cli wcocr) 80 | target_compile_definitions(test_cli PRIVATE TEST_CLI) 81 | 82 | # 设置输出名称为 wcocr.so 83 | set_target_properties(wcocr PROPERTIES 84 | OUTPUT_NAME "wcocr" 85 | LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" 86 | ) 87 | 88 | # 设置安装规则 89 | install(TARGETS wcocr 90 | LIBRARY DESTINATION lib 91 | ) 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wcocr: demonstrate how to use WeChatOCR.exe 2 | 3 | Great thanks to IEEE by his [Project IEEE/QQImpl](https://github.com/EEEEhex/qqimpl)] and [article](https://bbs.kanxue.com/thread-278161.htm). 4 | This project is based on it and reduced the product size by using `protobuf-lite` instead of `protobuf`. 5 | 6 | This project provided a direct Python interface for calling in sync mode as well as other languages support including but not limited with c++/java/c#. 7 | 8 | # Prepare for usage 9 | 10 | To work with this project, you need to prepare the wechat OCR binary and the wechat runtime folder. 11 | 12 | For wechat 3.x, the wechat OCR binary is `wechatocr.exe`, it might be: 13 | 14 | ``` 15 | C:\Users\yourname\AppData\Roaming\Tencent\WeChat\XPlugin\Plugins\WeChatOCR\7061\extracted\WeChatOCR.exe 16 | ``` 17 | and the wechat runtime folder might be: 18 | ``` 19 | C:\Program Files (x86)\Tencent\WeChat\[3.9.8.25] 20 | ``` 21 | 22 | **Wechat 4.0 is now supported!** 23 | 24 | For wechat 4.0, the wechat OCR binary is `wxocr.dll`, it might be: 25 | 26 | ``` 27 | C:\Users\yourname\AppData\Roaming\Tencent\xwechat\XPlugin\plugins\WeChatOcr\8011\extracted\wxocr.dll 28 | ``` 29 | 30 | and the wechat runtime folder might be: 31 | 32 | ``` 33 | C:\Program Files\Tencent\Weixin\4.0.0.26 34 | ``` 35 | 36 | ## Warning 37 | 38 | WeChat 4.0 OCR binary is `wxocr.dll`, but this project built a DLL named `wcocr.dll` 39 | 40 | **Their names are similar, DO NOT confuse them.** 41 | 42 | 43 | 44 | # Linux is now supported 45 | 46 | ![linux supported](doc/images/linux-spt.jpg) 47 | 48 | Typically, You should use `/opt/wechat/wxocr` as the OCR exe path and `/opt/wechat/` as the WeChat folder path. 49 | 50 | The other usages are similar to those on Windows. 51 | 52 | ## C++ interface 53 | 54 | You can use the following code to test it: 55 | ```cpp 56 | CWeChatOCR ocr(wechatocr_path, wechat_path); 57 | if (!ocr.wait_connection(5000)) { 58 | // error handling 59 | } 60 | CWeChatOCR::result_t result; 61 | ocr.doOCR("D:\\test.png", &result); 62 | ``` 63 | You can also pass `nullptr` to the second parameter of `doOCR` to call in async mode and wait the callback. 64 | In this case, you need to subclass `CWeChatOCR` and implement the virtual function `OnOCRResult`. 65 | 66 | ## Python interface 67 | Rename the built `wcocr.dll` to `wcocr.pyd` and put it in the same directory as `test.py`. 68 | You can use the following code to test it: 69 | 70 | ```python 71 | import wcocr 72 | wcocr.init(wechatocr_path, wechat_path) 73 | result = wcocr.ocr("D:\\test.png") 74 | ``` 75 | 76 | Currently, the python interface only supports sync mode. 77 | 78 | ## Java interface 79 | 80 | * see java/Test.java 81 | * I'm not so familiar with java and don't know how to pass complex data structures, so I just passed a JSON string from cpp to java. 82 | * The added DLL export function `wechat_ocr` can also be used in other scenarios. 83 | 84 | ## C Sharp (C#) interface 85 | * see `c_sharp` folder. 86 | * It's important to ensure the built dll is copied to the folder test_cs.exe in! always copy the 64bit version dll! 87 | * It's ok to built a 32bit test_cs.exe and copy the 32bit dll, you can try. 88 | -------------------------------------------------------------------------------- /c_sharp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | using static Program; 5 | 6 | class WechatOCR 7 | { 8 | // 注意要把生成的64位dll拷到 c_sharp\bin\x64\Debug\net8.0 目录下 9 | delegate void SetResultDelegate(IntPtr result); 10 | 11 | [DllImport("wcocr.dll", CallingConvention = CallingConvention.Cdecl)] 12 | static extern bool wechat_ocr( 13 | [MarshalAs(UnmanagedType.LPWStr)] string ocr_exe, 14 | [MarshalAs(UnmanagedType.LPWStr)] string wechat_dir, 15 | byte[] imgfn, 16 | SetResultDelegate set_res); 17 | 18 | [DllImport("wcocr.dll", CallingConvention = CallingConvention.Cdecl)] 19 | public static extern void stop_ocr(); 20 | 21 | class StringResult 22 | { 23 | string result_ = ""; 24 | public void SetResult(IntPtr dt) 25 | { 26 | int length = 0; 27 | while (Marshal.ReadByte(dt, length) != 0) length++; 28 | byte[] byteArray = new byte[length]; 29 | Marshal.Copy(dt, byteArray, 0, length); 30 | result_ = Encoding.UTF8.GetString(byteArray); 31 | } 32 | public string GetResult() 33 | { 34 | return result_; 35 | } 36 | }; 37 | 38 | public static bool call_wechat_ocr(string ocr_exe, string wechat_dir, string imgfn, out string res) 39 | { 40 | StringResult stringResult = new StringResult(); 41 | SetResultDelegate setRes = new SetResultDelegate(stringResult.SetResult); 42 | bool success = wechat_ocr(ocr_exe, wechat_dir, Encoding.UTF8.GetBytes(imgfn + "\0"), setRes); 43 | res = stringResult.GetResult(); 44 | return success; 45 | } 46 | }; 47 | 48 | class Program 49 | { 50 | static void Main(string[] args) 51 | { 52 | if (args.Length != 3) 53 | { 54 | Console.WriteLine("Usage: wcocr.exe ocr_exe wechat_dir imgfn"); 55 | return; 56 | } 57 | string sRes; 58 | bool success = WechatOCR.call_wechat_ocr(args[0], args[1], args[2], out sRes); 59 | Console.WriteLine($"OCR Success?:{success} res:{sRes}"); 60 | WechatOCR.stop_ocr(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /c_sharp/test_cs.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | AnyCPU;x64 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /c_sharp/test_cs.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34728.123 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test_cs", "test_cs.csproj", "{0F79C844-AF8C-44CA-9D3C-27F1E47E4805}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Release|Any CPU = Release|Any CPU 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Debug|x64.ActiveCfg = Debug|x64 19 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Debug|x64.Build.0 = Debug|x64 20 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Release|x64.ActiveCfg = Release|x64 23 | {0F79C844-AF8C-44CA-9D3C-27F1E47E4805}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {61ED6E08-2B59-4CDB-8534-BC52560BC05E} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /compile-proto.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd /d %~dp0 3 | cd src 4 | ..\spt\protoc.exe --cpp_out=lite:. -I ../pb ocr_common.proto ocr_wx3.proto ocr_wx4.proto 5 | pause 6 | -------------------------------------------------------------------------------- /doc/images/linux-spt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/doc/images/linux-spt.jpg -------------------------------------------------------------------------------- /export_names.cmake: -------------------------------------------------------------------------------- 1 | # 这个模块提供了控制共享库导出符号的功能 2 | # 对Linux生成版本脚本,对Windows生成DEF文件 3 | 4 | # 函数:配置导出符号 5 | # 参数: 6 | # TARGET_NAME - 目标库名称 7 | # HOSTS - 目标平台 LWA for Linux, Windows, Apple 8 | # SYMBOLS - 要导出的符号列表 9 | function(configure_export_symbols HOSTS TARGET_NAME) 10 | # 解析参数 11 | set(SYMBOLS ${ARGN}) 12 | 13 | if(NOT SYMBOLS) 14 | message(WARNING "没有指定导出符号") 15 | return() 16 | endif() 17 | 18 | # 为不同平台创建不同的导出文件 19 | if (UNIX AND NOT APPLE) 20 | string(FIND "${HOSTS}" "L" FOUND_INDEX) 21 | if (${FOUND_INDEX} GREATER -1) 22 | # Linux平台: 生成版本脚本 23 | set(EXPORT_FILE "${CMAKE_BINARY_DIR}/${TARGET_NAME}_symbols.def") 24 | file(WRITE ${EXPORT_FILE} "{\n") 25 | file(APPEND ${EXPORT_FILE} " global:\n") 26 | 27 | foreach(SYMBOL ${SYMBOLS}) 28 | file(APPEND ${EXPORT_FILE} " ${SYMBOL};\n") 29 | endforeach() 30 | 31 | file(APPEND ${EXPORT_FILE} "\n") 32 | file(APPEND ${EXPORT_FILE} " local: *;\n") 33 | file(APPEND ${EXPORT_FILE} "};\n") 34 | 35 | # 添加链接器标志 36 | target_link_options(${TARGET_NAME} PRIVATE "-Wl,--version-script=${EXPORT_FILE}") 37 | message(STATUS "为 ${TARGET_NAME} 配置了符号导出 (${SYMBOLS})") 38 | endif() 39 | elseif(WIN32) 40 | string(FIND "${HOSTS}" "W" FOUND_INDEX) 41 | if (${FOUND_INDEX} GREATER -1) 42 | # Windows平台: 生成DEF文件 43 | set(EXPORT_FILE "${CMAKE_BINARY_DIR}/${TARGET_NAME}_exports.def") 44 | file(WRITE ${EXPORT_FILE} "EXPORTS\n") 45 | 46 | foreach(SYMBOL ${SYMBOLS}) 47 | file(APPEND ${EXPORT_FILE} " ${SYMBOL}\n") 48 | endforeach() 49 | 50 | # 添加DEF文件到链接器 51 | set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS " /DEF:\"${EXPORT_FILE}\"") 52 | message(STATUS "为 ${TARGET_NAME} 配置了符号导出 (${SYMBOLS})") 53 | endif() 54 | elseif(APPLE) 55 | string(FIND "${HOSTS}" "A" FOUND_INDEX) 56 | if (${FOUND_INDEX} GREATER -1) 57 | # macOS平台处理(可选) 58 | message(STATUS "TODO: macOS平台暂时不支持") 59 | endif() 60 | endif() 61 | 62 | # 设置属性记录已应用导出配置 63 | # set_target_properties(${TARGET_NAME} PROPERTIES HAS_SYMBOL_EXPORTS TRUE) 64 | endfunction() 65 | -------------------------------------------------------------------------------- /fake/fake.c: -------------------------------------------------------------------------------- 1 | int foo(int a,int b){ 2 | return 0; 3 | } 4 | -------------------------------------------------------------------------------- /fake/fake.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | AppendMMSubProcessSwitchNative=foo 3 | CreateMMMojoEnvironment=foo 4 | CreateMMMojoWriteInfo=foo 5 | GetHandleVerifier=foo 6 | GetMMMojoReadInfoAttach=foo 7 | GetMMMojoReadInfoMethod=foo 8 | GetMMMojoReadInfoRequest=foo 9 | GetMMMojoReadInfoSync=foo 10 | GetMMMojoWriteInfoAttach=foo 11 | GetMMMojoWriteInfoRequest=foo 12 | InitializeMMMojo=foo 13 | IsSandboxedProcess=foo 14 | MMMojoLog=foo 15 | MMMojoLogArg=foo 16 | RemoveMMMojoEnvironment=foo 17 | RemoveMMMojoReadInfo=foo 18 | RemoveMMMojoWriteInfo=foo 19 | SendMMMojoWriteInfo=foo 20 | SetMMMojoEnvironmentCallbacks=foo 21 | SetMMMojoEnvironmentInitParams=foo 22 | SetMMMojoWriteInfoMessagePipe=foo 23 | SetMMMojoWriteInfoResponseSync=foo 24 | ShutdownMMMojo=foo 25 | StartMMMojoEnvironment=foo 26 | StopMMMojoEnvironment=foo 27 | SwapMMMojoWriteInfoCallback=foo 28 | SwapMMMojoWriteInfoMessage=foo 29 | -------------------------------------------------------------------------------- /java/Test.java: -------------------------------------------------------------------------------- 1 | import com.sun.jna.Callback; 2 | import com.sun.jna.Library; 3 | import com.sun.jna.Native; 4 | import com.sun.jna.WString; 5 | import java.util.Collections; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | 9 | public class Test { 10 | public interface WechatOCR extends Library { 11 | WechatOCR dll = (WechatOCR) Native.load("wcocr", WechatOCR.class, 12 | Collections.singletonMap(Library.OPTION_STRING_ENCODING, "UTF-8")); 13 | interface SetResCallback extends Callback { 14 | void callback(String arg); 15 | } 16 | boolean wechat_ocr(Object ocr_exe, Object wechat_dir, String imgfn, SetResCallback res); 17 | void stop_ocr(); 18 | public static boolean call_wechat_ocr(String ocr_exe, String wechat_dir, String imgfn, SetResCallback res) { 19 | String os = System.getProperty("os.name").toLowerCase(); 20 | boolean isWindows = os.contains("win"); 21 | if (isWindows) { 22 | return dll.wechat_ocr(new WString(ocr_exe), new WString(wechat_dir), imgfn, res); 23 | } else { 24 | return dll.wechat_ocr(ocr_exe, wechat_dir, imgfn, res); 25 | } 26 | } 27 | } 28 | public static void main(String [] args) { 29 | if (args.length != 3) { 30 | System.out.println("usage: java ... Test ocr_exe_path wechat_dir_path png_path"); 31 | return; 32 | } 33 | System.out.println("ocr begin..."); 34 | String ocr_exe = args[0]; 35 | String wechat_dir = args[1]; 36 | String tstpng = args[2]; 37 | AtomicReference result = new AtomicReference<>(); 38 | WechatOCR.call_wechat_ocr(ocr_exe, wechat_dir, tstpng, new WechatOCR.SetResCallback() { 39 | public void callback(String args) { 40 | result.set(args); 41 | } 42 | }); 43 | System.out.println("OCR result: " + result.get()); 44 | System.out.println("ocr end..."); 45 | WechatOCR.dll.stop_ocr(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /java/jna.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/java/jna.jar -------------------------------------------------------------------------------- /java/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | copy ..\vs.proj\x64\Debug\wcocr.dll . 3 | javac -cp jna.jar Test.java 4 | java -cp "jna.jar;." Test "C:\Users\xungeng\AppData\Roaming\Tencent\xwechat\XPlugin\plugins\WeChatOcr\8020\extracted\wxocr.dll" "C:\Program Files\Tencent\Weixin\4.0.2.13" test.png 5 | pause 6 | -------------------------------------------------------------------------------- /java/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ ! -f libwcocr.so ] ; then 3 | if [ ! -f ../build/libwcocr.so ] ; then 4 | echo "please build project first! (using cmake)" >&2 5 | exit 1 6 | fi 7 | ln -sf ../build/libwcocr.so . 8 | fi 9 | javac -cp jna.jar Test.java 10 | java -cp "jna.jar:." Test "/opt/wechat/wxocr" "/opt/wechat" test.png 11 | -------------------------------------------------------------------------------- /java/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/java/test.png -------------------------------------------------------------------------------- /pb/ocr_common.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/pb/ocr_common.proto -------------------------------------------------------------------------------- /pb/ocr_wx3.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package wx3; 3 | import "ocr_common.proto"; 4 | 5 | message OcrInputBuffer { 6 | // 看起来有两种传递图片的方式。 7 | // 第一种是只传文件路径 pic_path = "C:/path/to/xxx.png" 8 | // 第二种是用字节流传,猜测需要用到u2,u3,pic_data变量。暂时微信没有用到,可能是为将来保留 9 | optional string pic_path = 1; 10 | optional uint32 u2 = 2; 11 | optional uint32 u3 = 3; 12 | optional bytes pic_data = 4; 13 | } 14 | 15 | message OcrOutputBuffer { 16 | repeated ocr_common.OCRResultLine lines = 1; //repeated 每行的结果 17 | optional uint32 img_width = 2; 18 | optional uint32 img_height = 3; 19 | optional string unk4 = 4; 20 | } 21 | 22 | message OcrRespond { 23 | optional int32 type = 1; // type=1像是初始化成功回调。如果是正常OCR请求,回答的type=0 24 | optional uint64 task_id = 2; 25 | optional int32 err_code = 3; 26 | optional OcrOutputBuffer ocr_result = 4; 27 | } 28 | 29 | message OcrRequest { 30 | int32 type = 1; //为0执行ocr,为1会直接返回init信息. 与OcrRespond.type意义相同 31 | // 经过反复核查,在腾讯proto文件中,这个task_id确实是64位的。但在,在执行过程中,高32位会被丢弃,且第32位为1会出错。 32 | // 也就是协议上是有64位的uint64,实际上只能有31位。必须是>0的整形数字,范围是[1,2147483647] 33 | // 由于 task_id = 1会被用于初始化,所以最好取值为 [2, 0x7fffFFFF] 34 | uint64 task_id = 2; 35 | OcrInputBuffer input = 3; 36 | } 37 | -------------------------------------------------------------------------------- /pb/ocr_wx4.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/pb/ocr_wx4.proto -------------------------------------------------------------------------------- /pb/player_protobuf.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package player_protobuf; 4 | 5 | //WeChatWin: 10011(发) -> 10012(收) -> 10010(发) -> 10030(收) -> 10028(发) -> 10028(发) -> 10030(收) -> 10030(收) -> 10032(收) -> 10030(收) -> 10032(收) -> 10030(收) -> 10014(收) -> 6 | //WeChatPlayer: 1011(收) -> 10012(发) -> 10010(收) -> 10030(发) -> 10028(收) -> 10028(收) -> 10030(发) -> 10030(发) -> 10032(发) -> 10030(发) -> 10030(发) -> 10030(发) -> 10014(发) -> 7 | //所有int32都有可能是以下类型: int32,int64,uint32,uint64,sint32,sint64,bool,enum 8 | 9 | message InitReqMessage { 10 | int32 expire_timestamp = 1; //可能是过期时间 11 | int32 type = 2; //为1 12 | } 13 | 14 | message InitRespMessage { 15 | int32 status = 1; //为1 16 | } 17 | 18 | message CreatePlayerCoreReqMessage { 19 | int32 player_id = 1; 20 | int32 is_post_frame = 2; //为1 21 | } 22 | 23 | message CreatePlayerCoreRespMessage { 24 | int32 player_id = 1; //可能是 应该是返回1 25 | int32 is_suceess = 2; //可能是 应该是返回1 26 | } 27 | 28 | message InitPlayerCoreMessage { 29 | int32 player_id = 1; //Player ID 30 | string file_name = 2; //文件名 (不包括最后一个字母 不包括扩展名) 31 | string file_path = 3; //要播放的视频路径 32 | int64 file_size = 4; //网络视频的大小 本地时为0 33 | bool is_local = 5; //视频是来自本地还是网络 为1 34 | int32 placeholder_6 = 6; //为0 35 | int64 media_id = 7; //为1 36 | bool is_audio_mute = 8; //是否设置静音 为0 37 | int64 video_surface = 9; //窗口句柄 38 | float audio_volume = 10; //音量 为1.0 39 | int32 is_repeat = 11; //是否设置重复播放 为1 40 | float speed_ratio = 12; //播放速率 为1.0 41 | int32 max_frame_width = 13; //为0 42 | int32 max_frame_height = 14; //为0 43 | int32 codec_type = 15; //为-1 44 | int64 decoder_type = 16; //为-1 45 | } 46 | 47 | message InfoPlayerCoreMessage { 48 | int32 player_id = 1; //. 49 | string type = 2; //例如"video decoder type" "the first shard opened" "Unknow Player Msg" "read the first data packets" "read the key frame packet"... "whether to use p2p" 50 | int32 arg = 3; //未知 106 0 0 0 0... 1 51 | int32 unknown_2 = 4; //1或0 1 0 0 0 0... 0 52 | } 53 | 54 | //10014 10015 10016 10017 10018 55 | message PlayerIdMessage { 56 | int32 player_id = 1; 57 | } 58 | 59 | message CurrentPositionMsMessage { 60 | int32 unknown = 1; //为0 61 | } 62 | 63 | message CurrentPositionMsInfo { 64 | message MsInfo{ 65 | int32 player_id = 1; 66 | int32 pos = 2; 67 | } 68 | 69 | repeated bytes ms_info = 1; //这里面是MsInfo序列化 70 | } 71 | 72 | message ResizePlayerCoreMessage { 73 | int32 player_id = 1; 74 | int32 new_width = 2; 75 | int32 new_height = 3; 76 | } 77 | 78 | message VideoSizeChangedPlayerCoreMessage { 79 | int32 player_id = 1; 80 | int32 org_width = 2; //可能是 81 | int32 org_height = 3; //可能是 82 | } 83 | 84 | message PreparePlayerCoreMessage { 85 | int32 player_id = 1; 86 | int32 duration = 2; //视频时长 时分秒 87 | } 88 | 89 | message StatePlayerCoreMessage { 90 | int32 player_id = 1; 91 | int32 state = 2; //4: 开始播放 8: 停止播放 92 | } 93 | 94 | //以下都可能是 没有验证 95 | 96 | message AudioMutePlayerCoreMessage { 97 | int32 player_id = 1; 98 | bool is_audio_mute = 2; 99 | } 100 | 101 | message SeekToPlayerCoreMessage { 102 | int32 player_id = 1; 103 | int32 pos_ms = 2; 104 | } 105 | 106 | message VideoSurfaceMessage { 107 | int32 player_id = 1; 108 | int32 window = 2; //窗口句柄 109 | } 110 | 111 | message AudioVolumePlayerCoreMessage { 112 | int32 player_id = 1; 113 | float audio_volume = 2; 114 | } 115 | 116 | message RepeatPlayerCoreMessage { 117 | int32 player_id = 1; 118 | int32 is_repeat = 2; 119 | } 120 | 121 | message SpeedRatioPlayerCoreMessage { 122 | int32 player_id = 1; 123 | float speed_ratio = 2; 124 | } 125 | 126 | message ReadyDataSourceCoreMessage { 127 | int32 player_id = 1; 128 | string file_name = 2; 129 | string file_path = 3; 130 | int64 media_id = 4; 131 | } 132 | 133 | message DownloadDataSourceCoreMessage { 134 | int32 player_id = 1; 135 | string file_name = 2; 136 | string file_path = 3; 137 | int64 file_size = 4; 138 | int64 media_id = 5; 139 | } 140 | 141 | message ErrorPlayerCoreMessage { 142 | int32 player_id = 1; 143 | string error = 2; 144 | int32 error_type = 3; 145 | int32 error_code = 4; 146 | } 147 | 148 | message StartTaskProxyMessage { 149 | int32 task_id = 1; 150 | int32 player_id = 2; 151 | } 152 | 153 | message StartRequestProxyMessage { 154 | int32 task_id = 1; 155 | int32 player_id = 2; 156 | int32 request_start = 3; 157 | int32 request_end = 4; 158 | } 159 | 160 | message CloseRequestProxyMessage { 161 | int32 task_id = 1; 162 | int32 player_id = 2; 163 | } 164 | 165 | message PollingDataProxyReqMessage { 166 | int32 task_id = 1; 167 | int32 player_id = 2; 168 | int32 offset = 3; 169 | int32 ready_size = 4; 170 | int32 download_size = 5; 171 | int32 read_size=6; 172 | } 173 | 174 | message PollingDataProxyRespMessage { 175 | 176 | } -------------------------------------------------------------------------------- /pb/utility_protobuf.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package utility_protobuf; 4 | 5 | //所有int32都有可能是以下类型: int32,int64,uint32,uint64,sint32,sint64,bool,enum 6 | 7 | message InitReqMessage { 8 | int32 expire_timestamp = 1; //猜的 9 | int32 type = 2; //为1 10 | } 11 | 12 | message InitRespMessage { 13 | int32 status = 1; //是否初始化成功 WeChatWin.dll并没有处理这个消息 14 | } 15 | 16 | message ResampleImageReqMessage{ 17 | string decode_pic = 1; //解码图片的路径 18 | string encode_pic = 2; //原始加密图片的路径 19 | int32 re_pic_x = 3; //图片长 20 | int32 re_pic_y = 4; //图片宽 21 | int32 unknown_0 = 5; //未知 一般为1 22 | } 23 | 24 | message ResampleImageRespMessage { 25 | int32 err_code = 1; //可能是 一般为0 错误为8 26 | } 27 | 28 | message TextScanMessage { 29 | int32 text_scan_id = 1; //可能是 30 | string pic_path = 2; //扫描的图片路径 31 | int32 have_text = 3; //是否有文字 32 | int32 unknown_0 = 4; //未知 33 | float rate = 5; //应该是浮点数 图上要是没文字这个字段肯定为0.0 34 | } 35 | 36 | //当使用图片时发送的是1 2(可为空) 3 7 8 9项 37 | //当在截图中框选时发送的是 4 5 6 7 8 9项 38 | message QRScanReqMessage { 39 | string origin_pic = 1; //原始图片路径 可选 40 | string decode_pic = 2; //解码后的图片路径 可选 41 | int32 unknown_0 = 3; //未知 可选 一般为0 42 | bytes encode_pic_data = 4; //某种编码后的图片数据 可选 43 | int32 encode_pic_x = 5; //编码图片长 可选 44 | int32 encode_pic_y = 6; //编码图片宽 可选 45 | int32 unknown_1 = 7; //未知 一般为1 46 | int32 text_scan_id = 8; //可能是 47 | int32 unknown_3 = 9; //未知 一般为1 48 | } 49 | 50 | message QRScanRespMessage { 51 | message QRScanResult{ 52 | bytes result = 1; //二维码识别结果 53 | int32 unknow_0 = 2; //未知 一般为19 54 | double unknown_1 = 3; //未知 可能是浮点数 55 | double unknown_2 = 4; //未知 可能是浮点数 56 | int32 unknown_3 = 5; //未知 一般为1 57 | } 58 | 59 | repeated QRScanResult qr_result = 1; 60 | int32 unknown_0 = 2; //未知 一般为1 61 | } -------------------------------------------------------------------------------- /python/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | if not exist "wcocr.pyd" ( 3 | copy ..\vs.proj\x64\Debug\wcocr.dll wcocr.pyd 4 | ) 5 | python test.py 6 | pause 7 | -------------------------------------------------------------------------------- /python/test.py: -------------------------------------------------------------------------------- 1 | import wcocr 2 | import os 3 | 4 | if os.name == 'nt': 5 | wechat_path = r"C:\Program Files\Tencent\Weixin\4.0.2.13" 6 | wechatocr_path = os.getenv("APPDATA") + r"\Tencent\WeChat\XPlugin\Plugins\WeChatOCR\7079\extracted\WeChatOCR.exe" 7 | else: 8 | wechat_path = "/opt/wechat" 9 | wechatocr_path = "/opt/wechat/wxocr" 10 | 11 | wcocr.init(wechatocr_path, wechat_path) 12 | result = wcocr.ocr("../demo/test呀哈哟.png") 13 | print(result) 14 | -------------------------------------------------------------------------------- /spt/google/protobuf/any.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_ANY_H__ 32 | #define GOOGLE_PROTOBUF_ANY_H__ 33 | 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | // Must be included last. 41 | #include 42 | 43 | namespace google { 44 | namespace protobuf { 45 | 46 | class FieldDescriptor; 47 | class Message; 48 | 49 | namespace internal { 50 | 51 | extern const char kAnyFullTypeName[]; // "google.protobuf.Any". 52 | extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/". 53 | extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/". 54 | 55 | std::string GetTypeUrl(StringPiece message_name, 56 | StringPiece type_url_prefix); 57 | 58 | // Helper class used to implement google::protobuf::Any. 59 | class PROTOBUF_EXPORT AnyMetadata { 60 | typedef ArenaStringPtr UrlType; 61 | typedef ArenaStringPtr ValueType; 62 | public: 63 | // AnyMetadata does not take ownership of "type_url" and "value". 64 | constexpr AnyMetadata(UrlType* type_url, ValueType* value) 65 | : type_url_(type_url), value_(value) {} 66 | 67 | // Packs a message using the default type URL prefix: "type.googleapis.com". 68 | // The resulted type URL will be "type.googleapis.com/". 69 | // Returns false if serializing the message failed. 70 | template 71 | bool PackFrom(Arena* arena, const T& message) { 72 | return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix, 73 | T::FullMessageName()); 74 | } 75 | 76 | bool PackFrom(Arena* arena, const Message& message); 77 | 78 | // Packs a message using the given type URL prefix. The type URL will be 79 | // constructed by concatenating the message type's full name to the prefix 80 | // with an optional "/" separator if the prefix doesn't already end with "/". 81 | // For example, both PackFrom(message, "type.googleapis.com") and 82 | // PackFrom(message, "type.googleapis.com/") yield the same result type 83 | // URL: "type.googleapis.com/". 84 | // Returns false if serializing the message failed. 85 | template 86 | bool PackFrom(Arena* arena, const T& message, 87 | StringPiece type_url_prefix) { 88 | return InternalPackFrom(arena, message, type_url_prefix, 89 | T::FullMessageName()); 90 | } 91 | 92 | bool PackFrom(Arena* arena, const Message& message, 93 | StringPiece type_url_prefix); 94 | 95 | // Unpacks the payload into the given message. Returns false if the message's 96 | // type doesn't match the type specified in the type URL (i.e., the full 97 | // name after the last "/" of the type URL doesn't match the message's actual 98 | // full name) or parsing the payload has failed. 99 | template 100 | bool UnpackTo(T* message) const { 101 | return InternalUnpackTo(T::FullMessageName(), message); 102 | } 103 | 104 | bool UnpackTo(Message* message) const; 105 | 106 | // Checks whether the type specified in the type URL matches the given type. 107 | // A type is considered matching if its full name matches the full name after 108 | // the last "/" in the type URL. 109 | template 110 | bool Is() const { 111 | return InternalIs(T::FullMessageName()); 112 | } 113 | 114 | private: 115 | bool InternalPackFrom(Arena* arena, const MessageLite& message, 116 | StringPiece type_url_prefix, 117 | StringPiece type_name); 118 | bool InternalUnpackTo(StringPiece type_name, 119 | MessageLite* message) const; 120 | bool InternalIs(StringPiece type_name) const; 121 | 122 | UrlType* type_url_; 123 | ValueType* value_; 124 | 125 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata); 126 | }; 127 | 128 | // Get the proto type name from Any::type_url value. For example, passing 129 | // "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in 130 | // *full_type_name. Returns false if the type_url does not have a "/" 131 | // in the type url separating the full type name. 132 | // 133 | // NOTE: this function is available publicly as a static method on the 134 | // generated message type: google::protobuf::Any::ParseAnyTypeUrl() 135 | bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name); 136 | 137 | // Get the proto type name and prefix from Any::type_url value. For example, 138 | // passing "type.googleapis.com/rpc.QueryOrigin" will return 139 | // "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in 140 | // *full_type_name. Returns false if the type_url does not have a "/" in the 141 | // type url separating the full type name. 142 | bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix, 143 | std::string* full_type_name); 144 | 145 | // See if message is of type google.protobuf.Any, if so, return the descriptors 146 | // for "type_url" and "value" fields. 147 | bool GetAnyFieldDescriptors(const Message& message, 148 | const FieldDescriptor** type_url_field, 149 | const FieldDescriptor** value_field); 150 | 151 | } // namespace internal 152 | } // namespace protobuf 153 | } // namespace google 154 | 155 | #include 156 | 157 | #endif // GOOGLE_PROTOBUF_ANY_H__ 158 | -------------------------------------------------------------------------------- /spt/google/protobuf/arenaz_sampler.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__ 32 | #define GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__ 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | 39 | // Must be included last. 40 | #include 41 | 42 | namespace google { 43 | namespace protobuf { 44 | namespace internal { 45 | 46 | #if defined(PROTOBUF_ARENAZ_SAMPLE) 47 | struct ThreadSafeArenaStats; 48 | void RecordResetSlow(ThreadSafeArenaStats* info); 49 | void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested, 50 | size_t allocated, size_t wasted); 51 | // Stores information about a sampled thread safe arena. All mutations to this 52 | // *must* be made through `Record*` functions below. All reads from this *must* 53 | // only occur in the callback to `ThreadSafeArenazSampler::Iterate`. 54 | struct ThreadSafeArenaStats 55 | : public absl::profiling_internal::Sample { 56 | // Constructs the object but does not fill in any fields. 57 | ThreadSafeArenaStats(); 58 | ~ThreadSafeArenaStats(); 59 | 60 | // Puts the object into a clean state, fills in the logically `const` members, 61 | // blocking for any readers that are currently sampling the object. 62 | void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu); 63 | 64 | // These fields are mutated by the various Record* APIs and need to be 65 | // thread-safe. 66 | std::atomic num_allocations; 67 | std::atomic num_resets; 68 | std::atomic bytes_requested; 69 | std::atomic bytes_allocated; 70 | std::atomic bytes_wasted; 71 | // Records the largest size an arena ever had. Maintained across resets. 72 | std::atomic max_bytes_allocated; 73 | // Bit i when set to 1 indicates that a thread with tid % 63 = i accessed the 74 | // underlying arena. The field is maintained across resets. 75 | std::atomic thread_ids; 76 | 77 | // All of the fields below are set by `PrepareForSampling`, they must not 78 | // be mutated in `Record*` functions. They are logically `const` in that 79 | // sense. These are guarded by init_mu, but that is not externalized to 80 | // clients, who can only read them during 81 | // `ThreadSafeArenazSampler::Iterate` which will hold the lock. 82 | static constexpr int kMaxStackDepth = 64; 83 | int32_t depth; 84 | void* stack[kMaxStackDepth]; 85 | static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t requested, 86 | size_t allocated, size_t wasted) { 87 | if (PROTOBUF_PREDICT_TRUE(info == nullptr)) return; 88 | RecordAllocateSlow(info, requested, allocated, wasted); 89 | } 90 | }; 91 | 92 | ThreadSafeArenaStats* SampleSlow(int64_t* next_sample); 93 | void UnsampleSlow(ThreadSafeArenaStats* info); 94 | 95 | class ThreadSafeArenaStatsHandle { 96 | public: 97 | explicit ThreadSafeArenaStatsHandle() = default; 98 | explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats* info) 99 | : info_(info) {} 100 | 101 | ~ThreadSafeArenaStatsHandle() { 102 | if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return; 103 | UnsampleSlow(info_); 104 | } 105 | 106 | ThreadSafeArenaStatsHandle(ThreadSafeArenaStatsHandle&& other) noexcept 107 | : info_(absl::exchange(other.info_, nullptr)) {} 108 | 109 | ThreadSafeArenaStatsHandle& operator=( 110 | ThreadSafeArenaStatsHandle&& other) noexcept { 111 | if (PROTOBUF_PREDICT_FALSE(info_ != nullptr)) { 112 | UnsampleSlow(info_); 113 | } 114 | info_ = absl::exchange(other.info_, nullptr); 115 | return *this; 116 | } 117 | 118 | void RecordReset() { 119 | if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return; 120 | RecordResetSlow(info_); 121 | } 122 | 123 | ThreadSafeArenaStats* MutableStats() { return info_; } 124 | 125 | friend void swap(ThreadSafeArenaStatsHandle& lhs, 126 | ThreadSafeArenaStatsHandle& rhs) { 127 | std::swap(lhs.info_, rhs.info_); 128 | } 129 | 130 | friend class ThreadSafeArenaStatsHandlePeer; 131 | 132 | private: 133 | ThreadSafeArenaStats* info_ = nullptr; 134 | }; 135 | 136 | using ThreadSafeArenazSampler = 137 | ::absl::profiling_internal::SampleRecorder; 138 | 139 | extern PROTOBUF_THREAD_LOCAL int64_t global_next_sample; 140 | 141 | // Returns an RAII sampling handle that manages registration and unregistation 142 | // with the global sampler. 143 | inline ThreadSafeArenaStatsHandle Sample() { 144 | if (PROTOBUF_PREDICT_TRUE(--global_next_sample > 0)) { 145 | return ThreadSafeArenaStatsHandle(nullptr); 146 | } 147 | return ThreadSafeArenaStatsHandle(SampleSlow(&global_next_sample)); 148 | } 149 | 150 | #else 151 | struct ThreadSafeArenaStats { 152 | static void RecordAllocateStats(ThreadSafeArenaStats*, size_t /*requested*/, 153 | size_t /*allocated*/, size_t /*wasted*/) {} 154 | }; 155 | 156 | ThreadSafeArenaStats* SampleSlow(int64_t* next_sample); 157 | void UnsampleSlow(ThreadSafeArenaStats* info); 158 | 159 | class ThreadSafeArenaStatsHandle { 160 | public: 161 | explicit ThreadSafeArenaStatsHandle() = default; 162 | explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats*) {} 163 | 164 | void RecordReset() {} 165 | 166 | ThreadSafeArenaStats* MutableStats() { return nullptr; } 167 | 168 | friend void swap(ThreadSafeArenaStatsHandle&, ThreadSafeArenaStatsHandle&) {} 169 | 170 | private: 171 | friend class ThreadSafeArenaStatsHandlePeer; 172 | }; 173 | 174 | class ThreadSafeArenazSampler { 175 | public: 176 | void Unregister(ThreadSafeArenaStats*) {} 177 | void SetMaxSamples(int32_t) {} 178 | }; 179 | 180 | // Returns an RAII sampling handle that manages registration and unregistation 181 | // with the global sampler. 182 | inline ThreadSafeArenaStatsHandle Sample() { 183 | return ThreadSafeArenaStatsHandle(nullptr); 184 | } 185 | #endif // defined(PROTOBUF_ARENAZ_SAMPLE) 186 | 187 | // Returns a global Sampler. 188 | ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler(); 189 | 190 | // Enables or disables sampling for thread safe arenas. 191 | void SetThreadSafeArenazEnabled(bool enabled); 192 | 193 | // Sets the rate at which thread safe arena will be sampled. 194 | void SetThreadSafeArenazSampleParameter(int32_t rate); 195 | 196 | // Sets a soft max for the number of samples that will be kept. 197 | void SetThreadSafeArenazMaxSamples(int32_t max); 198 | 199 | // Sets the current value for when arenas should be next sampled. 200 | void SetThreadSafeArenazGlobalNextSample(int64_t next_sample); 201 | 202 | } // namespace internal 203 | } // namespace protobuf 204 | } // namespace google 205 | 206 | #include 207 | #endif // GOOGLE_PROTOBUF_SRC_PROTOBUF_ARENAZ_SAMPLER_H__ 208 | -------------------------------------------------------------------------------- /spt/google/protobuf/endian.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_ENDIAN_H__ 32 | #define GOOGLE_PROTOBUF_ENDIAN_H__ 33 | 34 | #if defined(_MSC_VER) 35 | #include 36 | #endif 37 | 38 | #include 39 | 40 | // Must be included last. 41 | #include 42 | 43 | namespace google { 44 | namespace protobuf { 45 | namespace internal { 46 | 47 | inline uint64_t BSwap64(uint64_t host_int) { 48 | #if defined(PROTOBUF_BUILTIN_BSWAP64) 49 | return PROTOBUF_BUILTIN_BSWAP64(host_int); 50 | #elif defined(_MSC_VER) 51 | return _byteswap_uint64(host_int); 52 | #else 53 | return (((host_int & uint64_t{0xFF}) << 56) | 54 | ((host_int & uint64_t{0xFF00}) << 40) | 55 | ((host_int & uint64_t{0xFF0000}) << 24) | 56 | ((host_int & uint64_t{0xFF000000}) << 8) | 57 | ((host_int & uint64_t{0xFF00000000}) >> 8) | 58 | ((host_int & uint64_t{0xFF0000000000}) >> 24) | 59 | ((host_int & uint64_t{0xFF000000000000}) >> 40) | 60 | ((host_int & uint64_t{0xFF00000000000000}) >> 56)); 61 | #endif 62 | } 63 | 64 | inline uint32_t BSwap32(uint32_t host_int) { 65 | #if defined(PROTOBUF_BUILTIN_BSWAP32) 66 | return PROTOBUF_BUILTIN_BSWAP32(host_int); 67 | #elif defined(_MSC_VER) 68 | return _byteswap_ulong(host_int); 69 | #else 70 | return (((host_int & uint32_t{0xFF}) << 24) | 71 | ((host_int & uint32_t{0xFF00}) << 8) | 72 | ((host_int & uint32_t{0xFF0000}) >> 8) | 73 | ((host_int & uint32_t{0xFF000000}) >> 24)); 74 | #endif 75 | } 76 | 77 | inline uint16_t BSwap16(uint16_t host_int) { 78 | #if defined(PROTOBUF_BUILTIN_BSWAP16) 79 | return PROTOBUF_BUILTIN_BSWAP16(host_int); 80 | #elif defined(_MSC_VER) 81 | return _byteswap_ushort(host_int); 82 | #else 83 | return (((host_int & uint16_t{0xFF}) << 8) | 84 | ((host_int & uint16_t{0xFF00}) >> 8)); 85 | #endif 86 | } 87 | 88 | namespace little_endian { 89 | 90 | inline uint16_t FromHost(uint16_t value) { 91 | #if defined(PROTOBUF_BIG_ENDIAN) 92 | return BSwap16(value); 93 | #else 94 | return value; 95 | #endif 96 | } 97 | 98 | inline uint32_t FromHost(uint32_t value) { 99 | #if defined(PROTOBUF_BIG_ENDIAN) 100 | return BSwap32(value); 101 | #else 102 | return value; 103 | #endif 104 | } 105 | 106 | inline uint64_t FromHost(uint64_t value) { 107 | #if defined(PROTOBUF_BIG_ENDIAN) 108 | return BSwap64(value); 109 | #else 110 | return value; 111 | #endif 112 | } 113 | 114 | inline uint16_t ToHost(uint16_t value) { 115 | #if defined(PROTOBUF_BIG_ENDIAN) 116 | return BSwap16(value); 117 | #else 118 | return value; 119 | #endif 120 | } 121 | 122 | inline uint32_t ToHost(uint32_t value) { 123 | #if defined(PROTOBUF_BIG_ENDIAN) 124 | return BSwap32(value); 125 | #else 126 | return value; 127 | #endif 128 | } 129 | 130 | inline uint64_t ToHost(uint64_t value) { 131 | #if defined(PROTOBUF_BIG_ENDIAN) 132 | return BSwap64(value); 133 | #else 134 | return value; 135 | #endif 136 | } 137 | 138 | } // namespace little_endian 139 | 140 | namespace big_endian { 141 | 142 | inline uint16_t FromHost(uint16_t value) { 143 | #if defined(PROTOBUF_BIG_ENDIAN) 144 | return value; 145 | #else 146 | return BSwap16(value); 147 | #endif 148 | } 149 | 150 | inline uint32_t FromHost(uint32_t value) { 151 | #if defined(PROTOBUF_BIG_ENDIAN) 152 | return value; 153 | #else 154 | return BSwap32(value); 155 | #endif 156 | } 157 | 158 | inline uint64_t FromHost(uint64_t value) { 159 | #if defined(PROTOBUF_BIG_ENDIAN) 160 | return value; 161 | #else 162 | return BSwap64(value); 163 | #endif 164 | } 165 | 166 | inline uint16_t ToHost(uint16_t value) { 167 | #if defined(PROTOBUF_BIG_ENDIAN) 168 | return value; 169 | #else 170 | return BSwap16(value); 171 | #endif 172 | } 173 | 174 | inline uint32_t ToHost(uint32_t value) { 175 | #if defined(PROTOBUF_BIG_ENDIAN) 176 | return value; 177 | #else 178 | return BSwap32(value); 179 | #endif 180 | } 181 | 182 | inline uint64_t ToHost(uint64_t value) { 183 | #if defined(PROTOBUF_BIG_ENDIAN) 184 | return value; 185 | #else 186 | return BSwap64(value); 187 | #endif 188 | } 189 | 190 | } // namespace big_endian 191 | 192 | } // namespace internal 193 | } // namespace protobuf 194 | } // namespace google 195 | 196 | #include 197 | 198 | #endif // GOOGLE_PROTOBUF_ENDIAN_H__ 199 | -------------------------------------------------------------------------------- /spt/google/protobuf/explicitly_constructed.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ 32 | #define GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ 33 | 34 | #include 35 | 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | // clang-format off 42 | #include 43 | // clang-format on 44 | 45 | namespace google { 46 | namespace protobuf { 47 | namespace internal { 48 | 49 | // Wraps a variable whose constructor and destructor are explicitly 50 | // called. It is particularly useful for a global variable, without its 51 | // constructor and destructor run on start and end of the program lifetime. 52 | // This circumvents the initial construction order fiasco, while keeping 53 | // the address of the empty string a compile time constant. 54 | // 55 | // Pay special attention to the initialization state of the object. 56 | // 1. The object is "uninitialized" to begin with. 57 | // 2. Call Construct() or DefaultConstruct() only if the object is 58 | // uninitialized. After the call, the object becomes "initialized". 59 | // 3. Call get() and get_mutable() only if the object is initialized. 60 | // 4. Call Destruct() only if the object is initialized. 61 | // After the call, the object becomes uninitialized. 62 | template 63 | class ExplicitlyConstructed { 64 | public: 65 | void DefaultConstruct() { new (&union_) T(); } 66 | 67 | template 68 | void Construct(Args&&... args) { 69 | new (&union_) T(std::forward(args)...); 70 | } 71 | 72 | void Destruct() { get_mutable()->~T(); } 73 | 74 | constexpr const T& get() const { return reinterpret_cast(union_); } 75 | T* get_mutable() { return reinterpret_cast(&union_); } 76 | 77 | private: 78 | union AlignedUnion { 79 | alignas(min_align > alignof(T) ? min_align 80 | : alignof(T)) char space[sizeof(T)]; 81 | int64_t align_to_int64; 82 | void* align_to_ptr; 83 | } union_; 84 | }; 85 | 86 | // ArenaStringPtr compatible explicitly constructed string type. 87 | // This empty string type is aligned with a minimum alignment of 8 bytes 88 | // which is the minimum requirement of ArenaStringPtr 89 | using ExplicitlyConstructedArenaString = ExplicitlyConstructed; 90 | 91 | } // namespace internal 92 | } // namespace protobuf 93 | } // namespace google 94 | 95 | #include 96 | 97 | #endif // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ 98 | -------------------------------------------------------------------------------- /spt/google/protobuf/generated_message_util.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // This file contains miscellaneous helper code used by generated code -- 36 | // including lite types -- but which should not be used directly by users. 37 | 38 | #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ 39 | #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ 40 | 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include 49 | #include // Add direct dep on port for pb.cc 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | 60 | // Must be included last. 61 | #include 62 | 63 | #ifdef SWIG 64 | #error "You cannot SWIG proto headers" 65 | #endif 66 | 67 | namespace google { 68 | namespace protobuf { 69 | 70 | class Arena; 71 | class Message; 72 | 73 | namespace io { 74 | class CodedInputStream; 75 | } 76 | 77 | namespace internal { 78 | 79 | template 80 | inline To DownCast(From* f) { 81 | return PROTOBUF_NAMESPACE_ID::internal::down_cast(f); 82 | } 83 | template 84 | inline To DownCast(From& f) { 85 | return PROTOBUF_NAMESPACE_ID::internal::down_cast(f); 86 | } 87 | 88 | 89 | // This fastpath inlines a single branch instead of having to make the 90 | // InitProtobufDefaults function call. 91 | // It also generates less inlined code than a function-scope static initializer. 92 | PROTOBUF_EXPORT extern std::atomic init_protobuf_defaults_state; 93 | PROTOBUF_EXPORT void InitProtobufDefaultsSlow(); 94 | PROTOBUF_EXPORT inline void InitProtobufDefaults() { 95 | if (PROTOBUF_PREDICT_FALSE( 96 | !init_protobuf_defaults_state.load(std::memory_order_acquire))) { 97 | InitProtobufDefaultsSlow(); 98 | } 99 | } 100 | 101 | // This used by proto1 102 | PROTOBUF_EXPORT inline const std::string& GetEmptyString() { 103 | InitProtobufDefaults(); 104 | return GetEmptyStringAlreadyInited(); 105 | } 106 | 107 | 108 | // True if IsInitialized() is true for all elements of t. Type is expected 109 | // to be a RepeatedPtrField. It's useful to have this 110 | // helper here to keep the protobuf compiler from ever having to emit loops in 111 | // IsInitialized() methods. We want the C++ compiler to inline this or not 112 | // as it sees fit. 113 | template 114 | bool AllAreInitialized(const RepeatedPtrField& t) { 115 | for (int i = t.size(); --i >= 0;) { 116 | if (!t.Get(i).IsInitialized()) return false; 117 | } 118 | return true; 119 | } 120 | 121 | // "Weak" variant of AllAreInitialized, used to implement implicit weak fields. 122 | // This version operates on MessageLite to avoid introducing a dependency on the 123 | // concrete message type. 124 | template 125 | bool AllAreInitializedWeak(const RepeatedPtrField& t) { 126 | for (int i = t.size(); --i >= 0;) { 127 | if (!reinterpret_cast(t) 128 | .Get >(i) 129 | .IsInitialized()) { 130 | return false; 131 | } 132 | } 133 | return true; 134 | } 135 | 136 | inline bool IsPresent(const void* base, uint32_t hasbit) { 137 | const uint32_t* has_bits_array = static_cast(base); 138 | return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0; 139 | } 140 | 141 | inline bool IsOneofPresent(const void* base, uint32_t offset, uint32_t tag) { 142 | const uint32_t* oneof = reinterpret_cast( 143 | static_cast(base) + offset); 144 | return *oneof == tag >> 3; 145 | } 146 | 147 | typedef void (*SpecialSerializer)(const uint8_t* base, uint32_t offset, 148 | uint32_t tag, uint32_t has_offset, 149 | io::CodedOutputStream* output); 150 | 151 | PROTOBUF_EXPORT void ExtensionSerializer(const MessageLite* extendee, 152 | const uint8_t* ptr, uint32_t offset, 153 | uint32_t tag, uint32_t has_offset, 154 | io::CodedOutputStream* output); 155 | PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8_t* base, 156 | uint32_t offset, uint32_t tag, 157 | uint32_t has_offset, 158 | io::CodedOutputStream* output); 159 | 160 | PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message); 161 | PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena, 162 | MessageLite* submessage, 163 | Arena* submessage_arena); 164 | PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2); 165 | // We specialize GenericSwap for non-lite messages to benefit from reflection. 166 | PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2); 167 | 168 | template 169 | T* DuplicateIfNonNull(T* message) { 170 | // The casts must be reinterpret_cast<> because T might be a forward-declared 171 | // type that the compiler doesn't know is related to MessageLite. 172 | return reinterpret_cast( 173 | DuplicateIfNonNullInternal(reinterpret_cast(message))); 174 | } 175 | 176 | template 177 | T* GetOwnedMessage(Arena* message_arena, T* submessage, 178 | Arena* submessage_arena) { 179 | // The casts must be reinterpret_cast<> because T might be a forward-declared 180 | // type that the compiler doesn't know is related to MessageLite. 181 | return reinterpret_cast(GetOwnedMessageInternal( 182 | message_arena, reinterpret_cast(submessage), 183 | submessage_arena)); 184 | } 185 | 186 | // Hide atomic from the public header and allow easy change to regular int 187 | // on platforms where the atomic might have a perf impact. 188 | class PROTOBUF_EXPORT CachedSize { 189 | public: 190 | int Get() const { return size_.load(std::memory_order_relaxed); } 191 | void Set(int size) { size_.store(size, std::memory_order_relaxed); } 192 | 193 | private: 194 | std::atomic size_{0}; 195 | }; 196 | 197 | PROTOBUF_EXPORT void DestroyMessage(const void* message); 198 | PROTOBUF_EXPORT void DestroyString(const void* s); 199 | // Destroy (not delete) the message 200 | inline void OnShutdownDestroyMessage(const void* ptr) { 201 | OnShutdownRun(DestroyMessage, ptr); 202 | } 203 | // Destroy the string (call std::string destructor) 204 | inline void OnShutdownDestroyString(const std::string* ptr) { 205 | OnShutdownRun(DestroyString, ptr); 206 | } 207 | 208 | } // namespace internal 209 | } // namespace protobuf 210 | } // namespace google 211 | 212 | #include 213 | 214 | #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ 215 | -------------------------------------------------------------------------------- /spt/google/protobuf/has_bits.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_HAS_BITS_H__ 32 | #define GOOGLE_PROTOBUF_HAS_BITS_H__ 33 | 34 | #include 35 | #include 36 | 37 | // Must be included last. 38 | #include 39 | 40 | #ifdef SWIG 41 | #error "You cannot SWIG proto headers" 42 | #endif 43 | 44 | namespace google { 45 | namespace protobuf { 46 | namespace internal { 47 | 48 | template 49 | class HasBits { 50 | public: 51 | PROTOBUF_NDEBUG_INLINE constexpr HasBits() : has_bits_{} {} 52 | 53 | PROTOBUF_NDEBUG_INLINE void Clear() { 54 | memset(has_bits_, 0, sizeof(has_bits_)); 55 | } 56 | 57 | PROTOBUF_NDEBUG_INLINE uint32_t& operator[](int index) { 58 | return has_bits_[index]; 59 | } 60 | 61 | PROTOBUF_NDEBUG_INLINE const uint32_t& operator[](int index) const { 62 | return has_bits_[index]; 63 | } 64 | 65 | bool operator==(const HasBits& rhs) const { 66 | return memcmp(has_bits_, rhs.has_bits_, sizeof(has_bits_)) == 0; 67 | } 68 | 69 | bool operator!=(const HasBits& rhs) const { 70 | return !(*this == rhs); 71 | } 72 | 73 | void Or(const HasBits& rhs) { 74 | for (size_t i = 0; i < doublewords; i++) has_bits_[i] |= rhs[i]; 75 | } 76 | 77 | bool empty() const; 78 | 79 | private: 80 | uint32_t has_bits_[doublewords]; 81 | }; 82 | 83 | template <> 84 | inline bool HasBits<1>::empty() const { 85 | return !has_bits_[0]; 86 | } 87 | 88 | template <> 89 | inline bool HasBits<2>::empty() const { 90 | return !(has_bits_[0] | has_bits_[1]); 91 | } 92 | 93 | template <> 94 | inline bool HasBits<3>::empty() const { 95 | return !(has_bits_[0] | has_bits_[1] | has_bits_[2]); 96 | } 97 | 98 | template <> 99 | inline bool HasBits<4>::empty() const { 100 | return !(has_bits_[0] | has_bits_[1] | has_bits_[2] | has_bits_[3]); 101 | } 102 | 103 | template 104 | inline bool HasBits::empty() const { 105 | for (size_t i = 0; i < doublewords; ++i) { 106 | if (has_bits_[i]) return false; 107 | } 108 | return true; 109 | } 110 | 111 | } // namespace internal 112 | } // namespace protobuf 113 | } // namespace google 114 | 115 | #include 116 | 117 | #endif // GOOGLE_PROTOBUF_HAS_BITS_H__ 118 | -------------------------------------------------------------------------------- /spt/google/protobuf/implicit_weak_message.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ 32 | #define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ 33 | 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef SWIG 42 | #error "You cannot SWIG proto headers" 43 | #endif 44 | 45 | // Must be included last. 46 | #include 47 | 48 | // This file is logically internal-only and should only be used by protobuf 49 | // generated code. 50 | 51 | namespace google { 52 | namespace protobuf { 53 | namespace internal { 54 | 55 | // An implementation of MessageLite that treats all data as unknown. This type 56 | // acts as a placeholder for an implicit weak field in the case where the true 57 | // message type does not get linked into the binary. 58 | class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite { 59 | public: 60 | ImplicitWeakMessage() : data_(new std::string) {} 61 | explicit constexpr ImplicitWeakMessage(ConstantInitialized) 62 | : data_(nullptr) {} 63 | explicit ImplicitWeakMessage(Arena* arena) 64 | : MessageLite(arena), data_(new std::string) {} 65 | 66 | ~ImplicitWeakMessage() override { 67 | // data_ will be null in the default instance, but we can safely call delete 68 | // here because the default instance will never be destroyed. 69 | delete data_; 70 | } 71 | 72 | static const ImplicitWeakMessage* default_instance(); 73 | 74 | std::string GetTypeName() const override { return ""; } 75 | 76 | MessageLite* New(Arena* arena) const override { 77 | return Arena::CreateMessage(arena); 78 | } 79 | 80 | void Clear() override { data_->clear(); } 81 | 82 | bool IsInitialized() const override { return true; } 83 | 84 | void CheckTypeAndMergeFrom(const MessageLite& other) override { 85 | const std::string* other_data = 86 | static_cast(other).data_; 87 | if (other_data != nullptr) { 88 | data_->append(*other_data); 89 | } 90 | } 91 | 92 | const char* _InternalParse(const char* ptr, ParseContext* ctx) final; 93 | 94 | size_t ByteSizeLong() const override { 95 | return data_ == nullptr ? 0 : data_->size(); 96 | } 97 | 98 | uint8_t* _InternalSerialize(uint8_t* target, 99 | io::EpsCopyOutputStream* stream) const final { 100 | if (data_ == nullptr) { 101 | return target; 102 | } 103 | return stream->WriteRaw(data_->data(), static_cast(data_->size()), 104 | target); 105 | } 106 | 107 | int GetCachedSize() const override { 108 | return data_ == nullptr ? 0 : static_cast(data_->size()); 109 | } 110 | 111 | typedef void InternalArenaConstructable_; 112 | 113 | private: 114 | // This std::string is allocated on the heap, but we use a raw pointer so that 115 | // the default instance can be constant-initialized. In the const methods, we 116 | // have to handle the possibility of data_ being null. 117 | std::string* data_; 118 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage); 119 | }; 120 | 121 | struct ImplicitWeakMessageDefaultType; 122 | extern ImplicitWeakMessageDefaultType implicit_weak_message_default_instance; 123 | 124 | // A type handler for use with implicit weak repeated message fields. 125 | template 126 | class ImplicitWeakTypeHandler { 127 | public: 128 | typedef MessageLite Type; 129 | static constexpr bool Moveable = false; 130 | 131 | static inline MessageLite* NewFromPrototype(const MessageLite* prototype, 132 | Arena* arena = nullptr) { 133 | return prototype->New(arena); 134 | } 135 | 136 | static inline void Delete(MessageLite* value, Arena* arena) { 137 | if (arena == nullptr) { 138 | delete value; 139 | } 140 | } 141 | static inline Arena* GetArena(MessageLite* value) { 142 | return value->GetArena(); 143 | } 144 | static inline void Clear(MessageLite* value) { value->Clear(); } 145 | static void Merge(const MessageLite& from, MessageLite* to) { 146 | to->CheckTypeAndMergeFrom(from); 147 | } 148 | }; 149 | 150 | } // namespace internal 151 | 152 | template 153 | struct WeakRepeatedPtrField { 154 | using TypeHandler = internal::ImplicitWeakTypeHandler; 155 | constexpr WeakRepeatedPtrField() : weak() {} 156 | explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {} 157 | ~WeakRepeatedPtrField() { weak.template Destroy(); } 158 | 159 | typedef internal::RepeatedPtrIterator iterator; 160 | typedef internal::RepeatedPtrIterator const_iterator; 161 | typedef internal::RepeatedPtrOverPtrsIterator 162 | pointer_iterator; 163 | typedef internal::RepeatedPtrOverPtrsIterator 165 | const_pointer_iterator; 166 | 167 | iterator begin() { return iterator(base().raw_data()); } 168 | const_iterator begin() const { return iterator(base().raw_data()); } 169 | const_iterator cbegin() const { return begin(); } 170 | iterator end() { return begin() + base().size(); } 171 | const_iterator end() const { return begin() + base().size(); } 172 | const_iterator cend() const { return end(); } 173 | pointer_iterator pointer_begin() { 174 | return pointer_iterator(base().raw_mutable_data()); 175 | } 176 | const_pointer_iterator pointer_begin() const { 177 | return const_pointer_iterator(base().raw_mutable_data()); 178 | } 179 | pointer_iterator pointer_end() { 180 | return pointer_iterator(base().raw_mutable_data() + base().size()); 181 | } 182 | const_pointer_iterator pointer_end() const { 183 | return const_pointer_iterator(base().raw_mutable_data() + base().size()); 184 | } 185 | 186 | MessageLite* AddWeak(const MessageLite* prototype) { 187 | return base().AddWeak(prototype); 188 | } 189 | T* Add() { return weak.Add(); } 190 | void Clear() { base().template Clear(); } 191 | void MergeFrom(const WeakRepeatedPtrField& other) { 192 | base().template MergeFrom(other.base()); 193 | } 194 | void InternalSwap(WeakRepeatedPtrField* other) { 195 | base().InternalSwap(&other->base()); 196 | } 197 | 198 | const internal::RepeatedPtrFieldBase& base() const { return weak; } 199 | internal::RepeatedPtrFieldBase& base() { return weak; } 200 | // Union disables running the destructor. Which would create a strong link. 201 | // Instead we explicitly destroy the underlying base through the virtual 202 | // destructor. 203 | union { 204 | RepeatedPtrField weak; 205 | }; 206 | }; 207 | 208 | } // namespace protobuf 209 | } // namespace google 210 | 211 | #include 212 | 213 | #endif // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ 214 | -------------------------------------------------------------------------------- /spt/google/protobuf/io/zero_copy_stream.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // This file contains the ZeroCopyInputStream and ZeroCopyOutputStream 36 | // interfaces, which represent abstract I/O streams to and from which 37 | // protocol buffers can be read and written. For a few simple 38 | // implementations of these interfaces, see zero_copy_stream_impl.h. 39 | // 40 | // These interfaces are different from classic I/O streams in that they 41 | // try to minimize the amount of data copying that needs to be done. 42 | // To accomplish this, responsibility for allocating buffers is moved to 43 | // the stream object, rather than being the responsibility of the caller. 44 | // So, the stream can return a buffer which actually points directly into 45 | // the final data structure where the bytes are to be stored, and the caller 46 | // can interact directly with that buffer, eliminating an intermediate copy 47 | // operation. 48 | // 49 | // As an example, consider the common case in which you are reading bytes 50 | // from an array that is already in memory (or perhaps an mmap()ed file). 51 | // With classic I/O streams, you would do something like: 52 | // char buffer[BUFFER_SIZE]; 53 | // input->Read(buffer, BUFFER_SIZE); 54 | // DoSomething(buffer, BUFFER_SIZE); 55 | // Then, the stream basically just calls memcpy() to copy the data from 56 | // the array into your buffer. With a ZeroCopyInputStream, you would do 57 | // this instead: 58 | // const void* buffer; 59 | // int size; 60 | // input->Next(&buffer, &size); 61 | // DoSomething(buffer, size); 62 | // Here, no copy is performed. The input stream returns a pointer directly 63 | // into the backing array, and the caller ends up reading directly from it. 64 | // 65 | // If you want to be able to read the old-fashion way, you can create 66 | // a CodedInputStream or CodedOutputStream wrapping these objects and use 67 | // their ReadRaw()/WriteRaw() methods. These will, of course, add a copy 68 | // step, but Coded*Stream will handle buffering so at least it will be 69 | // reasonably efficient. 70 | // 71 | // ZeroCopyInputStream example: 72 | // // Read in a file and print its contents to stdout. 73 | // int fd = open("myfile", O_RDONLY); 74 | // ZeroCopyInputStream* input = new FileInputStream(fd); 75 | // 76 | // const void* buffer; 77 | // int size; 78 | // while (input->Next(&buffer, &size)) { 79 | // cout.write(buffer, size); 80 | // } 81 | // 82 | // delete input; 83 | // close(fd); 84 | // 85 | // ZeroCopyOutputStream example: 86 | // // Copy the contents of "infile" to "outfile", using plain read() for 87 | // // "infile" but a ZeroCopyOutputStream for "outfile". 88 | // int infd = open("infile", O_RDONLY); 89 | // int outfd = open("outfile", O_WRONLY); 90 | // ZeroCopyOutputStream* output = new FileOutputStream(outfd); 91 | // 92 | // void* buffer; 93 | // int size; 94 | // while (output->Next(&buffer, &size)) { 95 | // int bytes = read(infd, buffer, size); 96 | // if (bytes < size) { 97 | // // Reached EOF. 98 | // output->BackUp(size - bytes); 99 | // break; 100 | // } 101 | // } 102 | // 103 | // delete output; 104 | // close(infd); 105 | // close(outfd); 106 | 107 | #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ 108 | #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ 109 | 110 | 111 | #include 112 | 113 | 114 | // Must be included last. 115 | #include 116 | 117 | namespace google { 118 | namespace protobuf { 119 | namespace io { 120 | 121 | // Defined in this file. 122 | class ZeroCopyInputStream; 123 | class ZeroCopyOutputStream; 124 | 125 | // Abstract interface similar to an input stream but designed to minimize 126 | // copying. 127 | class PROTOBUF_EXPORT ZeroCopyInputStream { 128 | public: 129 | ZeroCopyInputStream() {} 130 | virtual ~ZeroCopyInputStream() {} 131 | 132 | // Obtains a chunk of data from the stream. 133 | // 134 | // Preconditions: 135 | // * "size" and "data" are not NULL. 136 | // 137 | // Postconditions: 138 | // * If the returned value is false, there is no more data to return or 139 | // an error occurred. All errors are permanent. 140 | // * Otherwise, "size" points to the actual number of bytes read and "data" 141 | // points to a pointer to a buffer containing these bytes. 142 | // * Ownership of this buffer remains with the stream, and the buffer 143 | // remains valid only until some other method of the stream is called 144 | // or the stream is destroyed. 145 | // * It is legal for the returned buffer to have zero size, as long 146 | // as repeatedly calling Next() eventually yields a buffer with non-zero 147 | // size. 148 | virtual bool Next(const void** data, int* size) = 0; 149 | 150 | // Backs up a number of bytes, so that the next call to Next() returns 151 | // data again that was already returned by the last call to Next(). This 152 | // is useful when writing procedures that are only supposed to read up 153 | // to a certain point in the input, then return. If Next() returns a 154 | // buffer that goes beyond what you wanted to read, you can use BackUp() 155 | // to return to the point where you intended to finish. 156 | // 157 | // This method can be called with `count = 0` to finalize (flush) any 158 | // previously returned buffer. For example, a file output stream can 159 | // flush buffers returned from a previous call to Next() upon such 160 | // BackUp(0) invocations. ZeroCopyOutputStream callers should always 161 | // invoke BackUp() after a final Next() call, even if there is no 162 | // excess buffer data to be backed up to indicate a flush point. 163 | // 164 | // Preconditions: 165 | // * The last method called must have been Next(). 166 | // * count must be less than or equal to the size of the last buffer 167 | // returned by Next(). 168 | // 169 | // Postconditions: 170 | // * The last "count" bytes of the last buffer returned by Next() will be 171 | // pushed back into the stream. Subsequent calls to Next() will return 172 | // the same data again before producing new data. 173 | virtual void BackUp(int count) = 0; 174 | 175 | // Skips a number of bytes. Returns false if the end of the stream is 176 | // reached or some input error occurred. In the end-of-stream case, the 177 | // stream is advanced to the end of the stream (so ByteCount() will return 178 | // the total size of the stream). 179 | virtual bool Skip(int count) = 0; 180 | 181 | // Returns the total number of bytes read since this object was created. 182 | virtual int64_t ByteCount() const = 0; 183 | 184 | 185 | private: 186 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream); 187 | }; 188 | 189 | // Abstract interface similar to an output stream but designed to minimize 190 | // copying. 191 | class PROTOBUF_EXPORT ZeroCopyOutputStream { 192 | public: 193 | ZeroCopyOutputStream() {} 194 | virtual ~ZeroCopyOutputStream() {} 195 | 196 | // Obtains a buffer into which data can be written. Any data written 197 | // into this buffer will eventually (maybe instantly, maybe later on) 198 | // be written to the output. 199 | // 200 | // Preconditions: 201 | // * "size" and "data" are not NULL. 202 | // 203 | // Postconditions: 204 | // * If the returned value is false, an error occurred. All errors are 205 | // permanent. 206 | // * Otherwise, "size" points to the actual number of bytes in the buffer 207 | // and "data" points to the buffer. 208 | // * Ownership of this buffer remains with the stream, and the buffer 209 | // remains valid only until some other method of the stream is called 210 | // or the stream is destroyed. 211 | // * Any data which the caller stores in this buffer will eventually be 212 | // written to the output (unless BackUp() is called). 213 | // * It is legal for the returned buffer to have zero size, as long 214 | // as repeatedly calling Next() eventually yields a buffer with non-zero 215 | // size. 216 | virtual bool Next(void** data, int* size) = 0; 217 | 218 | // Backs up a number of bytes, so that the end of the last buffer returned 219 | // by Next() is not actually written. This is needed when you finish 220 | // writing all the data you want to write, but the last buffer was bigger 221 | // than you needed. You don't want to write a bunch of garbage after the 222 | // end of your data, so you use BackUp() to back up. 223 | // 224 | // Preconditions: 225 | // * The last method called must have been Next(). 226 | // * count must be less than or equal to the size of the last buffer 227 | // returned by Next(). 228 | // * The caller must not have written anything to the last "count" bytes 229 | // of that buffer. 230 | // 231 | // Postconditions: 232 | // * The last "count" bytes of the last buffer returned by Next() will be 233 | // ignored. 234 | virtual void BackUp(int count) = 0; 235 | 236 | // Returns the total number of bytes written since this object was created. 237 | virtual int64_t ByteCount() const = 0; 238 | 239 | // Write a given chunk of data to the output. Some output streams may 240 | // implement this in a way that avoids copying. Check AllowsAliasing() before 241 | // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is 242 | // called on a stream that does not allow aliasing. 243 | // 244 | // NOTE: It is caller's responsibility to ensure that the chunk of memory 245 | // remains live until all of the data has been consumed from the stream. 246 | virtual bool WriteAliasedRaw(const void* data, int size); 247 | virtual bool AllowsAliasing() const { return false; } 248 | 249 | 250 | private: 251 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream); 252 | }; 253 | 254 | } // namespace io 255 | } // namespace protobuf 256 | } // namespace google 257 | 258 | #include 259 | 260 | #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ 261 | -------------------------------------------------------------------------------- /spt/google/protobuf/port.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // A common header that is included across all protobuf headers. We do our best 32 | // to avoid #defining any macros here; instead we generally put macros in 33 | // port_def.inc and port_undef.inc so they are not visible from outside of 34 | // protobuf. 35 | 36 | #ifndef GOOGLE_PROTOBUF_PORT_H__ 37 | #define GOOGLE_PROTOBUF_PORT_H__ 38 | 39 | #include 40 | #include 41 | 42 | 43 | namespace google { 44 | namespace protobuf { 45 | namespace internal { 46 | inline void SizedDelete(void* p, size_t size) { 47 | #if defined(__cpp_sized_deallocation) 48 | ::operator delete(p, size); 49 | #else 50 | ::operator delete(p); 51 | #endif 52 | } 53 | inline void SizedArrayDelete(void* p, size_t size) { 54 | #if defined(__cpp_sized_deallocation) 55 | ::operator delete[](p, size); 56 | #else 57 | ::operator delete[](p); 58 | #endif 59 | } 60 | 61 | // Tag type used to invoke the constinit constructor overload of classes 62 | // such as ArenaStringPtr and MapFieldBase. Such constructors are internal 63 | // implementation details of the library. 64 | struct ConstantInitialized { 65 | explicit ConstantInitialized() = default; 66 | }; 67 | 68 | // Tag type used to invoke the arena constructor overload of classes such 69 | // as ExtensionSet and MapFieldLite in aggregate initialization. These 70 | // classes typically don't have move/copy constructors, which rules out 71 | // explicit initialization in pre-C++17. 72 | struct ArenaInitialized { 73 | explicit ArenaInitialized() = default; 74 | }; 75 | 76 | } // namespace internal 77 | } // namespace protobuf 78 | } // namespace google 79 | 80 | #endif // GOOGLE_PROTOBUF_PORT_H__ 81 | -------------------------------------------------------------------------------- /spt/google/protobuf/port_undef.inc: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // #undefs all macros defined in port_def.inc. See comments in port_def.inc 32 | // for more info. 33 | 34 | #ifndef PROTOBUF_NAMESPACE 35 | #error "port_undef.inc must be included after port_def.inc" 36 | #endif 37 | 38 | #undef PROTOBUF_BUILTIN_BSWAP16 39 | #undef PROTOBUF_BUILTIN_BSWAP32 40 | #undef PROTOBUF_BUILTIN_BSWAP64 41 | #undef PROTOBUF_GNUC_MIN 42 | #undef PROTOBUF_MSC_VER_MIN 43 | #undef PROTOBUF_CPLUSPLUS_MIN 44 | #undef PROTOBUF_NAMESPACE 45 | #undef PROTOBUF_NAMESPACE_ID 46 | #undef PROTOBUF_ALWAYS_INLINE 47 | #undef PROTOBUF_NDEBUG_INLINE 48 | #undef PROTOBUF_MUSTTAIL 49 | #undef PROTOBUF_TAILCALL 50 | #undef PROTOBUF_COLD 51 | #undef PROTOBUF_NOINLINE 52 | #undef PROTOBUF_SECTION_VARIABLE 53 | #undef PROTOBUF_DEPRECATED 54 | #undef PROTOBUF_DEPRECATED_ENUM 55 | #undef PROTOBUF_DEPRECATED_MSG 56 | #undef PROTOBUF_FUNC_ALIGN 57 | #undef PROTOBUF_RETURNS_NONNULL 58 | #undef PROTOBUF_ATTRIBUTE_REINITIALIZES 59 | #undef PROTOBUF_RTTI 60 | #undef PROTOBUF_VERSION 61 | #undef PROTOBUF_VERSION_SUFFIX 62 | #undef PROTOBUF_FIELD_OFFSET 63 | #undef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 64 | #undef PROTOBUF_MIN_PROTOC_VERSION 65 | #undef PROTOBUF_PREDICT_TRUE 66 | #undef PROTOBUF_PREDICT_FALSE 67 | #undef PROTOBUF_FALLTHROUGH_INTENDED 68 | #undef PROTOBUF_EXPORT 69 | #undef PROTOC_EXPORT 70 | #undef PROTOBUF_NODISCARD 71 | #undef PROTOBUF_FORCE_COPY_IN_RELEASE 72 | #undef PROTOBUF_FORCE_COPY_IN_SWAP 73 | #undef PROTOBUF_FORCE_COPY_IN_MOVE 74 | #undef PROTOBUF_FORCE_RESET_IN_CLEAR 75 | #undef PROTOBUF_FORCE_COPY_DEFAULT_STRING 76 | #undef PROTOBUF_NAMESPACE_OPEN 77 | #undef PROTOBUF_NAMESPACE_CLOSE 78 | #undef PROTOBUF_UNUSED 79 | #undef PROTOBUF_ASSUME 80 | #undef PROTOBUF_EXPORT_TEMPLATE_DECLARE 81 | #undef PROTOBUF_EXPORT_TEMPLATE_DEFINE 82 | #undef PROTOBUF_ALIGNAS 83 | #undef PROTOBUF_FINAL 84 | #undef PROTOBUF_FUTURE_FINAL 85 | #undef PROTOBUF_THREAD_LOCAL 86 | #undef PROTOBUF_LITTLE_ENDIAN 87 | #undef PROTOBUF_BIG_ENDIAN 88 | #undef PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT 89 | #undef PROTOBUF_CONSTINIT 90 | #undef PROTOBUF_CONSTEXPR 91 | #undef PROTOBUF_ATTRIBUTE_WEAK 92 | #undef PROTOBUF_HAVE_ATTRIBUTE_WEAK 93 | #undef PROTOBUF_ATTRIBUTE_NO_DESTROY 94 | #undef PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG 95 | #undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 96 | #undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 97 | #undef PROTOBUF_PRAGMA_INIT_SEG 98 | #undef PROTOBUF_ASAN 99 | #undef PROTOBUF_MSAN 100 | #undef PROTOBUF_TSAN 101 | #undef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED 102 | #undef PROTOBUF_TC_PARAM_DECL 103 | #undef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED 104 | #undef PROTOBUF_LOCKS_EXCLUDED 105 | #undef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS 106 | #undef PROTOBUF_GUARDED_BY 107 | 108 | #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES 109 | #undef PROTOBUF_FUTURE_BREAKING_CHANGES 110 | #endif 111 | 112 | // Restore macro that may have been #undef'd in port_def.inc. 113 | #ifdef _MSC_VER 114 | #pragma pop_macro("CREATE_NEW") 115 | #pragma pop_macro("DELETE") 116 | #pragma pop_macro("DOUBLE_CLICK") 117 | #pragma pop_macro("ERROR") 118 | #pragma pop_macro("ERROR_BUSY") 119 | #pragma pop_macro("ERROR_INSTALL_FAILED") 120 | #pragma pop_macro("ERROR_NOT_FOUND") 121 | #pragma pop_macro("GetClassName") 122 | #pragma pop_macro("GetMessage") 123 | #pragma pop_macro("GetObject") 124 | #pragma pop_macro("IGNORE") 125 | #pragma pop_macro("IN") 126 | #pragma pop_macro("INPUT_KEYBOARD") 127 | #pragma pop_macro("OUT") 128 | #pragma pop_macro("OPTIONAL") 129 | #pragma pop_macro("min") 130 | #pragma pop_macro("max") 131 | #pragma pop_macro("NEAR") 132 | #pragma pop_macro("NO_DATA") 133 | #pragma pop_macro("NO_ERROR") 134 | #pragma pop_macro("REASON_UNKNOWN") 135 | #pragma pop_macro("SERVICE_DISABLED") 136 | #pragma pop_macro("SEVERITY_ERROR") 137 | #pragma pop_macro("STRICT") 138 | #pragma pop_macro("STATUS_PENDING") 139 | #pragma pop_macro("timezone") 140 | #endif 141 | 142 | #ifdef __APPLE__ 143 | #pragma pop_macro("DOMAIN") 144 | #pragma pop_macro("TRUE") 145 | #pragma pop_macro("FALSE") 146 | #pragma pop_macro("UID_MAX") 147 | #endif // __APPLE__ 148 | 149 | #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) 150 | #pragma pop_macro("DEBUG") 151 | #endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) 152 | 153 | #if defined(__GNUC__) 154 | #pragma GCC diagnostic pop 155 | #endif 156 | 157 | #ifdef __clang__ 158 | #pragma clang diagnostic pop 159 | #endif 160 | 161 | // Pop the warning(push) from port_def.inc 162 | #ifdef _MSC_VER 163 | #pragma warning(pop) 164 | #endif 165 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/casts.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2014 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_CASTS_H__ 32 | #define GOOGLE_PROTOBUF_CASTS_H__ 33 | 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | namespace google { 40 | namespace protobuf { 41 | namespace internal { 42 | 43 | // Use implicit_cast as a safe version of static_cast or const_cast 44 | // for upcasting in the type hierarchy (i.e. casting a pointer to Foo 45 | // to a pointer to SuperclassOfFoo or casting a pointer to Foo to 46 | // a const pointer to Foo). 47 | // When you use implicit_cast, the compiler checks that the cast is safe. 48 | // Such explicit implicit_casts are necessary in surprisingly many 49 | // situations where C++ demands an exact type match instead of an 50 | // argument type convertible to a target type. 51 | // 52 | // The From type can be inferred, so the preferred syntax for using 53 | // implicit_cast is the same as for static_cast etc.: 54 | // 55 | // implicit_cast(expr) 56 | // 57 | // implicit_cast would have been part of the C++ standard library, 58 | // but the proposal was submitted too late. It will probably make 59 | // its way into the language in the future. 60 | template 61 | inline To implicit_cast(From const &f) { 62 | return f; 63 | } 64 | 65 | // When you upcast (that is, cast a pointer from type Foo to type 66 | // SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts 67 | // always succeed. When you downcast (that is, cast a pointer from 68 | // type Foo to type SubclassOfFoo), static_cast<> isn't safe, because 69 | // how do you know the pointer is really of type SubclassOfFoo? It 70 | // could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, 71 | // when you downcast, you should use this macro. In debug mode, we 72 | // use dynamic_cast<> to double-check the downcast is legal (we die 73 | // if it's not). In normal mode, we do the efficient static_cast<> 74 | // instead. Thus, it's important to test in debug mode to make sure 75 | // the cast is legal! 76 | // This is the only place in the code we should use dynamic_cast<>. 77 | // In particular, you SHOULDN'T be using dynamic_cast<> in order to 78 | // do RTTI (eg code like this: 79 | // if (dynamic_cast(foo)) HandleASubclass1Object(foo); 80 | // if (dynamic_cast(foo)) HandleASubclass2Object(foo); 81 | // You should design the code some other way not to need this. 82 | 83 | template // use like this: down_cast(foo); 84 | inline To down_cast(From* f) { // so we only accept pointers 85 | // Ensures that To is a sub-type of From *. This test is here only 86 | // for compile-time type checking, and has no overhead in an 87 | // optimized build at run-time, as it will be optimized away 88 | // completely. 89 | if (false) { 90 | implicit_cast(0); 91 | } 92 | 93 | #if !defined(NDEBUG) && PROTOBUF_RTTI 94 | assert(f == nullptr || dynamic_cast(f) != nullptr); // RTTI: debug mode only! 95 | #endif 96 | return static_cast(f); 97 | } 98 | 99 | template // use like this: down_cast(foo); 100 | inline To down_cast(From& f) { 101 | typedef typename std::remove_reference::type* ToAsPointer; 102 | // Ensures that To is a sub-type of From *. This test is here only 103 | // for compile-time type checking, and has no overhead in an 104 | // optimized build at run-time, as it will be optimized away 105 | // completely. 106 | if (false) { 107 | implicit_cast(0); 108 | } 109 | 110 | #if !defined(NDEBUG) && PROTOBUF_RTTI 111 | // RTTI: debug mode only! 112 | assert(dynamic_cast(&f) != nullptr); 113 | #endif 114 | return *static_cast(&f); 115 | } 116 | 117 | template 118 | inline To bit_cast(const From& from) { 119 | static_assert(sizeof(From) == sizeof(To), "bit_cast_with_different_sizes"); 120 | To dest; 121 | memcpy(&dest, &from, sizeof(dest)); 122 | return dest; 123 | } 124 | 125 | } // namespace internal 126 | 127 | // We made these internal so that they would show up as such in the docs, 128 | // but we don't want to stick "internal::" in front of them everywhere. 129 | using internal::implicit_cast; 130 | using internal::down_cast; 131 | using internal::bit_cast; 132 | 133 | } // namespace protobuf 134 | } // namespace google 135 | 136 | #include 137 | 138 | #endif // GOOGLE_PROTOBUF_CASTS_H__ 139 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/common.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) and others 32 | // 33 | // Contains basic types and utilities used by the rest of the library. 34 | 35 | #ifndef GOOGLE_PROTOBUF_COMMON_H__ 36 | #define GOOGLE_PROTOBUF_COMMON_H__ 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #ifndef PROTOBUF_USE_EXCEPTIONS 52 | #if defined(_MSC_VER) && defined(_CPPUNWIND) 53 | #define PROTOBUF_USE_EXCEPTIONS 1 54 | #elif defined(__EXCEPTIONS) 55 | #define PROTOBUF_USE_EXCEPTIONS 1 56 | #else 57 | #define PROTOBUF_USE_EXCEPTIONS 0 58 | #endif 59 | #endif 60 | 61 | #if PROTOBUF_USE_EXCEPTIONS 62 | #include 63 | #endif 64 | #if defined(__APPLE__) 65 | #include // for TARGET_OS_IPHONE 66 | #endif 67 | 68 | #if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE) 69 | #include 70 | #endif 71 | 72 | #include 73 | 74 | namespace std {} 75 | 76 | namespace google { 77 | namespace protobuf { 78 | namespace internal { 79 | 80 | // Some of these constants are macros rather than const ints so that they can 81 | // be used in #if directives. 82 | 83 | // The current version, represented as a single integer to make comparison 84 | // easier: major * 10^6 + minor * 10^3 + micro 85 | #define GOOGLE_PROTOBUF_VERSION 3021012 86 | 87 | // A suffix string for alpha, beta or rc releases. Empty for stable releases. 88 | #define GOOGLE_PROTOBUF_VERSION_SUFFIX "" 89 | 90 | // The minimum header version which works with the current version of 91 | // the library. This constant should only be used by protoc's C++ code 92 | // generator. 93 | static const int kMinHeaderVersionForLibrary = 3021000; 94 | 95 | // The minimum protoc version which works with the current version of the 96 | // headers. 97 | #define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3021000 98 | 99 | // The minimum header version which works with the current version of 100 | // protoc. This constant should only be used in VerifyVersion(). 101 | static const int kMinHeaderVersionForProtoc = 3021000; 102 | 103 | // Verifies that the headers and libraries are compatible. Use the macro 104 | // below to call this. 105 | void PROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion, 106 | const char* filename); 107 | 108 | // Converts a numeric version number to a string. 109 | std::string PROTOBUF_EXPORT VersionString(int version); 110 | 111 | } // namespace internal 112 | 113 | // Place this macro in your main() function (or somewhere before you attempt 114 | // to use the protobuf library) to verify that the version you link against 115 | // matches the headers you compiled against. If a version mismatch is 116 | // detected, the process will abort. 117 | #define GOOGLE_PROTOBUF_VERIFY_VERSION \ 118 | ::google::protobuf::internal::VerifyVersion( \ 119 | GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \ 120 | __FILE__) 121 | 122 | 123 | // =================================================================== 124 | // from google3/util/utf8/public/unilib.h 125 | 126 | namespace internal { 127 | 128 | // Checks if the buffer contains structurally-valid UTF-8. Implemented in 129 | // structurally_valid.cc. 130 | PROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); 131 | 132 | inline bool IsStructurallyValidUTF8(StringPiece str) { 133 | return IsStructurallyValidUTF8(str.data(), static_cast(str.length())); 134 | } 135 | 136 | // Returns initial number of bytes of structurally valid UTF-8. 137 | PROTOBUF_EXPORT int UTF8SpnStructurallyValid(StringPiece str); 138 | 139 | // Coerce UTF-8 byte string in src_str to be 140 | // a structurally-valid equal-length string by selectively 141 | // overwriting illegal bytes with replace_char (typically ' ' or '?'). 142 | // replace_char must be legal printable 7-bit Ascii 0x20..0x7e. 143 | // src_str is read-only. 144 | // 145 | // Returns pointer to output buffer, src_str.data() if no changes were made, 146 | // or idst if some bytes were changed. idst is allocated by the caller 147 | // and must be at least as big as src_str 148 | // 149 | // Optimized for: all structurally valid and no byte copying is done. 150 | // 151 | PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(StringPiece str, char* dst, 152 | char replace_char); 153 | 154 | } // namespace internal 155 | 156 | // This lives in message_lite.h now, but we leave this here for any users that 157 | // #include common.h and not message_lite.h. 158 | PROTOBUF_EXPORT void ShutdownProtobufLibrary(); 159 | 160 | namespace internal { 161 | 162 | // Strongly references the given variable such that the linker will be forced 163 | // to pull in this variable's translation unit. 164 | template 165 | void StrongReference(const T& var) { 166 | auto volatile unused = &var; 167 | (void)&unused; // Use address to avoid an extra load of "unused". 168 | } 169 | 170 | } // namespace internal 171 | 172 | #if PROTOBUF_USE_EXCEPTIONS 173 | class FatalException : public std::exception { 174 | public: 175 | FatalException(const char* filename, int line, const std::string& message) 176 | : filename_(filename), line_(line), message_(message) {} 177 | virtual ~FatalException() throw(); 178 | 179 | const char* what() const throw() override; 180 | 181 | const char* filename() const { return filename_; } 182 | int line() const { return line_; } 183 | const std::string& message() const { return message_; } 184 | 185 | private: 186 | const char* filename_; 187 | const int line_; 188 | const std::string message_; 189 | }; 190 | #endif 191 | 192 | } // namespace protobuf 193 | } // namespace google 194 | 195 | #include 196 | 197 | #endif // GOOGLE_PROTOBUF_COMMON_H__ 198 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/hash.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | 33 | #ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__ 34 | #define GOOGLE_PROTOBUF_STUBS_HASH_H__ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \ 42 | namespace google { \ 43 | namespace protobuf { 44 | # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }} 45 | 46 | namespace google { 47 | namespace protobuf { 48 | 49 | template 50 | struct hash : public std::hash {}; 51 | 52 | template 53 | struct hash { 54 | inline size_t operator()(const Key* key) const { 55 | return reinterpret_cast(key); 56 | } 57 | }; 58 | 59 | // Unlike the old SGI version, the TR1 "hash" does not special-case char*. So, 60 | // we go ahead and provide our own implementation. 61 | template <> 62 | struct hash { 63 | inline size_t operator()(const char* str) const { 64 | size_t result = 0; 65 | for (; *str != '\0'; str++) { 66 | result = 5 * result + static_cast(*str); 67 | } 68 | return result; 69 | } 70 | }; 71 | 72 | template<> 73 | struct hash { 74 | size_t operator()(bool x) const { 75 | return static_cast(x); 76 | } 77 | }; 78 | 79 | template <> 80 | struct hash { 81 | inline size_t operator()(const std::string& key) const { 82 | return hash()(key.c_str()); 83 | } 84 | 85 | static const size_t bucket_size = 4; 86 | static const size_t min_buckets = 8; 87 | inline bool operator()(const std::string& a, const std::string& b) const { 88 | return a < b; 89 | } 90 | }; 91 | 92 | template 93 | struct hash > { 94 | inline size_t operator()(const std::pair& key) const { 95 | size_t first_hash = hash()(key.first); 96 | size_t second_hash = hash()(key.second); 97 | 98 | // FIXME(kenton): What is the best way to compute this hash? I have 99 | // no idea! This seems a bit better than an XOR. 100 | return first_hash * ((1 << 16) - 1) + second_hash; 101 | } 102 | 103 | static const size_t bucket_size = 4; 104 | static const size_t min_buckets = 8; 105 | inline bool operator()(const std::pair& a, 106 | const std::pair& b) const { 107 | return a < b; 108 | } 109 | }; 110 | 111 | } // namespace protobuf 112 | } // namespace google 113 | 114 | #endif // GOOGLE_PROTOBUF_STUBS_HASH_H__ 115 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/logging.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_ 32 | #define GOOGLE_PROTOBUF_STUBS_LOGGING_H_ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | // =================================================================== 42 | // emulates google3/base/logging.h 43 | 44 | namespace google { 45 | namespace protobuf { 46 | 47 | enum LogLevel { 48 | LOGLEVEL_INFO, // Informational. This is never actually used by 49 | // libprotobuf. 50 | LOGLEVEL_WARNING, // Warns about issues that, although not technically a 51 | // problem now, could cause problems in the future. For 52 | // example, a // warning will be printed when parsing a 53 | // message that is near the message size limit. 54 | LOGLEVEL_ERROR, // An error occurred which should never happen during 55 | // normal use. 56 | LOGLEVEL_FATAL, // An error occurred from which the library cannot 57 | // recover. This usually indicates a programming error 58 | // in the code which calls the library, especially when 59 | // compiled in debug mode. 60 | 61 | #ifdef NDEBUG 62 | LOGLEVEL_DFATAL = LOGLEVEL_ERROR 63 | #else 64 | LOGLEVEL_DFATAL = LOGLEVEL_FATAL 65 | #endif 66 | }; 67 | 68 | class uint128; 69 | namespace internal { 70 | 71 | class LogFinisher; 72 | 73 | class PROTOBUF_EXPORT LogMessage { 74 | public: 75 | LogMessage(LogLevel level, const char* filename, int line); 76 | ~LogMessage(); 77 | 78 | LogMessage& operator<<(const std::string& value); 79 | LogMessage& operator<<(const char* value); 80 | LogMessage& operator<<(char value); 81 | LogMessage& operator<<(int value); 82 | LogMessage& operator<<(uint value); 83 | LogMessage& operator<<(long value); 84 | LogMessage& operator<<(unsigned long value); 85 | LogMessage& operator<<(long long value); 86 | LogMessage& operator<<(unsigned long long value); 87 | LogMessage& operator<<(double value); 88 | LogMessage& operator<<(void* value); 89 | LogMessage& operator<<(const StringPiece& value); 90 | LogMessage& operator<<(const util::Status& status); 91 | LogMessage& operator<<(const uint128& value); 92 | 93 | private: 94 | friend class LogFinisher; 95 | void Finish(); 96 | 97 | LogLevel level_; 98 | const char* filename_; 99 | int line_; 100 | std::string message_; 101 | }; 102 | 103 | // Used to make the entire "LOG(BLAH) << etc." expression have a void return 104 | // type and print a newline after each message. 105 | class PROTOBUF_EXPORT LogFinisher { 106 | public: 107 | void operator=(LogMessage& other); 108 | }; 109 | 110 | template 111 | bool IsOk(T status) { return status.ok(); } 112 | template<> 113 | inline bool IsOk(bool status) { return status; } 114 | 115 | } // namespace internal 116 | 117 | // Undef everything in case we're being mixed with some other Google library 118 | // which already defined them itself. Presumably all Google libraries will 119 | // support the same syntax for these so it should not be a big deal if they 120 | // end up using our definitions instead. 121 | #undef GOOGLE_LOG 122 | #undef GOOGLE_LOG_IF 123 | 124 | #undef GOOGLE_CHECK 125 | #undef GOOGLE_CHECK_OK 126 | #undef GOOGLE_CHECK_EQ 127 | #undef GOOGLE_CHECK_NE 128 | #undef GOOGLE_CHECK_LT 129 | #undef GOOGLE_CHECK_LE 130 | #undef GOOGLE_CHECK_GT 131 | #undef GOOGLE_CHECK_GE 132 | #undef GOOGLE_CHECK_NOTNULL 133 | 134 | #undef GOOGLE_DLOG 135 | #undef GOOGLE_DCHECK 136 | #undef GOOGLE_DCHECK_OK 137 | #undef GOOGLE_DCHECK_EQ 138 | #undef GOOGLE_DCHECK_NE 139 | #undef GOOGLE_DCHECK_LT 140 | #undef GOOGLE_DCHECK_LE 141 | #undef GOOGLE_DCHECK_GT 142 | #undef GOOGLE_DCHECK_GE 143 | 144 | #define GOOGLE_LOG(LEVEL) \ 145 | ::google::protobuf::internal::LogFinisher() = \ 146 | ::google::protobuf::internal::LogMessage( \ 147 | ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) 148 | #define GOOGLE_LOG_IF(LEVEL, CONDITION) \ 149 | !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL) 150 | 151 | #define GOOGLE_CHECK(EXPRESSION) \ 152 | GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " 153 | #define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) 154 | #define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) 155 | #define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) 156 | #define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) 157 | #define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B)) 158 | #define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) 159 | #define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B)) 160 | 161 | namespace internal { 162 | template 163 | T* CheckNotNull(const char* /* file */, int /* line */, 164 | const char* name, T* val) { 165 | if (val == nullptr) { 166 | GOOGLE_LOG(FATAL) << name; 167 | } 168 | return val; 169 | } 170 | } // namespace internal 171 | #define GOOGLE_CHECK_NOTNULL(A) \ 172 | ::google::protobuf::internal::CheckNotNull( \ 173 | __FILE__, __LINE__, "'" #A "' must not be nullptr", (A)) 174 | 175 | #ifdef NDEBUG 176 | 177 | #define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false) 178 | 179 | #define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) 180 | #define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E)) 181 | #define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) 182 | #define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) 183 | #define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) 184 | #define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B)) 185 | #define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B)) 186 | #define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B)) 187 | 188 | #else // NDEBUG 189 | 190 | #define GOOGLE_DLOG GOOGLE_LOG 191 | 192 | #define GOOGLE_DCHECK GOOGLE_CHECK 193 | #define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK 194 | #define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ 195 | #define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE 196 | #define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT 197 | #define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE 198 | #define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT 199 | #define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE 200 | 201 | #endif // !NDEBUG 202 | 203 | typedef void LogHandler(LogLevel level, const char* filename, int line, 204 | const std::string& message); 205 | 206 | // The protobuf library sometimes writes warning and error messages to 207 | // stderr. These messages are primarily useful for developers, but may 208 | // also help end users figure out a problem. If you would prefer that 209 | // these messages be sent somewhere other than stderr, call SetLogHandler() 210 | // to set your own handler. This returns the old handler. Set the handler 211 | // to nullptr to ignore log messages (but see also LogSilencer, below). 212 | // 213 | // Obviously, SetLogHandler is not thread-safe. You should only call it 214 | // at initialization time, and probably not from library code. If you 215 | // simply want to suppress log messages temporarily (e.g. because you 216 | // have some code that tends to trigger them frequently and you know 217 | // the warnings are not important to you), use the LogSilencer class 218 | // below. 219 | PROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); 220 | 221 | // Create a LogSilencer if you want to temporarily suppress all log 222 | // messages. As long as any LogSilencer objects exist, non-fatal 223 | // log messages will be discarded (the current LogHandler will *not* 224 | // be called). Constructing a LogSilencer is thread-safe. You may 225 | // accidentally suppress log messages occurring in another thread, but 226 | // since messages are generally for debugging purposes only, this isn't 227 | // a big deal. If you want to intercept log messages, use SetLogHandler(). 228 | class PROTOBUF_EXPORT LogSilencer { 229 | public: 230 | LogSilencer(); 231 | ~LogSilencer(); 232 | }; 233 | 234 | } // namespace protobuf 235 | } // namespace google 236 | 237 | #include 238 | 239 | #endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_ 240 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/macros.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_MACROS_H__ 32 | #define GOOGLE_PROTOBUF_MACROS_H__ 33 | 34 | namespace google { 35 | namespace protobuf { 36 | 37 | #undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS 38 | #define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ 39 | TypeName(const TypeName&) = delete; \ 40 | void operator=(const TypeName&) = delete 41 | 42 | #undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS 43 | #define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ 44 | TypeName() = delete; \ 45 | TypeName(const TypeName&) = delete; \ 46 | void operator=(const TypeName&) = delete 47 | 48 | // =================================================================== 49 | // from google3/base/basictypes.h 50 | 51 | // The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr. 52 | // The expression is a compile-time constant, and therefore can be 53 | // used in defining new arrays, for example. 54 | // 55 | // GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error 56 | // 57 | // "warning: division by zero in ..." 58 | // 59 | // when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer. 60 | // You should only use GOOGLE_ARRAYSIZE on statically allocated arrays. 61 | // 62 | // The following comments are on the implementation details, and can 63 | // be ignored by the users. 64 | // 65 | // ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in 66 | // the array) and sizeof(*(arr)) (the # of bytes in one array 67 | // element). If the former is divisible by the latter, perhaps arr is 68 | // indeed an array, in which case the division result is the # of 69 | // elements in the array. Otherwise, arr cannot possibly be an array, 70 | // and we generate a compiler error to prevent the code from 71 | // compiling. 72 | // 73 | // Since the size of bool is implementation-defined, we need to cast 74 | // !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final 75 | // result has type size_t. 76 | // 77 | // This macro is not perfect as it wrongfully accepts certain 78 | // pointers, namely where the pointer size is divisible by the pointee 79 | // size. Since all our code has to go through a 32-bit compiler, 80 | // where a pointer is 4 bytes, this means all pointers to a type whose 81 | // size is 3 or greater than 4 will be (righteously) rejected. 82 | // 83 | // Kudos to Jorg Brown for this simple and elegant implementation. 84 | 85 | #undef GOOGLE_ARRAYSIZE 86 | #define GOOGLE_ARRAYSIZE(a) \ 87 | ((sizeof(a) / sizeof(*(a))) / \ 88 | static_cast(!(sizeof(a) % sizeof(*(a))))) 89 | 90 | } // namespace protobuf 91 | } // namespace google 92 | 93 | #endif // GOOGLE_PROTOBUF_MACROS_H__ 94 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/once.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__ 32 | #define GOOGLE_PROTOBUF_STUBS_ONCE_H__ 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | namespace google { 40 | namespace protobuf { 41 | namespace internal { 42 | 43 | using once_flag = std::once_flag; 44 | template 45 | void call_once(Args&&... args ) { 46 | std::call_once(std::forward(args)...); 47 | } 48 | 49 | } // namespace internal 50 | } // namespace protobuf 51 | } // namespace google 52 | 53 | #include 54 | 55 | #endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__ 56 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/platform_macros.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2012 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ 32 | #define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ 33 | 34 | #define GOOGLE_PROTOBUF_PLATFORM_ERROR \ 35 | #error "Host platform was not detected as supported by protobuf" 36 | 37 | // Processor architecture detection. For more info on what's defined, see: 38 | // http://msdn.microsoft.com/en-us/library/b0084kay.aspx 39 | // http://www.agner.org/optimize/calling_conventions.pdf 40 | // or with gcc, run: "echo | gcc -E -dM -" 41 | #if defined(_M_X64) || defined(__x86_64__) 42 | #define GOOGLE_PROTOBUF_ARCH_X64 1 43 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 44 | #elif defined(_M_IX86) || defined(__i386__) 45 | #define GOOGLE_PROTOBUF_ARCH_IA32 1 46 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 47 | #elif defined(__QNX__) 48 | #define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1 49 | #if defined(__aarch64__) 50 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 51 | #else 52 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 53 | #endif 54 | #elif defined(_M_ARM) || defined(__ARMEL__) 55 | #define GOOGLE_PROTOBUF_ARCH_ARM 1 56 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 57 | #elif defined(_M_ARM64) 58 | #define GOOGLE_PROTOBUF_ARCH_ARM 1 59 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 60 | #elif defined(__aarch64__) 61 | #define GOOGLE_PROTOBUF_ARCH_AARCH64 1 62 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 63 | #elif defined(__mips__) 64 | #if defined(__LP64__) 65 | #define GOOGLE_PROTOBUF_ARCH_MIPS64 1 66 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 67 | #else 68 | #define GOOGLE_PROTOBUF_ARCH_MIPS 1 69 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 70 | #endif 71 | #elif defined(__pnacl__) 72 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 73 | #elif defined(sparc) 74 | #define GOOGLE_PROTOBUF_ARCH_SPARC 1 75 | #if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__) 76 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 77 | #else 78 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 79 | #endif 80 | #elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__) 81 | #define GOOGLE_PROTOBUF_ARCH_POWER 1 82 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 83 | #elif defined(__PPC__) 84 | #define GOOGLE_PROTOBUF_ARCH_PPC 1 85 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 86 | #elif defined(__GNUC__) 87 | # if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) 88 | // We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h 89 | # elif defined(__clang__) 90 | # if !__has_extension(c_atomic) 91 | GOOGLE_PROTOBUF_PLATFORM_ERROR 92 | # endif 93 | // We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h 94 | # endif 95 | # if __LP64__ 96 | # define GOOGLE_PROTOBUF_ARCH_64_BIT 1 97 | # else 98 | # define GOOGLE_PROTOBUF_ARCH_32_BIT 1 99 | # endif 100 | #else 101 | GOOGLE_PROTOBUF_PLATFORM_ERROR 102 | #endif 103 | 104 | #if defined(__APPLE__) 105 | #define GOOGLE_PROTOBUF_OS_APPLE 106 | #include 107 | #include 108 | #if TARGET_OS_IPHONE 109 | #define GOOGLE_PROTOBUF_OS_IPHONE 110 | #endif 111 | #elif defined(__EMSCRIPTEN__) 112 | #define GOOGLE_PROTOBUF_OS_EMSCRIPTEN 113 | #elif defined(__native_client__) 114 | #define GOOGLE_PROTOBUF_OS_NACL 115 | #elif defined(sun) 116 | #define GOOGLE_PROTOBUF_OS_SOLARIS 117 | #elif defined(_AIX) 118 | #define GOOGLE_PROTOBUF_OS_AIX 119 | #elif defined(__ANDROID__) 120 | #define GOOGLE_PROTOBUF_OS_ANDROID 121 | #endif 122 | 123 | #undef GOOGLE_PROTOBUF_PLATFORM_ERROR 124 | 125 | #if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) 126 | // Android ndk does not support the __thread keyword very well yet. Here 127 | // we use pthread_key_create()/pthread_getspecific()/... methods for 128 | // TLS support on android. 129 | // iOS also does not support the __thread keyword. 130 | #define GOOGLE_PROTOBUF_NO_THREADLOCAL 131 | #endif 132 | 133 | #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070 134 | // __thread keyword requires at least 10.7 135 | #define GOOGLE_PROTOBUF_NO_THREADLOCAL 136 | #endif 137 | 138 | #endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ 139 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/status.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_ 32 | #define GOOGLE_PROTOBUF_STUBS_STATUS_H_ 33 | 34 | #include 35 | 36 | #include 37 | 38 | #include 39 | 40 | namespace google { 41 | namespace protobuf { 42 | namespace util { 43 | namespace status_internal { 44 | 45 | // These values must match error codes defined in google/rpc/code.proto. 46 | enum class StatusCode : int { 47 | kOk = 0, 48 | kCancelled = 1, 49 | kUnknown = 2, 50 | kInvalidArgument = 3, 51 | kDeadlineExceeded = 4, 52 | kNotFound = 5, 53 | kAlreadyExists = 6, 54 | kPermissionDenied = 7, 55 | kUnauthenticated = 16, 56 | kResourceExhausted = 8, 57 | kFailedPrecondition = 9, 58 | kAborted = 10, 59 | kOutOfRange = 11, 60 | kUnimplemented = 12, 61 | kInternal = 13, 62 | kUnavailable = 14, 63 | kDataLoss = 15, 64 | }; 65 | 66 | class PROTOBUF_EXPORT Status { 67 | public: 68 | // Creates a "successful" status. 69 | Status(); 70 | 71 | // Create a status in the canonical error space with the specified 72 | // code, and error message. If "code == 0", error_message is 73 | // ignored and a Status object identical to Status::kOk is 74 | // constructed. 75 | Status(StatusCode error_code, StringPiece error_message); 76 | Status(const Status&); 77 | Status& operator=(const Status& x); 78 | ~Status() {} 79 | 80 | // Accessor 81 | bool ok() const { return error_code_ == StatusCode::kOk; } 82 | StatusCode code() const { return error_code_; } 83 | StringPiece message() const { 84 | return error_message_; 85 | } 86 | 87 | bool operator==(const Status& x) const; 88 | bool operator!=(const Status& x) const { 89 | return !operator==(x); 90 | } 91 | 92 | // Return a combination of the error code name and message. 93 | std::string ToString() const; 94 | 95 | private: 96 | StatusCode error_code_; 97 | std::string error_message_; 98 | }; 99 | 100 | // Returns an OK status, equivalent to a default constructed instance. Prefer 101 | // usage of `OkStatus()` when constructing such an OK status. 102 | PROTOBUF_EXPORT Status OkStatus(); 103 | 104 | // Prints a human-readable representation of 'x' to 'os'. 105 | PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x); 106 | 107 | // These convenience functions return `true` if a given status matches the 108 | // `StatusCode` error code of its associated function. 109 | PROTOBUF_EXPORT bool IsAborted(const Status& status); 110 | PROTOBUF_EXPORT bool IsAlreadyExists(const Status& status); 111 | PROTOBUF_EXPORT bool IsCancelled(const Status& status); 112 | PROTOBUF_EXPORT bool IsDataLoss(const Status& status); 113 | PROTOBUF_EXPORT bool IsDeadlineExceeded(const Status& status); 114 | PROTOBUF_EXPORT bool IsFailedPrecondition(const Status& status); 115 | PROTOBUF_EXPORT bool IsInternal(const Status& status); 116 | PROTOBUF_EXPORT bool IsInvalidArgument(const Status& status); 117 | PROTOBUF_EXPORT bool IsNotFound(const Status& status); 118 | PROTOBUF_EXPORT bool IsOutOfRange(const Status& status); 119 | PROTOBUF_EXPORT bool IsPermissionDenied(const Status& status); 120 | PROTOBUF_EXPORT bool IsResourceExhausted(const Status& status); 121 | PROTOBUF_EXPORT bool IsUnauthenticated(const Status& status); 122 | PROTOBUF_EXPORT bool IsUnavailable(const Status& status); 123 | PROTOBUF_EXPORT bool IsUnimplemented(const Status& status); 124 | PROTOBUF_EXPORT bool IsUnknown(const Status& status); 125 | 126 | // These convenience functions create an `Status` object with an error code as 127 | // indicated by the associated function name, using the error message passed in 128 | // `message`. 129 | // 130 | // These functions are intentionally named `*Error` rather than `*Status` to 131 | // match the names from Abseil: 132 | // https://github.com/abseil/abseil-cpp/blob/2e9532cc6c701a8323d0cffb468999ab804095ab/absl/status/status.h#L716 133 | PROTOBUF_EXPORT Status AbortedError(StringPiece message); 134 | PROTOBUF_EXPORT Status AlreadyExistsError(StringPiece message); 135 | PROTOBUF_EXPORT Status CancelledError(StringPiece message); 136 | PROTOBUF_EXPORT Status DataLossError(StringPiece message); 137 | PROTOBUF_EXPORT Status DeadlineExceededError(StringPiece message); 138 | PROTOBUF_EXPORT Status FailedPreconditionError(StringPiece message); 139 | PROTOBUF_EXPORT Status InternalError(StringPiece message); 140 | PROTOBUF_EXPORT Status InvalidArgumentError(StringPiece message); 141 | PROTOBUF_EXPORT Status NotFoundError(StringPiece message); 142 | PROTOBUF_EXPORT Status OutOfRangeError(StringPiece message); 143 | PROTOBUF_EXPORT Status PermissionDeniedError(StringPiece message); 144 | PROTOBUF_EXPORT Status ResourceExhaustedError(StringPiece message); 145 | PROTOBUF_EXPORT Status UnauthenticatedError(StringPiece message); 146 | PROTOBUF_EXPORT Status UnavailableError(StringPiece message); 147 | PROTOBUF_EXPORT Status UnimplementedError(StringPiece message); 148 | PROTOBUF_EXPORT Status UnknownError(StringPiece message); 149 | 150 | } // namespace status_internal 151 | 152 | using ::google::protobuf::util::status_internal::Status; 153 | using ::google::protobuf::util::status_internal::StatusCode; 154 | 155 | using ::google::protobuf::util::status_internal::IsAborted; 156 | using ::google::protobuf::util::status_internal::IsAlreadyExists; 157 | using ::google::protobuf::util::status_internal::IsCancelled; 158 | using ::google::protobuf::util::status_internal::IsDataLoss; 159 | using ::google::protobuf::util::status_internal::IsDeadlineExceeded; 160 | using ::google::protobuf::util::status_internal::IsFailedPrecondition; 161 | using ::google::protobuf::util::status_internal::IsInternal; 162 | using ::google::protobuf::util::status_internal::IsInvalidArgument; 163 | using ::google::protobuf::util::status_internal::IsNotFound; 164 | using ::google::protobuf::util::status_internal::IsOutOfRange; 165 | using ::google::protobuf::util::status_internal::IsPermissionDenied; 166 | using ::google::protobuf::util::status_internal::IsResourceExhausted; 167 | using ::google::protobuf::util::status_internal::IsUnauthenticated; 168 | using ::google::protobuf::util::status_internal::IsUnavailable; 169 | using ::google::protobuf::util::status_internal::IsUnimplemented; 170 | using ::google::protobuf::util::status_internal::IsUnknown; 171 | 172 | using ::google::protobuf::util::status_internal::AbortedError; 173 | using ::google::protobuf::util::status_internal::AlreadyExistsError; 174 | using ::google::protobuf::util::status_internal::CancelledError; 175 | using ::google::protobuf::util::status_internal::DataLossError; 176 | using ::google::protobuf::util::status_internal::DeadlineExceededError; 177 | using ::google::protobuf::util::status_internal::FailedPreconditionError; 178 | using ::google::protobuf::util::status_internal::InternalError; 179 | using ::google::protobuf::util::status_internal::InvalidArgumentError; 180 | using ::google::protobuf::util::status_internal::NotFoundError; 181 | using ::google::protobuf::util::status_internal::OkStatus; 182 | using ::google::protobuf::util::status_internal::OutOfRangeError; 183 | using ::google::protobuf::util::status_internal::PermissionDeniedError; 184 | using ::google::protobuf::util::status_internal::ResourceExhaustedError; 185 | using ::google::protobuf::util::status_internal::UnauthenticatedError; 186 | using ::google::protobuf::util::status_internal::UnavailableError; 187 | using ::google::protobuf::util::status_internal::UnimplementedError; 188 | using ::google::protobuf::util::status_internal::UnknownError; 189 | 190 | } // namespace util 191 | } // namespace protobuf 192 | } // namespace google 193 | 194 | #include 195 | 196 | #endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ 197 | -------------------------------------------------------------------------------- /spt/google/protobuf/stubs/stl_util.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // from google3/util/gtl/stl_util.h 32 | 33 | #ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ 34 | #define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ 35 | 36 | #include 37 | 38 | #include 39 | 40 | // Must be last. 41 | #include // NOLINT 42 | 43 | namespace google { 44 | namespace protobuf { 45 | 46 | // Inside Google, this function implements a horrible, disgusting hack in which 47 | // we reach into the string's private implementation and resize it without 48 | // initializing the new bytes. In some cases doing this can significantly 49 | // improve performance. However, since it's totally non-portable it has no 50 | // place in open source code. Feel free to fill this function in with your 51 | // own disgusting hack if you want the perf boost. 52 | inline void STLStringResizeUninitialized(std::string* s, size_t new_size) { 53 | s->resize(new_size); 54 | } 55 | 56 | // As above, but we make sure to follow amortized growth in which we always 57 | // increase the capacity by at least a constant factor >1. 58 | inline void STLStringResizeUninitializedAmortized(std::string* s, 59 | size_t new_size) { 60 | const size_t cap = s->capacity(); 61 | if (new_size > cap) { 62 | // Make sure to always grow by at least a factor of 2x. 63 | s->reserve(std::max(new_size, 2 * cap)); 64 | } 65 | STLStringResizeUninitialized(s, new_size); 66 | } 67 | 68 | // Return a mutable char* pointing to a string's internal buffer, 69 | // which may not be null-terminated. Writing through this pointer will 70 | // modify the string. 71 | // 72 | // string_as_array(&str)[i] is valid for 0 <= i < str.size() until the 73 | // next call to a string method that invalidates iterators. 74 | // 75 | // As of 2006-04, there is no standard-blessed way of getting a 76 | // mutable reference to a string's internal buffer. However, issue 530 77 | // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) 78 | // proposes this as the method. According to Matt Austern, this should 79 | // already work on all current implementations. 80 | inline char* string_as_array(std::string* str) { 81 | // DO NOT USE const_cast(str->data())! See the unittest for why. 82 | return str->empty() ? nullptr : &*str->begin(); 83 | } 84 | 85 | } // namespace protobuf 86 | } // namespace google 87 | 88 | #include // NOLINT 89 | 90 | #endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ 91 | -------------------------------------------------------------------------------- /spt/google/protobuf/util/json_util.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Utility functions to convert between protobuf binary format and proto3 JSON 32 | // format. 33 | #ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ 34 | #define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | // Must be included last. 43 | #include 44 | 45 | namespace google { 46 | namespace protobuf { 47 | namespace io { 48 | class ZeroCopyInputStream; 49 | class ZeroCopyOutputStream; 50 | } // namespace io 51 | namespace util { 52 | 53 | struct JsonParseOptions { 54 | // Whether to ignore unknown JSON fields during parsing 55 | bool ignore_unknown_fields; 56 | 57 | // If true, when a lowercase enum value fails to parse, try convert it to 58 | // UPPER_CASE and see if it matches a valid enum. 59 | // WARNING: This option exists only to preserve legacy behavior. Avoid using 60 | // this option. If your enum needs to support different casing, consider using 61 | // allow_alias instead. 62 | bool case_insensitive_enum_parsing; 63 | 64 | JsonParseOptions() 65 | : ignore_unknown_fields(false), case_insensitive_enum_parsing(false) {} 66 | }; 67 | 68 | struct JsonPrintOptions { 69 | // Whether to add spaces, line breaks and indentation to make the JSON output 70 | // easy to read. 71 | bool add_whitespace; 72 | // Whether to always print primitive fields. By default proto3 primitive 73 | // fields with default values will be omitted in JSON output. For example, an 74 | // int32 field set to 0 will be omitted. Set this flag to true will override 75 | // the default behavior and print primitive fields regardless of their values. 76 | bool always_print_primitive_fields; 77 | // Whether to always print enums as ints. By default they are rendered as 78 | // strings. 79 | bool always_print_enums_as_ints; 80 | // Whether to preserve proto field names 81 | bool preserve_proto_field_names; 82 | 83 | JsonPrintOptions() 84 | : add_whitespace(false), 85 | always_print_primitive_fields(false), 86 | always_print_enums_as_ints(false), 87 | preserve_proto_field_names(false) {} 88 | }; 89 | 90 | // DEPRECATED. Use JsonPrintOptions instead. 91 | typedef JsonPrintOptions JsonOptions; 92 | 93 | // Converts from protobuf message to JSON and appends it to |output|. This is a 94 | // simple wrapper of BinaryToJsonString(). It will use the DescriptorPool of the 95 | // passed-in message to resolve Any types. 96 | PROTOBUF_EXPORT util::Status MessageToJsonString(const Message& message, 97 | std::string* output, 98 | const JsonOptions& options); 99 | 100 | inline util::Status MessageToJsonString(const Message& message, 101 | std::string* output) { 102 | return MessageToJsonString(message, output, JsonOptions()); 103 | } 104 | 105 | // Converts from JSON to protobuf message. This is a simple wrapper of 106 | // JsonStringToBinary(). It will use the DescriptorPool of the passed-in 107 | // message to resolve Any types. 108 | PROTOBUF_EXPORT util::Status JsonStringToMessage( 109 | StringPiece input, Message* message, const JsonParseOptions& options); 110 | 111 | inline util::Status JsonStringToMessage(StringPiece input, 112 | Message* message) { 113 | return JsonStringToMessage(input, message, JsonParseOptions()); 114 | } 115 | 116 | // Converts protobuf binary data to JSON. 117 | // The conversion will fail if: 118 | // 1. TypeResolver fails to resolve a type. 119 | // 2. input is not valid protobuf wire format, or conflicts with the type 120 | // information returned by TypeResolver. 121 | // Note that unknown fields will be discarded silently. 122 | PROTOBUF_EXPORT util::Status BinaryToJsonStream( 123 | TypeResolver* resolver, const std::string& type_url, 124 | io::ZeroCopyInputStream* binary_input, 125 | io::ZeroCopyOutputStream* json_output, const JsonPrintOptions& options); 126 | 127 | inline util::Status BinaryToJsonStream(TypeResolver* resolver, 128 | const std::string& type_url, 129 | io::ZeroCopyInputStream* binary_input, 130 | io::ZeroCopyOutputStream* json_output) { 131 | return BinaryToJsonStream(resolver, type_url, binary_input, json_output, 132 | JsonPrintOptions()); 133 | } 134 | 135 | PROTOBUF_EXPORT util::Status BinaryToJsonString( 136 | TypeResolver* resolver, const std::string& type_url, 137 | const std::string& binary_input, std::string* json_output, 138 | const JsonPrintOptions& options); 139 | 140 | inline util::Status BinaryToJsonString(TypeResolver* resolver, 141 | const std::string& type_url, 142 | const std::string& binary_input, 143 | std::string* json_output) { 144 | return BinaryToJsonString(resolver, type_url, binary_input, json_output, 145 | JsonPrintOptions()); 146 | } 147 | 148 | // Converts JSON data to protobuf binary format. 149 | // The conversion will fail if: 150 | // 1. TypeResolver fails to resolve a type. 151 | // 2. input is not valid JSON format, or conflicts with the type 152 | // information returned by TypeResolver. 153 | PROTOBUF_EXPORT util::Status JsonToBinaryStream( 154 | TypeResolver* resolver, const std::string& type_url, 155 | io::ZeroCopyInputStream* json_input, 156 | io::ZeroCopyOutputStream* binary_output, const JsonParseOptions& options); 157 | 158 | inline util::Status JsonToBinaryStream( 159 | TypeResolver* resolver, const std::string& type_url, 160 | io::ZeroCopyInputStream* json_input, 161 | io::ZeroCopyOutputStream* binary_output) { 162 | return JsonToBinaryStream(resolver, type_url, json_input, binary_output, 163 | JsonParseOptions()); 164 | } 165 | 166 | PROTOBUF_EXPORT util::Status JsonToBinaryString( 167 | TypeResolver* resolver, const std::string& type_url, 168 | StringPiece json_input, std::string* binary_output, 169 | const JsonParseOptions& options); 170 | 171 | inline util::Status JsonToBinaryString(TypeResolver* resolver, 172 | const std::string& type_url, 173 | StringPiece json_input, 174 | std::string* binary_output) { 175 | return JsonToBinaryString(resolver, type_url, json_input, binary_output, 176 | JsonParseOptions()); 177 | } 178 | 179 | namespace internal { 180 | // Internal helper class. Put in the header so we can write unit-tests for it. 181 | class PROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink { 182 | public: 183 | explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream) 184 | : stream_(stream), buffer_(nullptr), buffer_size_(0) {} 185 | ~ZeroCopyStreamByteSink() override; 186 | 187 | void Append(const char* bytes, size_t len) override; 188 | 189 | private: 190 | io::ZeroCopyOutputStream* stream_; 191 | void* buffer_; 192 | int buffer_size_; 193 | 194 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink); 195 | }; 196 | } // namespace internal 197 | 198 | } // namespace util 199 | } // namespace protobuf 200 | } // namespace google 201 | 202 | #include 203 | 204 | #endif // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ 205 | -------------------------------------------------------------------------------- /spt/protoc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/spt/protoc.exe -------------------------------------------------------------------------------- /spt/x64/libprotobuf-lite.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/spt/x64/libprotobuf-lite.lib -------------------------------------------------------------------------------- /spt/x64/libprotobuf-lited.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/spt/x64/libprotobuf-lited.lib -------------------------------------------------------------------------------- /spt/x64/mmmojo_64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/spt/x64/mmmojo_64.lib -------------------------------------------------------------------------------- /spt/x86/libprotobuf-lite.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/spt/x86/libprotobuf-lite.lib -------------------------------------------------------------------------------- /spt/x86/libprotobuf-lited.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/spt/x86/libprotobuf-lited.lib -------------------------------------------------------------------------------- /spt/x86/mmmojo.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swigger/wechat-ocr/81e6e75dda85e99754c90a8254f0fc16a52eb3b9/spt/x86/mmmojo.lib -------------------------------------------------------------------------------- /src/api.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "wechatocr.h" 3 | #include 4 | 5 | static string json_encode(const string& input) { 6 | string output; 7 | output.reserve(input.size() + 2); 8 | for (auto c : input) { 9 | switch (c) { 10 | case '"': output += "\\\""; break; 11 | case '\\': output += "\\\\"; break; 12 | case '\n': output += "\\n"; break; 13 | case '\r': output += "\\r"; break; 14 | case '\t': output += "\\t"; break; 15 | default: 16 | if (c>=0 && c < 0x20) { 17 | char buf[16]; 18 | snprintf(buf, sizeof(buf), "\\u%04x", c); 19 | output += buf; 20 | } else { 21 | output.push_back(c); 22 | } 23 | } 24 | } 25 | return output; 26 | } 27 | 28 | static std::unique_ptr g_instance; 29 | 30 | extern "C" EXPORTED_API 31 | bool wechat_ocr(LPCTSTR ocr_exe, LPCTSTR wechat_dir, const char * imgfn, void(*set_res)(const char * dt)) 32 | { 33 | if (!g_instance) { 34 | auto ocr = std::make_unique(ocr_exe, wechat_dir); 35 | if (!ocr->wait_connection(5000)) { 36 | return false; 37 | } 38 | g_instance = std::move(ocr); 39 | } 40 | 41 | CWeChatOCR::result_t res; 42 | if (!g_instance->doOCR(imgfn, &res)) 43 | return false; 44 | string json; 45 | json += "{"; 46 | json += "\"errcode\":" + std::to_string(res.errcode) + ","; 47 | json += "\"imgpath\":\"" + json_encode(res.imgpath) + "\","; 48 | json += "\"width\":" + std::to_string(res.width) + ","; 49 | json += "\"height\":" + std::to_string(res.height) + ","; 50 | json += "\"ocr_response\":["; 51 | for (auto& blk : res.ocr_response) { 52 | json += "{"; 53 | json += "\"left\":" + std::to_string(blk.left) + ","; 54 | json += "\"top\":" + std::to_string(blk.top) + ","; 55 | json += "\"right\":" + std::to_string(blk.right) + ","; 56 | json += "\"bottom\":" + std::to_string(blk.bottom) + ","; 57 | json += "\"rate\":" + std::to_string(blk.rate) + ","; 58 | json += "\"text\":\"" + json_encode(blk.text) + "\""; 59 | json += "},"; 60 | } 61 | if (json.back() == ',') { 62 | json.pop_back(); 63 | } 64 | json += "]}"; 65 | if (set_res) { 66 | set_res(json.c_str()); 67 | } 68 | return true; 69 | } 70 | 71 | extern "C" EXPORTED_API 72 | void stop_ocr() { 73 | g_instance.reset(); 74 | } 75 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "wechatocr.h" 3 | #include 4 | 5 | #if defined(TEST_CLI) 6 | class CGotOCR : public CWeChatOCR 7 | { 8 | public: 9 | CGotOCR(LPCTSTR exe, LPCTSTR wcdir) 10 | : CWeChatOCR(exe, wcdir) 11 | {} 12 | void OnOCRResult(result_t& ocr_response) override 13 | { 14 | printf("OCR errcode=%d\n", ocr_response.errcode); 15 | for (auto& text : ocr_response.ocr_response) { 16 | printf("[%.2f,%.2f,%.2f,%.2f] r=%.3f %s\n", text.left, text.top, text.right, text.bottom, 17 | text.rate, text.text.c_str()); 18 | } 19 | } 20 | }; 21 | 22 | int main(int argc, char* argv[]) 23 | { 24 | #ifdef _WIN32 25 | SetConsoleCP(CP_UTF8); 26 | SetConsoleOutputCP(CP_UTF8); 27 | setlocale(LC_ALL, "en_US.UTF-8"); 28 | #endif 29 | if (argc != 4) { 30 | fprintf(stderr, "Usage: %s \n", argv[0]); 31 | return -1; 32 | } 33 | 34 | string msg; 35 | CGotOCR ocr(util::to_tstr(argv[1]).c_str(), util::to_tstr(argv[2]).c_str()); 36 | if (!ocr.wait_connection(5000)) { 37 | fprintf(stderr, "wechat_ocr.wait_connection failed\n"); 38 | return -1; 39 | } 40 | ocr.doOCR(argv[3], nullptr); 41 | ocr.wait_done(-1); 42 | fprintf(stderr, "debug play ocr DONE!\n"); 43 | return 0; 44 | } 45 | #elif defined(_WIN32) 46 | int APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 47 | { 48 | switch (ul_reason_for_call) 49 | { 50 | case DLL_PROCESS_ATTACH: 51 | case DLL_THREAD_ATTACH: 52 | case DLL_THREAD_DETACH: 53 | case DLL_PROCESS_DETACH: 54 | break; 55 | } 56 | return TRUE; 57 | } 58 | 59 | # ifdef _DEBUG 60 | // 定义这个函数仅方便使用regsvr32.exe调试本DLL, 使用环境变量WECHATOCR_EXE和WECHAT_DIR以及TEST_PNG传入调试参数 61 | extern "C" __declspec(dllexport) 62 | HRESULT DllRegisterServer(void) 63 | { 64 | if (AllocConsole()) { 65 | (void)freopen("CONOUT$", "w", stdout); 66 | (void)freopen("CONOUT$", "w", stderr); 67 | // disalbe stdout cache. 68 | setvbuf(stdout, NULL, _IONBF, 0); 69 | SetConsoleCP(CP_UTF8); 70 | SetConsoleOutputCP(CP_UTF8); 71 | } 72 | 73 | // printf("Protobuf version: %u\n", GOOGLE_PROTOBUF_VERSION); 74 | // printf("tencent protobuf version string: %s\n", google::protobuf::internal::VersionString(2005000).c_str()); 75 | string msg; 76 | 77 | CWeChatOCR wechat_ocr(_wgetenv(L"WECHATOCR_EXE"), _wgetenv(L"WECHAT_DIR")); 78 | if (!wechat_ocr.wait_connection(5000)) { 79 | fprintf(stderr, "wechat_ocr.wait_connection failed\n"); 80 | return E_FAIL; 81 | } 82 | wechat_ocr.doOCR(getenv("TEST_PNG"), nullptr); 83 | wechat_ocr.wait_done(-1); 84 | fprintf(stderr, "debug play ocr DONE!\n"); 85 | return S_OK; 86 | } 87 | # endif 88 | #endif 89 | -------------------------------------------------------------------------------- /src/mmmojo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // method interface 4 | typedef enum { 5 | kMMNone = 0, 6 | kMMPush, 7 | kMMPullReq, 8 | kMMPullResp, 9 | kMMShared, 10 | } MMMojoInfoMethod; 11 | 12 | // env interface 13 | typedef enum { 14 | kMMUserData = 0, 15 | kMMReadPush, 16 | kMMReadPull, 17 | kMMReadShared, 18 | kMMRemoteConnect, 19 | kMMRemoteDisconnect, 20 | kMMRemoteProcessLaunched, 21 | kMMRemoteProcessLaunchFailed, 22 | kMMRemoteMojoError, 23 | } MMMojoEnvironmentCallbackType; 24 | 25 | typedef enum { 26 | kMMHostProcess = 0, 27 | kMMLoopStartThread, 28 | kMMExePath, 29 | kMMLogPath, 30 | kMMLogToStderr, 31 | kMMAddNumMessagepipe, 32 | kMMSetDisconnectHandlers, 33 | #if defined(WIN32) 34 | kMMDisableDefaultPolicy = 1000, 35 | kMMElevated, 36 | kMMCompatible, 37 | #endif // defined(WIN32) 38 | } MMMojoEnvironmentInitParamType; 39 | -------------------------------------------------------------------------------- /src/mmmojo_funcs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef MMMOJO_EXPORT 4 | # ifdef _WIN32 5 | # define MMMOJO_EXPORT __declspec(dllimport) 6 | # else 7 | # define MMMOJO_EXPORT 8 | # endif 9 | #endif 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | // read interface 16 | MMMOJO_EXPORT const void* GetMMMojoReadInfoRequest(const void* mmmojo_readinfo, uint32_t* request_data_size); 17 | MMMOJO_EXPORT const void* GetMMMojoReadInfoAttach(const void* mmmojo_readinfo, uint32_t* attach_data_size); 18 | MMMOJO_EXPORT int GetMMMojoReadInfoMethod(const void* mmmojo_readinfo); 19 | MMMOJO_EXPORT bool GetMMMojoReadInfoSync(const void* mmmojo_readinfo); 20 | MMMOJO_EXPORT void RemoveMMMojoReadInfo(const void* mmmojo_readinfo); 21 | 22 | // write interface 23 | // 24 | // MMMojoInfoMethod::kMMPush & kMMPullReq & kMMPullResp 25 | // using default max num bytes 26 | // mojo/core/embedder/configuration.h 27 | // Maximum data size of messages sent over message pipes, in bytes. 28 | // size_t max_message_num_bytes = 256 * 1024 * 1024; 29 | // 30 | // MMMojoInfoMethod:kMMShared 31 | // Maximum size of a single shared memory segment, in bytes. 32 | // size_t max_shared_memory_num_bytes = 1024 * 1024 * 1024; 33 | MMMOJO_EXPORT void* CreateMMMojoWriteInfo(int method, bool sync, uint32_t request_id); 34 | MMMOJO_EXPORT void SetMMMojoWriteInfoMessagePipe(void* mmmojo_writeinfo, int num_of_message_pipe); 35 | MMMOJO_EXPORT void SetMMMojoWriteInfoResponseSync(void* mmmojo_writeinfo, void** mmmojo_readinfo); 36 | MMMOJO_EXPORT void* GetMMMojoWriteInfoRequest(void* mmmojo_writeinfo, size_t request_data_size); 37 | MMMOJO_EXPORT void* GetMMMojoWriteInfoAttach(void* mmmojo_writeinfo, size_t attach_data_size); 38 | MMMOJO_EXPORT bool SwapMMMojoWriteInfoCallback(void* mmmojo_writeinfo, void* mmmojo_readinfo); 39 | MMMOJO_EXPORT bool SwapMMMojoWriteInfoMessage(void* mmmojo_writeinfo, void* mmmojo_readinfo); 40 | MMMOJO_EXPORT bool SendMMMojoWriteInfo(void* mmmojo_env, void* mmmojo_writeinfo); 41 | MMMOJO_EXPORT void RemoveMMMojoWriteInfo(void* mmmojo_writeinfo); 42 | 43 | MMMOJO_EXPORT void* CreateMMMojoEnvironment(); 44 | MMMOJO_EXPORT void SetMMMojoEnvironmentCallbacks(void* mmmojo_env, int type, ...); 45 | MMMOJO_EXPORT void SetMMMojoEnvironmentInitParams(void* mmmojo_env, int type, ...); 46 | #if defined(WIN32) 47 | MMMOJO_EXPORT void AppendMMSubProcessSwitchNative(void* mmmojo_env, const char* switch_string, const wchar_t* value); 48 | #else 49 | MMMOJO_EXPORT void AppendMMSubProcessSwitchNative(void* mmmojo_env, const char* switch_string, const char* value); 50 | #endif // defined(WIN32) 51 | MMMOJO_EXPORT void StartMMMojoEnvironment(void* mmmojo_env); 52 | MMMOJO_EXPORT void StopMMMojoEnvironment(void* mmmojo_env); 53 | MMMOJO_EXPORT void RemoveMMMojoEnvironment(void* mmmojo_env); 54 | 55 | // global interface 56 | MMMOJO_EXPORT void InitializeMMMojo(int argc, const char* const* argv); 57 | MMMOJO_EXPORT void ShutdownMMMojo(); 58 | 59 | #ifdef __cplusplus 60 | } // extern "C" 61 | #endif 62 | -------------------------------------------------------------------------------- /src/mojocall.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include "mmmojo_funcs.h" 4 | #include "mojocall.h" 5 | #ifndef _WIN32 6 | # include 7 | #endif 8 | 9 | #ifdef _DEBUG 10 | # define DBG_PRINT(fmt, ...) fprintf(stderr, "[DEBUG]" fmt, __VA_ARGS__) 11 | #else 12 | # define DBG_PRINT(fmt, ...) 13 | #endif 14 | 15 | namespace midlevel 16 | { 17 | #define LAZY_FUNCTION(x) decltype(&::x) x = nullptr 18 | LAZY_FUNCTION(CreateMMMojoEnvironment); 19 | LAZY_FUNCTION(AppendMMSubProcessSwitchNative); 20 | LAZY_FUNCTION(CreateMMMojoWriteInfo); 21 | LAZY_FUNCTION(GetMMMojoReadInfoRequest); 22 | LAZY_FUNCTION(GetMMMojoWriteInfoRequest); 23 | LAZY_FUNCTION(RemoveMMMojoEnvironment); 24 | LAZY_FUNCTION(RemoveMMMojoReadInfo); 25 | LAZY_FUNCTION(RemoveMMMojoWriteInfo); 26 | LAZY_FUNCTION(SendMMMojoWriteInfo); 27 | LAZY_FUNCTION(SetMMMojoEnvironmentCallbacks); 28 | LAZY_FUNCTION(SetMMMojoEnvironmentInitParams); 29 | LAZY_FUNCTION(StartMMMojoEnvironment); 30 | LAZY_FUNCTION(StopMMMojoEnvironment); 31 | LAZY_FUNCTION(InitializeMMMojo); 32 | 33 | template 34 | bool init_func(HMODULE mod, T*& func, const char* name) 35 | { 36 | #ifdef _WIN32 37 | func = (T*)GetProcAddress(mod, name); 38 | #else 39 | func = (T*)dlsym(mod, name); 40 | #endif 41 | return !!func; 42 | } 43 | 44 | static int init_funcs(HMODULE mod) 45 | { 46 | int failcnt = 0; 47 | #define INIT_LAZY_FUNCTION(x) failcnt += init_func(mod, x, #x) ? 0 : 1; 48 | INIT_LAZY_FUNCTION(CreateMMMojoEnvironment); 49 | INIT_LAZY_FUNCTION(AppendMMSubProcessSwitchNative); 50 | INIT_LAZY_FUNCTION(CreateMMMojoWriteInfo); 51 | INIT_LAZY_FUNCTION(GetMMMojoReadInfoRequest); 52 | INIT_LAZY_FUNCTION(GetMMMojoWriteInfoRequest); 53 | INIT_LAZY_FUNCTION(RemoveMMMojoEnvironment); 54 | INIT_LAZY_FUNCTION(RemoveMMMojoReadInfo); 55 | INIT_LAZY_FUNCTION(RemoveMMMojoWriteInfo); 56 | INIT_LAZY_FUNCTION(SendMMMojoWriteInfo); 57 | INIT_LAZY_FUNCTION(SetMMMojoEnvironmentCallbacks); 58 | INIT_LAZY_FUNCTION(SetMMMojoEnvironmentInitParams); 59 | INIT_LAZY_FUNCTION(StartMMMojoEnvironment); 60 | INIT_LAZY_FUNCTION(StopMMMojoEnvironment); 61 | INIT_LAZY_FUNCTION(InitializeMMMojo); 62 | return failcnt; 63 | } 64 | 65 | class CMojoCall_Mid : public CMojoCall 66 | { 67 | public: 68 | bool Init(LPCTSTR wcdir) 69 | { 70 | #ifdef _WIN32 71 | if (!m_mod) { 72 | // find mmmojo(_64).dll 73 | std::wstring mojo_dll = wcdir; 74 | if (mojo_dll.empty()) return false; 75 | if (mojo_dll.back() != L'\\') mojo_dll += L'\\'; 76 | size_t osz = mojo_dll.size(); 77 | # ifdef _WIN64 78 | mojo_dll += L"mmmojo_64.dll"; 79 | # else 80 | mojo_dll += L"mmmojo.dll"; 81 | # endif 82 | auto mod = GetModuleHandleW(mojo_dll.c_str() + osz); 83 | if (!mod) { 84 | mod = LoadLibraryW(mojo_dll.c_str()); 85 | if (mod == NULL) return false; 86 | m_should_free_mod = true; 87 | } 88 | if (init_funcs(mod)) { 89 | if (m_should_free_mod) FreeLibrary(mod); 90 | m_should_free_mod = false; 91 | return false; 92 | } 93 | m_mod = mod; 94 | } 95 | #else 96 | string folder = wcdir; 97 | if (!folder.empty() && folder.back() != '/') folder += '/'; 98 | folder += "libmmmojo.so"; 99 | void* mod = dlopen(folder.c_str(), RTLD_LAZY); 100 | if (!mod) { 101 | fprintf(stderr, "dlopen failed: %s\n", dlerror()); 102 | return false; 103 | } 104 | if (init_funcs(mod)) { 105 | dlclose(mod); 106 | return false; 107 | } 108 | m_should_free_mod = true; 109 | m_mod = mod; 110 | #endif 111 | InitializeMMMojo(0, 0); 112 | return true; 113 | } 114 | 115 | bool Start(LPCTSTR exepath) 116 | { 117 | if (!m_env) { 118 | // 创建MMMojo环境 119 | auto env = CreateMMMojoEnvironment(); 120 | if (!env) return false; 121 | 122 | #define self ((CMojoCall_Mid*)user_data) 123 | // 设置回调函数 124 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMUserData, this); 125 | auto ReadOnPush = +[](uint32_t request_id, const void* request_info, void* user_data) { 126 | DBG_PRINT("ReadOnPush: %u\n", request_id); 127 | uint32_t pb_size = 0; 128 | const void* pb_data = GetMMMojoReadInfoRequest(request_info, &pb_size); 129 | self->ReadOnPush(request_id, std::span((std::byte*)pb_data, pb_size)); 130 | RemoveMMMojoReadInfo(request_info); 131 | }; 132 | auto ReadOnPull = +[](uint32_t request_id, const void* request_info, void* user_data) { 133 | DBG_PRINT("ReadOnPull: %u\n", request_id); 134 | uint32_t pb_size = 0; 135 | const void* pb_data = GetMMMojoReadInfoRequest(request_info, &pb_size); 136 | self->ReadOnPull(request_id, std::span((std::byte*)pb_data, pb_size)); 137 | RemoveMMMojoReadInfo(request_info); 138 | }; 139 | auto ReadOnShared = +[](uint32_t request_id, const void* request_info, void* user_data) { 140 | DBG_PRINT("ReadOnShared: %u\n", request_id); 141 | uint32_t pb_size = 0; 142 | const void* pb_data = GetMMMojoReadInfoRequest(request_info, &pb_size); 143 | return self->ReadOnShared(request_id, std::span((std::byte*)pb_data, pb_size)); 144 | RemoveMMMojoReadInfo(request_info); 145 | }; 146 | auto OnConnect = +[](bool is_connected, void* user_data) { 147 | DBG_PRINT("OnConnect: %d\n", is_connected); 148 | return self->OnRemoteConnect(is_connected); 149 | }; 150 | auto OnDisConnect = +[](void* user_data) { 151 | DBG_PRINT("OnDisConnect\n"); 152 | return self->OnRemoteDisConnect(); 153 | }; 154 | auto OnProcessLaunched = +[](void* user_data) { 155 | DBG_PRINT("OnProcessLaunched\n"); 156 | return self->OnRemoteProcessLaunched(); 157 | }; 158 | auto OnProcessLaunchFailed = +[](int error_code, void* user_data) { 159 | DBG_PRINT("OnProcessLaunchFailed: %d\n", error_code); 160 | return self->OnRemoteProcessLaunchFailed(error_code); 161 | }; 162 | auto OnError = +[](const void* errorbuf, int errorsize, void* user_data) { 163 | DBG_PRINT("OnError: %.*s\n", errorsize, (const char*)errorbuf); 164 | return self->OnRemoteError(errorbuf, errorsize); 165 | }; 166 | 167 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMReadPush, ReadOnPush); 168 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMReadPull, ReadOnPull); 169 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMReadShared, ReadOnShared); 170 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMRemoteConnect, OnConnect); 171 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMRemoteDisconnect, OnDisConnect); 172 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMRemoteProcessLaunched, OnProcessLaunched); 173 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMRemoteProcessLaunchFailed, OnProcessLaunchFailed); 174 | SetMMMojoEnvironmentCallbacks(env, MMMojoEnvironmentCallbackType::kMMRemoteMojoError, OnError); 175 | m_env = env; 176 | } 177 | 178 | // 设置启动所需参数 179 | SetMMMojoEnvironmentInitParams(m_env, MMMojoEnvironmentInitParamType::kMMHostProcess, true); 180 | SetMMMojoEnvironmentInitParams(m_env, MMMojoEnvironmentInitParamType::kMMExePath, exepath); 181 | 182 | // 设置SwitchNative命令行参数 183 | for (const auto& [k, v] : m_args) { 184 | AppendMMSubProcessSwitchNative(m_env, k.c_str(), v.c_str()); 185 | } 186 | StartMMMojoEnvironment(m_env); 187 | return true; 188 | } 189 | 190 | void Stop() 191 | { 192 | if (m_env) { 193 | StopMMMojoEnvironment(m_env); 194 | RemoveMMMojoEnvironment(m_env); 195 | m_env = 0; 196 | } 197 | } 198 | 199 | bool SendPbSerializedData(const void* pb_data, size_t data_size, int method, bool sync, uint32_t request_id) 200 | { 201 | if (data_size < 0) return false; 202 | 203 | void* write_info = CreateMMMojoWriteInfo(method, sync, request_id); 204 | if (data_size != 0) { 205 | void* request = GetMMMojoWriteInfoRequest(write_info, data_size); 206 | // TODO: 这里是否有内存泄漏? request,write_info指针会释放吗? 207 | memcpy(request, pb_data, data_size); // 写入protobuf数据 208 | return SendMMMojoWriteInfo(m_env, write_info); 209 | } 210 | RemoveMMMojoWriteInfo(write_info); 211 | return false; 212 | } 213 | }; 214 | } // namespace midlevel 215 | 216 | CMojoCall::CMojoCall() 217 | { 218 | } 219 | 220 | CMojoCall::~CMojoCall() 221 | { 222 | Stop(); 223 | if (m_mod && m_should_free_mod) { 224 | /* I really want to release the module here, unfortunately stopping mmmojo env does not stop the threads it created, 225 | so free the module here will inevitably cause a crash. So I can only ignore it. 226 | If you want to load different mmmojo modules, you may have to find another way. . . 227 | */ 228 | #ifdef _WIN32 229 | // FreeLibrary(m_mod); 230 | #else 231 | // dlclose(m_mod); 232 | #endif 233 | } 234 | m_mod = 0; 235 | m_should_free_mod = false; 236 | } 237 | 238 | bool CMojoCall::Init(LPCTSTR wcdir) 239 | { 240 | return ((midlevel::CMojoCall_Mid*)this)->Init(wcdir); 241 | } 242 | 243 | bool CMojoCall::Start(LPCTSTR exepath) 244 | { 245 | return ((midlevel::CMojoCall_Mid*)this)->Start(exepath); 246 | } 247 | 248 | void CMojoCall::Stop() 249 | { 250 | ((midlevel::CMojoCall_Mid*)this)->Stop(); 251 | } 252 | 253 | bool CMojoCall::SendPbSerializedData(const void* pb_data, size_t data_size, int method, bool sync, uint32_t request_id) 254 | { 255 | return ((midlevel::CMojoCall_Mid*)this)->SendPbSerializedData(pb_data, data_size, method, sync, request_id); 256 | } 257 | 258 | void CMojoCall::OnRemoteConnect(bool is_connected) 259 | { 260 | std::lock_guard lock(m_mutex_state); 261 | m_state = is_connected ? MJC_CONNECTED : MJC_FAILED; 262 | m_cv_state.notify_all(); 263 | } 264 | 265 | void CMojoCall::OnRemoteDisConnect() 266 | { 267 | std::lock_guard lock(m_mutex_state); 268 | m_state = MJC_FAILED; 269 | m_cv_state.notify_all(); 270 | } 271 | 272 | bool CMojoCall::wait_connection(int timeout) 273 | { 274 | if (timeout < 0) { 275 | std::unique_lock lock(m_mutex_state); 276 | m_cv_state.wait(lock, [this] { return m_state != MJC_PENDING; }); 277 | } else { 278 | std::unique_lock lock(m_mutex_state); 279 | if (!m_cv_state.wait_for(lock, std::chrono::milliseconds(timeout), [this] { return m_state != MJC_PENDING; })) { 280 | return false; 281 | } 282 | } 283 | return m_state >= MJC_CONNECTED; 284 | } 285 | 286 | void CMojoCall::OnRemoteProcessLaunchFailed(int error_code) 287 | { 288 | std::lock_guard lock(m_mutex_state); 289 | if (m_state == MJC_PENDING) { 290 | m_state = MJC_FAILED; 291 | m_cv_state.notify_all(); 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /src/mojocall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "mmmojo.h" 4 | 5 | #ifdef _WIN32 6 | typedef std::wstring tstring; 7 | #else 8 | typedef const char* LPCTSTR; 9 | typedef void* HMODULE; 10 | typedef std::string tstring; 11 | #endif 12 | 13 | #ifndef EXPORTED_API 14 | # ifdef _WIN32 15 | # define EXPORTED_API __declspec(dllexport) 16 | # pragma warning(disable : 4251) 17 | # else 18 | # define EXPORTED_API 19 | # endif 20 | #endif 21 | 22 | #ifndef WIN_POSIX 23 | # ifdef _WIN32 24 | # define WIN_POSIX(a,b) a 25 | # else 26 | # define WIN_POSIX(a,b) b 27 | # endif 28 | #endif 29 | 30 | namespace mmmojo 31 | { 32 | //每一个组件的每一个请求都有一个自己的RequestId 组件会根据请求ID进行对应的操作 33 | 34 | //WeChatOCR组件 35 | enum RequestIdOCR3 36 | { 37 | OCRPush = 1, 38 | }; 39 | enum RequestIdOCR4 40 | { 41 | HAND_SHAKE = 10001, 42 | REQ_OCR = 10010, 43 | RESP_OCR = 10011, 44 | PUT_UserInfoMessage = 20012, 45 | }; 46 | 47 | //WeChatUtility组件 48 | enum RequestIdUtility 49 | { 50 | UtilityHiPush = 10001, //是Utility启动发送的 51 | UtilityInitPullReq = 10002, //初始化请求 52 | UtilityInitPullResp = 10003, //回复创建的都是Shared类型的info, 但是调用了SwapMMMojoWriteInfoCallback, 所以回调的还是Pull 53 | UtilityResampleImagePullReq = 10010, 54 | UtilityResampleImagePullResp = 10011, 55 | UtilityDecodeImagePullReq = 10020, 56 | UtilityDecodeImagePullResp = 10021, 57 | UtilityPicQRScanPullReq = 10030, //10030是点击OCR时(也是打开图片时)发送的请求, 参数是图片路径 58 | UtilityQRScanPullReq = 10031, //10031是截图框选时发送的请求, 参数应该是某种编码后的图片数据 59 | UtilityQRScanPullResp = 10032, //这两种请求的返回ID都是10032 60 | UtilityTextScanPushResp = 10040 //TextScan具体在扫什么不是很清楚 可能是用来判断图片上是否有文字 61 | }; 62 | 63 | //ThumbPlayer组件 64 | enum RequestIdPlayer 65 | { 66 | PlayerHiPush = 10001, //ThumbPlayer启动时发送的 67 | PlayerInitPullReq = 10002, //PlayerMgr::Init 68 | PlayerInitPullResp = 10003, //PlayerMgr::Init 69 | PlayerInitPlayerCorePush = 10010, 70 | PlayerCreatePlayerCorePullReq = 10011, //PlayerMgr::CreatePlayerCore 71 | PlayerCreatePlayerCorePullResp = 10012, //PlayerMgr::CreatePlayerCore 72 | PlayerDestroyPlayerCorePush = 10013, //PlayerMgr::DestroyCore 73 | PlayerPrepareAsyncPush = 10014, //PlayerMgr::PrepareCore 74 | PlayerStartPush = 10015, //PlayerMgr::StartCore 75 | PlayerStopPush = 10016, //PlayerMgr::StopCore 76 | PlayerPausePush = 10017, //PlayerMgr::PauseCore 77 | PlayerResumePush = 10018, //PlayerMgr::ResumeCore 78 | PlayerSetAudioMutePush = 10019, //PlayerMgr::AudioMuteCore 79 | PlayerSeekToAsyncPush = 10020, //PlayerMgr::SeekToCore 80 | PlayerGetCurrentPositionMsPullReq = 10021, //PlayerMgr::GetCurrentPositionMsCore 81 | PlayerGetCurrentPositionMsPullResp = 10022, //PlayerMgr::GetCurrentPositionMsCore 82 | PlayerSetVideoSurfacePush = 10023, //PlayerMgr::VideoSurfaceCore 83 | PlayerSetAudioVolumePush = 10024, //PlayerMgr::AudioVolumeCore 84 | PlayerSetDataSourcePush = 10025, //PlayerMgr::ReadyDataSourceCore 85 | PlayerSetLoaderSourcePush = 10026, //PlayerMgr::DownloadDataSourceCore 86 | PlayerSetRepeatPush = 10027, //PlayerMgr::RepeatCore 87 | PlayerResizePush = 10028, //PlayerMgr::ResizeCore 88 | PlayerSetPlaySpeedRatio = 10029, //PlayerMgr::SpeedRatioCore 89 | PlayerInfoPush = 10030, 90 | PlayerErrorPlayerPush = 10031, 91 | PlayerVideoSizeChangedPush = 10032, 92 | PlayerStopAsyncCompletedPush = 10033, 93 | PlayerStateChangePush = 10034, 94 | PlayerSeekCompletedPush = 10035, 95 | PlayerCompletedPush = 10036, 96 | PlayerStartTaskProxyPush = 10050, 97 | PlayerStartRequestProxyPush = 10051, 98 | PlayerCloseRequestProxyPush = 10052, 99 | PlayerPollingDatProxyPullReq = 10053, 100 | PlayerPollingDatProxyPullResp = 10054 101 | }; 102 | } 103 | 104 | class EXPORTED_API CMojoCall 105 | { 106 | public: 107 | static constexpr int MJC_FAILED = -1; 108 | static constexpr int MJC_PENDING = 0; 109 | static constexpr int MJC_CONNECTED = 1; 110 | 111 | protected: 112 | HMODULE m_mod = NULL; 113 | bool m_should_free_mod = false; 114 | void* m_env = 0; 115 | int m_state = MJC_PENDING; 116 | std::mutex m_mutex_state; // mutex for conn. 117 | std::condition_variable m_cv_state; 118 | 119 | /** 120 | * @brief 对应Chromium源码中的base::CommandLine->AppendSwitchNative方法 用于添加一个'开关(Switch)'. 121 | * 例如 "user-lib-dir" => X:\Foo 这样会在命令行参数添加一个"--user-lib-dir=X:\Foo" 122 | */ 123 | std::map m_args; 124 | 125 | protected: 126 | CMojoCall(); 127 | virtual ~CMojoCall(); 128 | 129 | bool Init(LPCTSTR dir); 130 | bool Start(LPCTSTR exepath); 131 | void Stop(); 132 | virtual bool wait_connection(int timeout); 133 | bool SendPbSerializedData(const void* pb_data, size_t data_size, int method, bool sync, uint32_t request_id); 134 | 135 | //call backs. 136 | virtual void ReadOnPush(uint32_t request_id, std::span request_info) {} 137 | virtual void ReadOnPull(uint32_t request_id, std::span request_info) {} 138 | virtual void ReadOnShared(uint32_t request_id, std::span request_info) {} 139 | virtual void OnRemoteConnect(bool is_connected); 140 | virtual void OnRemoteDisConnect(); 141 | virtual void OnRemoteProcessLaunched() {} 142 | virtual void OnRemoteProcessLaunchFailed(int error_code); 143 | virtual void OnRemoteError(const void* errorbuf, int errorsize) { 144 | fprintf(stderr, "OnRemoteError: %.*s\n", errorsize, (const char*)errorbuf); 145 | } 146 | }; 147 | 148 | namespace util 149 | { 150 | template 151 | requires std::is_pointer_v && std::is_function_v::type> && (std::is_pointer_v || std::is_integral_v) 152 | struct auto_del_t 153 | { 154 | T object; 155 | FT caller; 156 | 157 | auto_del_t(T obj, FT call) 158 | : object(obj) 159 | , caller(call) 160 | {} 161 | ~auto_del_t() 162 | { 163 | if (caller) caller(object); 164 | } 165 | auto_del_t(const auto_del_t&) = delete; 166 | auto_del_t& operator=(const auto_del_t&) = delete; 167 | auto_del_t(auto_del_t&&) noexcept = delete; 168 | auto_del_t& operator=(auto_del_t&&) noexcept = delete; 169 | }; 170 | 171 | inline tstring to_tstr(const char* src, bool isutf8 = true) 172 | { 173 | #ifdef _WIN32 174 | int cp = isutf8 ? CP_UTF8 : CP_ACP; 175 | int len = MultiByteToWideChar(cp, 0, src, -1, NULL, 0); 176 | wstring ret; 177 | if (len > 0) { 178 | ret.resize(len); 179 | MultiByteToWideChar(cp, 0, src, -1, &ret[0], len); 180 | } 181 | return ret; 182 | #else 183 | return src; 184 | #endif 185 | } 186 | inline string from_tstr(const tstring& src, bool isutf8 = true) 187 | { 188 | #ifdef _WIN32 189 | int cp = isutf8 ? CP_UTF8 : CP_ACP; 190 | int len = WideCharToMultiByte(cp, 0, src.c_str(), -1, NULL, 0, NULL, NULL); 191 | string ret; 192 | if (len > 0) { 193 | ret.reserve(len + 2); 194 | ret.resize(len); 195 | WideCharToMultiByte(cp, 0, src.c_str(), -1, &ret[0], len, NULL, NULL); 196 | } 197 | return ret; 198 | #else 199 | return src; 200 | #endif 201 | } 202 | inline int f_write(FILE* fp, const void* data, int size){ 203 | #ifdef _WIN32 204 | if (size < 0) return -1; 205 | if (size == 0) return 0; 206 | DWORD cp = GetConsoleOutputCP(); 207 | if (cp == CP_UTF8) { 208 | return (int) ::fwrite(data, 1, size, fp); 209 | } else { 210 | int len = MultiByteToWideChar(CP_UTF8, 0, (const char*)data, (int)size, NULL, 0); 211 | if (len > 0) { 212 | std::vector wbuf(len + 1); 213 | MultiByteToWideChar(CP_UTF8, 0, (const char*)data, (int)size, wbuf.data(), len); 214 | int len2 = WideCharToMultiByte(cp, 0, wbuf.data(), len, NULL, 0, NULL, NULL); 215 | if (len2 > 0) { 216 | std::vector buf(len2 + 1); 217 | WideCharToMultiByte(cp, 0, wbuf.data(), len, buf.data(), len2, NULL, NULL); 218 | return (int)::fwrite(buf.data(), 1, len2, fp); 219 | } 220 | } 221 | return -1; 222 | } 223 | #else 224 | return (int)::fwrite(data, 1, size, fp); 225 | #endif 226 | } 227 | inline int vfprintf(FILE* fp, const char* fmt, va_list ap) { 228 | va_list ap2; 229 | va_copy(ap2, ap); 230 | char buf[1024]; 231 | int len = vsnprintf(buf, sizeof(buf), fmt, ap); 232 | int ret; 233 | if (len >= 1024) { 234 | std::vector vbuf(len + 1); 235 | vsnprintf(vbuf.data(), len + 1, fmt, ap2); 236 | ret = f_write(fp, vbuf.data(), len); 237 | } else { 238 | ret = f_write(fp, buf, len); 239 | } 240 | va_end(ap2); 241 | return ret; 242 | } 243 | inline int fprintf(FILE* fp, const char* fmt, ...) { 244 | va_list ap; 245 | va_start(ap, fmt); 246 | int ret = util::vfprintf(fp, fmt, ap); 247 | va_end(ap); 248 | return ret; 249 | } 250 | } // namespace util 251 | -------------------------------------------------------------------------------- /src/pyspt.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "pyspt.h" 3 | #include "wechatocr.h" 4 | 5 | #if USE_PYTHON+0 6 | static CWeChatOCR* g_ocr_obj = 0; 7 | static PyObject* py_init(PyObject* self, PyObject* args) 8 | { 9 | const char* exe; 10 | const char* wcdir; 11 | if (!PyArg_ParseTuple(args, "ss", &exe, &wcdir)) 12 | return NULL; 13 | if (!g_ocr_obj) { 14 | tstring wexe = util::to_tstr(exe); 15 | tstring wwcdir = util::to_tstr(wcdir); 16 | auto obj = new CWeChatOCR(wexe.c_str(), wwcdir.c_str()); 17 | if (obj->wait_connection(5000)) { 18 | g_ocr_obj = obj; 19 | Py_RETURN_TRUE; 20 | } else { 21 | delete obj; 22 | Py_RETURN_FALSE; 23 | } 24 | } 25 | Py_RETURN_TRUE; 26 | } 27 | 28 | static PyObject* py_destroy(PyObject* self, PyObject* args) 29 | { 30 | if (g_ocr_obj) { 31 | delete g_ocr_obj; 32 | g_ocr_obj = 0; 33 | } 34 | Py_RETURN_NONE; 35 | } 36 | 37 | static PyObject* py_ocr(PyObject* self, PyObject* args) { 38 | const char* imgpath=0; 39 | if (!PyArg_ParseTuple(args, "s", &imgpath)) 40 | return NULL; 41 | if (!g_ocr_obj) { 42 | PyErr_SetString(PyExc_RuntimeError, "wechatocr not initialized"); 43 | return NULL; 44 | } 45 | 46 | CWeChatOCR::result_t res{}; 47 | if (!g_ocr_obj->doOCR(imgpath, &res)) { 48 | PyErr_SetString(PyExc_RuntimeError, "wechatocr doOCR failed"); 49 | return NULL; 50 | } 51 | 52 | PyObject* dict = PyDict_New(); 53 | 54 | PyObject* tmpo = PyUnicode_FromString(res.imgpath.c_str()); 55 | PyDict_SetItemString(dict, "imgpath", tmpo); 56 | Py_DECREF(tmpo); 57 | 58 | tmpo = PyLong_FromLong(res.errcode); 59 | PyDict_SetItemString(dict, "errcode", tmpo); 60 | Py_DECREF(tmpo); 61 | 62 | tmpo = PyLong_FromLong(res.width); 63 | PyDict_SetItemString(dict, "width", tmpo); 64 | Py_DECREF(tmpo); 65 | tmpo = PyLong_FromLong(res.height); 66 | PyDict_SetItemString(dict, "height", tmpo); 67 | Py_DECREF(tmpo); 68 | 69 | tmpo = PyList_New(res.ocr_response.size()); 70 | size_t idx = 0; 71 | for (auto& kv : res.ocr_response) { 72 | PyObject* tmpo2 = PyDict_New(); 73 | PyObject* tmpo3 = PyUnicode_FromString(kv.text.c_str()); 74 | PyDict_SetItemString(tmpo2, "text", tmpo3); 75 | Py_DECREF(tmpo3); 76 | tmpo3 = PyFloat_FromDouble(kv.left); 77 | PyDict_SetItemString(tmpo2, "left", tmpo3); 78 | Py_DECREF(tmpo3); 79 | tmpo3 = PyFloat_FromDouble(kv.top); 80 | PyDict_SetItemString(tmpo2, "top", tmpo3); 81 | Py_DECREF(tmpo3); 82 | tmpo3 = PyFloat_FromDouble(kv.right); 83 | PyDict_SetItemString(tmpo2, "right", tmpo3); 84 | Py_DECREF(tmpo3); 85 | tmpo3 = PyFloat_FromDouble(kv.bottom); 86 | PyDict_SetItemString(tmpo2, "bottom", tmpo3); 87 | Py_DECREF(tmpo3); 88 | tmpo3 = PyFloat_FromDouble(kv.rate); 89 | PyDict_SetItemString(tmpo2, "rate", tmpo3); 90 | Py_DECREF(tmpo3); 91 | PyList_SetItem(tmpo, idx++, tmpo2); 92 | // Py_DECREF(tmpo2); // note: no need to decref tmpo2, PyList_SetItem already steals the reference. 93 | } 94 | PyDict_SetItemString(dict, "ocr_response", tmpo); 95 | Py_DECREF(tmpo); 96 | return dict; 97 | } 98 | 99 | extern "C" EXPORTED_API 100 | PyObject* PyInit_wcocr(void) 101 | { 102 | static PyMethodDef wcocr_methods[] = { 103 | { "init", py_init, METH_VARARGS, "init(wechatocr_exe_path, wechat_dir)=>bool\ninit wechatocr" }, 104 | { "destroy", py_destroy, METH_VARARGS, "destroy()=>deinit wechatocr" }, 105 | { "ocr", py_ocr, METH_VARARGS, "ocr(imgpath)=>dict" }, 106 | { NULL, NULL, 0, NULL } 107 | }; 108 | static PyModuleDef wcocr_module = { 109 | PyModuleDef_HEAD_INIT, 110 | "wcocr", 111 | "wechatocr", 112 | 0, // size 113 | wcocr_methods, 114 | NULL, // slots 115 | }; 116 | PyObject* m = PyModule_Create(&wcocr_module); 117 | return m; 118 | } 119 | #endif 120 | -------------------------------------------------------------------------------- /src/pyspt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef USE_PYTHON 4 | #if __has_include() 5 | #define USE_PYTHON 1 6 | #endif 7 | #endif 8 | 9 | #if USE_PYTHON+0 10 | # define Py_LIMITED_API 0x03080000 11 | # pragma push_macro("_DEBUG") 12 | # undef _DEBUG // we dont have python310_d.lib, so temporarily disable debug mode 13 | # include 14 | # pragma pop_macro("_DEBUG") 15 | #endif 16 | -------------------------------------------------------------------------------- /src/wechatocr.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "wechatocr.h" 3 | #include "ocr_wx3.pb.h" 4 | #include "ocr_wx4.pb.h" 5 | #include 6 | 7 | namespace fs = std::filesystem; 8 | 9 | namespace { 10 | bool is_text_utf8(const char* sin, size_t len) { 11 | const unsigned char* s = (const unsigned char*)sin; 12 | const unsigned char* end = s + len; 13 | while (s < end) { 14 | if (*s < 0x80) { 15 | ++s; 16 | } else if (*s < 0xC0) { 17 | return false; 18 | } else if (*s < 0xE0) { 19 | if (s + 1 >= end || (s[1] & 0xC0) != 0x80) 20 | return false; 21 | s += 2; 22 | } else if (*s < 0xF0) { 23 | if (s + 2 >= end || (s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80) 24 | return false; 25 | s += 3; 26 | } else if (*s < 0xF8) { 27 | if (s + 3 >= end || (s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80 || (s[3] & 0xC0) != 0x80) 28 | return false; 29 | s += 4; 30 | } else { 31 | return false; 32 | } 33 | } 34 | return true; 35 | } 36 | } 37 | 38 | CWeChatOCR::CWeChatOCR(LPCTSTR exe0, LPCTSTR wcdir0) 39 | { 40 | tstring exe = exe0; 41 | tstring wcdir = wcdir0; 42 | #ifdef _WIN32 43 | // convert / to '\\' 44 | std::replace(wcdir.begin(), wcdir.end(), L'/', L'\\'); 45 | std::replace(exe.begin(), exe.end(), L'/', L'\\'); 46 | #endif 47 | bool exe_ok = fs::is_regular_file(exe); 48 | if (!exe_ok || !fs::is_directory(wcdir)) { 49 | // 传入的ocr.exe / wcdir 路径无效 50 | util::fprintf(stderr, "Invalid path: %s, must be %s.\n", util::from_tstr(exe_ok ? wcdir : exe).c_str(), 51 | exe_ok ? "a directory." : "an executable."); 52 | m_state = MJC_FAILED; 53 | return; 54 | } 55 | 56 | if (Init(wcdir.c_str())) 57 | { 58 | m_args["no-sandbox"] = WIN_POSIX(L"", ""); 59 | 60 | #ifdef _WIN32 61 | m_args["user-lib-dir"] = wcdir; 62 | // 测试 wc4.0, 改成 dll了 63 | auto fn_ext = exe.substr(exe.size() - 4); 64 | if (wcsicmp(fn_ext.c_str(), L".dll") == 0) { 65 | auto exe2 = wcdir; 66 | if (exe2.back() != '\\') exe2.push_back('\\'); 67 | exe2 += L"..\\weixin.exe"; 68 | auto sep_pos = exe.rfind('\\'); 69 | tstring app_path = exe.substr(0, sep_pos); 70 | tstring app_name = exe.substr(sep_pos + 1); 71 | if (size_t dot_pos = app_name.rfind('.'); dot_pos != std::wstring::npos) { 72 | app_name.resize(dot_pos); 73 | } 74 | m_args["type"] = std::move(app_name); 75 | m_args["app-path"] = std::move(app_path); 76 | exe = std::move(exe2); 77 | m_version = 400; 78 | } 79 | #else 80 | m_version = 400; // Linux 强制使用 4.0 版本 81 | #endif 82 | if (!Start(exe.c_str())) 83 | { 84 | std::lock_guard lock(m_mutex_state); 85 | m_state = MJC_FAILED; 86 | m_cv_state.notify_all(); 87 | } 88 | } 89 | } 90 | 91 | #define OCR_MAX_TASK_ID INT_MAX 92 | bool CWeChatOCR::doOCR(crefstr imgpath0, result_t* res) 93 | { 94 | if (!wait_connection(2000)) 95 | return false; 96 | 97 | // wx4 中,图片路径必须是绝对路径,否则会失败 98 | string imgpath; 99 | #ifndef _WIN32 100 | do { 101 | auto u8s = std::filesystem::weakly_canonical(imgpath0).u8string(); 102 | imgpath = std::string(u8s.begin(), u8s.end()); 103 | } while(0); 104 | #else 105 | do { 106 | std::wstring wtmp; 107 | wtmp.resize(imgpath0.length() + 2); 108 | DWORD cp = is_text_utf8(imgpath0.c_str(), imgpath0.length()) ? CP_UTF8 : CP_ACP; 109 | int len = MultiByteToWideChar(cp, 0, imgpath0.c_str(), (int)imgpath0.length(), &wtmp[0], (int)wtmp.size()); 110 | wtmp.resize(len > 0 ? len : 0); 111 | auto patho = std::filesystem::weakly_canonical(wtmp); 112 | if (!patho.empty()) { 113 | auto u8s = patho.u8string(); 114 | imgpath = std::string(u8s.begin(), u8s.end()); 115 | } else { 116 | if (res) { 117 | res->errcode = -2; 118 | res->imgpath = imgpath0; 119 | } 120 | return false; 121 | } 122 | } while (0); 123 | #endif 124 | 125 | int found_id = -1; 126 | m_mutex.lock(); 127 | // XXX: task_id本身可以是任何正整形数,但是这里要不要限制同时并发任务数呢? 128 | // 由于1号task_id已经被用于hello消息,所以从2开始。当然1号也不是不能重用,但为了安全起见不用了,也不差这一个task_id。 129 | for (uint32_t i = 2; i <= OCR_MAX_TASK_ID; ++i) 130 | { 131 | if (m_idpath.insert(std::make_pair(i, std::pair(imgpath0,res))).second) 132 | { 133 | found_id = i; 134 | break; 135 | } 136 | } 137 | m_mutex.unlock(); 138 | if (found_id < 0) // too many tasks. 139 | return false; 140 | 141 | std::string data_; 142 | uint32_t reqid = 0; 143 | //创建OcrRequest的pb数据 144 | if (m_version == 300) { 145 | wx3::OcrRequest ocr_request; 146 | ocr_request.set_type(0); 147 | ocr_request.set_task_id(found_id); 148 | auto pp = new wx3::OcrInputBuffer; 149 | pp->set_pic_path(imgpath); 150 | ocr_request.set_allocated_input(pp); 151 | ocr_request.SerializeToString(&data_); 152 | // 这个reqid根本没有用到,填啥都行 153 | reqid = mmmojo::RequestIdOCR3::OCRPush; 154 | } 155 | else if (m_version == 400) { 156 | wx4::ParseOCRReqMessage req; 157 | req.set_task_id(found_id); 158 | req.set_pic_path(imgpath); 159 | auto rt = new wx4::ReqType; 160 | // 我也不知道这仨是干啥的... 161 | rt->set_t1(true); 162 | rt->set_t2(true); 163 | rt->set_t3(false); 164 | req.set_allocated_rt(rt); 165 | req.SerializeToString(&data_); 166 | reqid = mmmojo::RequestIdOCR4::REQ_OCR; 167 | } 168 | // fprintf(stderr, "Sending Request...\n"); 169 | bool bx = SendPbSerializedData(data_.data(), data_.size(), MMMojoInfoMethod::kMMPush, false, reqid); 170 | if (bx && res) { 171 | // wait for result. 172 | std::unique_lock lock(m_mutex); 173 | m_cv_idpath.wait(lock, [this, found_id] {return m_idpath.find(found_id) == m_idpath.end(); }); 174 | } 175 | return bx; 176 | } 177 | 178 | void CWeChatOCR::ReadOnPush(uint32_t request_id, std::span request_info) 179 | { 180 | if (request_info.empty()) 181 | return; 182 | auto init_done = [this](bool init_ok) { 183 | std::lock_guard lock(m_mutex_state); 184 | if (m_state == MJC_PENDING || m_state == MJC_CONNECTED) 185 | { 186 | m_state = init_ok ? STATE_INITED : MJC_FAILED; 187 | m_cv_state.notify_all(); 188 | } 189 | }; 190 | auto ocr_copy = [this](const auto & ores, int ec, result_t& res) { 191 | res.width = ores.img_width(); 192 | res.height = ores.img_height(); 193 | res.errcode = ec; 194 | res.ocr_response.reserve(ores.lines_size()); 195 | for (int i = 0, mi = ores.lines_size(); i < mi; ++i) { 196 | text_block_t tb; 197 | const auto& single_result = ores.lines(i); 198 | tb.left = single_result.left(); 199 | tb.top = single_result.top(); 200 | tb.right = single_result.right(); 201 | tb.bottom = single_result.bottom(); 202 | tb.rate = single_result.rate(); 203 | tb.text = single_result.text(); 204 | // printf("{%.1f,%.1f,%.1f,%.1f}: \"%s\", rate=%.3f\n", tb.left, tb.top, tb.right, tb.bottom, tb.text.c_str(), tb.rate); 205 | res.ocr_response.push_back(std::move(tb)); 206 | } 207 | }; 208 | auto ocr_done = [this](uint64_t task_id, result_t & res) { 209 | { 210 | std::lock_guard lock(m_mutex); 211 | auto it = m_idpath.find(task_id); 212 | if (it != m_idpath.end()) 213 | { 214 | res.imgpath = std::move(it->second.first); 215 | auto wres = it->second.second; 216 | if (wres) *wres = res; 217 | } 218 | } 219 | OnOCRResult(res); 220 | std::lock_guard lock(m_mutex); 221 | m_idpath.erase(task_id); 222 | m_cv_idpath.notify_all(); 223 | }; 224 | 225 | result_t res; 226 | if (m_version >= 400) { 227 | if (request_id == mmmojo::RequestIdOCR4::HAND_SHAKE) { 228 | wx4::OCRSupportMessage msg; 229 | if (!msg.ParseFromArray(request_info.data(), (int)request_info.size())) 230 | return; 231 | bool supported = msg.has_supported() && msg.supported(); 232 | if (!supported) { 233 | fprintf(stderr, "OCR4: OCR not supported\n"); 234 | } 235 | init_done(supported); 236 | } 237 | else if (request_id == mmmojo::RequestIdOCR4::RESP_OCR) { 238 | wx4::ParseOCRRespMessage resp; 239 | if (!resp.ParseFromArray(request_info.data(), (int)request_info.size())) 240 | return; 241 | if (resp.has_res()) { 242 | ocr_copy(resp.res(), resp.err_code(), res); 243 | } else { 244 | res.errcode = resp.has_err_code() ? resp.err_code() : -1; 245 | } 246 | ocr_done(resp.task_id(), res); 247 | } 248 | return; 249 | } else if (m_version >= 300) { 250 | if (request_id == mmmojo::RequestIdOCR3::OCRPush) { 251 | wx3::OcrRespond resp; 252 | resp.ParseFromArray(request_info.data(), (int)request_info.size()); 253 | switch (resp.type()) { 254 | case 1: // init response, with taskid=1, ec=0 255 | do { 256 | auto ec = resp.err_code(); 257 | if (ec != 0) fprintf(stderr, "WX3: init failed, ec=%d\n", ec); 258 | init_done(ec == 0); 259 | } while (0); 260 | break; 261 | case 0: 262 | if (resp.has_ocr_result()) { 263 | ocr_copy(resp.ocr_result(), resp.err_code(), res); 264 | } else { 265 | res.errcode = resp.has_err_code() ? resp.err_code() : -1; 266 | } 267 | ocr_done(resp.task_id(), res); 268 | break; 269 | default: 270 | fprintf(stderr, "WX3: got responce with type %d\n", resp.type()); 271 | break; 272 | } 273 | } 274 | } 275 | } 276 | 277 | bool CWeChatOCR::wait_connection(int timeout) 278 | { 279 | if (m_state != MJC_PENDING) { 280 | return m_state >= STATE_INITED; 281 | } 282 | auto checker = [this] {return m_state >= STATE_INITED || m_state == MJC_FAILED; }; 283 | if (timeout < 0) { 284 | std::unique_lock lock(m_mutex_state); 285 | m_cv_state.wait(lock, checker); 286 | } else { 287 | std::unique_lock lock(m_mutex_state); 288 | if (!m_cv_state.wait_for(lock, std::chrono::milliseconds(timeout), checker)) 289 | { 290 | return false; 291 | } 292 | } 293 | return m_state >= STATE_INITED; 294 | } 295 | 296 | bool CWeChatOCR::wait_done(int timeout) 297 | { 298 | if (!wait_connection(timeout)) 299 | return false; 300 | 301 | std::unique_lock lock(m_mutex); 302 | if (timeout < 0) 303 | return m_cv_idpath.wait(lock, [this] {return m_idpath.empty(); }), true; 304 | else 305 | return m_cv_idpath.wait_for(lock, std::chrono::milliseconds(timeout), [this] {return m_idpath.empty(); }); 306 | } 307 | 308 | void CWeChatOCR::OnOCRResult(result_t& res) 309 | { 310 | // do nothing. 311 | } 312 | -------------------------------------------------------------------------------- /src/wechatocr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "mojocall.h" 3 | 4 | class EXPORTED_API CWeChatOCR : protected CMojoCall 5 | { 6 | public: 7 | struct text_block_t { 8 | float left, top, right, bottom; 9 | float rate; 10 | string text; 11 | }; 12 | struct result_t { 13 | string imgpath; 14 | int errcode; 15 | int width, height; 16 | std::vector ocr_response; 17 | }; 18 | static constexpr int STATE_INITED = 2; // extend state vars from base class. 19 | protected: 20 | int m_version = 300; // wechat version 3.x 21 | std::mutex m_mutex; 22 | std::condition_variable m_cv_idpath; 23 | std::map> m_idpath; 24 | 25 | public: 26 | CWeChatOCR(LPCTSTR exe, LPCTSTR wcdir); 27 | ~CWeChatOCR() = default; 28 | 29 | int state() const { return m_state; } 30 | bool wait_connection(int timeout) override; 31 | bool wait_done(int timeout); //wait for all pending ocr done. 32 | bool doOCR(crefstr imgpath, result_t* res = nullptr); 33 | 34 | protected: 35 | virtual void OnOCRResult(result_t& ocr_response); 36 | void ReadOnPush(uint32_t request_id, std::span request_info) override; 37 | }; 38 | -------------------------------------------------------------------------------- /vs.proj/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /vs.proj/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifdef _WIN32 3 | #define _WIN32_LEAN_AND_MEAN 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using std::string; 22 | using std::wstring; 23 | typedef const std::string& crefstr; 24 | -------------------------------------------------------------------------------- /vs.proj/wcocr.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34330.188 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wcocr", "wcocr.vcxproj", "{78005D76-B64F-47C2-A6F7-5E6FE485BB57}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Win32 = Release|Win32 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Debug|Win32.Build.0 = Debug|Win32 20 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Debug|x64.ActiveCfg = Debug|x64 21 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Debug|x64.Build.0 = Debug|x64 22 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Debug|x86.ActiveCfg = Debug|Win32 23 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Debug|x86.Build.0 = Debug|Win32 24 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Release|Win32.ActiveCfg = Release|Win32 25 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Release|Win32.Build.0 = Release|Win32 26 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Release|x64.ActiveCfg = Release|x64 27 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Release|x64.Build.0 = Release|x64 28 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Release|x86.ActiveCfg = Release|Win32 29 | {78005D76-B64F-47C2-A6F7-5E6FE485BB57}.Release|x86.Build.0 = Release|Win32 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {FEEC6966-6583-4294-BA4F-B2AFF701388B} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /vs.proj/wcocr.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {0CA4B783-7DED-44BE-861A-D23A20730163} 6 | 7 | 8 | {2CE2AC29-0BEB-4C66-BE65-33D8AAAE505B} 9 | 10 | 11 | {cb0b7138-ed7c-4a7c-851d-62abd130775b} 12 | 13 | 14 | 15 | 16 | src 17 | 18 | 19 | src 20 | 21 | 22 | src 23 | 24 | 25 | vs.proj 26 | 27 | 28 | src 29 | 30 | 31 | src 32 | 33 | 34 | src 35 | 36 | 37 | src 38 | 39 | 40 | src 41 | 42 | 43 | 44 | 45 | src 46 | 47 | 48 | src 49 | 50 | 51 | vs.proj 52 | 53 | 54 | src 55 | 56 | 57 | src 58 | 59 | 60 | src 61 | 62 | 63 | src 64 | 65 | 66 | src 67 | 68 | 69 | 70 | 71 | pb 72 | 73 | 74 | pb 75 | 76 | 77 | pb 78 | 79 | 80 | pb 81 | 82 | 83 | pb 84 | 85 | 86 | --------------------------------------------------------------------------------