├── README.md ├── STHTMLPP.sln ├── STHTMLPP ├── HtmlAgilityPack.h ├── STHTMLPP.cpp ├── STHTMLPP.vcxproj ├── STHTMLPP.vcxproj.filters ├── STHTMLPP.vcxproj.user ├── Source.def ├── Tools.h ├── sds.c ├── sds.h ├── stdafx.cpp ├── stdafx.h ├── strings.h ├── targetver.h ├── utf8_strings.cpp └── utf8_strings.h └── img ├── 123.PNG └── 456.PNG /README.md: -------------------------------------------------------------------------------- 1 | # gumbo-querySelector 2 | html选择器elss 3 | 4 | ![image](https://github.com/1694439208/gumbo-querySelector/blob/master/img/123.PNG) 5 | 6 | ![image](https://github.com/1694439208/gumbo-querySelector/blob/master/img/456.PNG) 7 | 8 | 于解析引擎无关的表达式解析引擎elss 9 | 10 | 11 | elss 0.0.1 12 | 2018/09/25 17:57:00 修订 13 | 人员: 14 | 开发:海绵宝宝 15 | 语法:我才是星辰 16 | 吹牛逼的:二毛娃娃 17 | 18 | 19 | 语法组成:指令 20 | 21 | 3大基本语法:标签名 .class值 #id值 22 | 23 | 基本指令 > : 24 | 25 | 多条指令使用语法:指令1 > 指令2 > 指令3 > ... 26 | 27 | 基本语法规范: 28 | ---------------------------------------------------- 29 | 字符串和属性使用单引号或者双引号引起来 30 | ---------------------------------------------------- 31 | 32 | 33 | 基本函数: 34 | ---------------------------------------------------- 35 | find(属性,内容) 为查找属性值为内容的标签 36 | fuzzyfind(属性,内容) 为查找属性值包含内容的标签 37 | ---------------------------------------------------- 38 | 39 | 40 | 基本功能1: 41 | ---------------------------------------------------- 42 | 说明:我想获取a标签的所有内容 43 | 44 | 1 45 | 2 46 | 3 47 | 48 | 指令:a 49 | ---------------------------------------------------- 50 | 51 | 基本功能2: 52 | ---------------------------------------------------- 53 | 说明:我想获取id为list1的div里面的a标签的所有内容 54 | 55 |
56 |
57 |
58 | 1 59 |
60 |
61 | 2 62 |
63 |
64 | 3 65 |
66 |
67 |
68 |
69 |
70 |
71 | 4 72 |
73 |
74 | 5 75 |
76 |
77 | 6 78 |
79 |
80 |
81 | 82 | 83 | 指令1:#list1 > dl > dd > a 84 | 或 85 | 指令2:div:find('id','list1') > dl > dd > a 86 | ---------------------------------------------------- 87 | 88 | 功能1: 89 | ---------------------------------------------------- 90 | 说明:指令前面是. 则为匹配class属性,要匹配出233 91 | 92 |
233
93 | 94 | 指令:.test 95 | ---------------------------------------------------- 96 | 97 | 98 | 功能2: 99 | ---------------------------------------------------- 100 | 说明:指令前面是# 则为匹配id属性,要匹配出233 101 | 102 |
233
103 | 104 | 指令:#test 105 | ---------------------------------------------------- 106 | 107 | 108 | 功能3: 109 | ---------------------------------------------------- 110 | 说明:如果想指定标签属性筛选,要匹配出233 111 | 112 |
233
113 |
266
114 | 115 | 指令:div:find('id','test') 116 | ---------------------------------------------------- 117 | 118 | 119 | 功能4: 120 | ---------------------------------------------------- 121 | 说明:如果想指定标签属性模糊筛选,要匹配出233和266 122 | 123 |
233
124 |
266
125 | 126 | 指令:div:fuzzyfind('id','test_') 127 | ---------------------------------------------------- 128 | 129 | 功能5: 130 | ---------------------------------------------------- 131 | 支持函数链式操作 132 | div:find('id','test'):div:fuzzyfind('id','test_')>div>a 133 | 支持以上所有语法混合 134 | div:find('id','test'):div>fuzzyfind('id','test_') 135 | 136 | ---------------------------------------------------- 137 | 138 | 139 | qq群交流:551518556 140 | -------------------------------------------------------------------------------- /STHTMLPP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2010 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "STHTMLPP", "STHTMLPP\STHTMLPP.vcxproj", "{0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Debug|x64.ActiveCfg = Debug|x64 17 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Debug|x64.Build.0 = Debug|x64 18 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Debug|x86.ActiveCfg = Debug|Win32 19 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Debug|x86.Build.0 = Debug|Win32 20 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Release|x64.ActiveCfg = Release|x64 21 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Release|x64.Build.0 = Release|x64 22 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Release|x86.ActiveCfg = Release|Win32 23 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {E1C4CE25-55F8-4739-B16D-8F7CFC0D181D} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /STHTMLPP/HtmlAgilityPack.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/STHTMLPP/HtmlAgilityPack.h -------------------------------------------------------------------------------- /STHTMLPP/STHTMLPP.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/STHTMLPP/STHTMLPP.cpp -------------------------------------------------------------------------------- /STHTMLPP/STHTMLPP.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {0E7FE817-E488-4F4D-ADB9-14BCD9317ABA} 24 | Win32Proj 25 | STHTMLPP 26 | 10.0.16299.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | Static 35 | false 36 | 37 | 38 | DynamicLibrary 39 | false 40 | v141_xp 41 | true 42 | MultiByte 43 | Static 44 | 45 | 46 | Application 47 | true 48 | v141 49 | Unicode 50 | 51 | 52 | DynamicLibrary 53 | false 54 | v141_xp 55 | true 56 | MultiByte 57 | Static 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | D:\用户目录\下载\htmlgumbo-parser-master\gumbo-parser-master\src;C:\Users\海绵宝宝\source\repos\libicon\Release;$(IncludePath) 80 | C:\Users\海绵宝宝\source\repos\libicon\Release;$(LibraryPath) 81 | 82 | 83 | true 84 | 85 | 86 | false 87 | C:\Users\海绵宝宝\source\repos\ATLProject1\Debug;C:\Users\海绵宝宝\source\repos\libicon\Release;$(IncludePath) 88 | C:\Users\海绵宝宝\source\repos\ATLProject1\Debug;C:\Users\海绵宝宝\source\repos\libiconv-1.15-3-vc15-x86\lib;C:\Users\海绵宝宝\source\repos\libicon\Release;$(LibraryPath) 89 | HtmlAgilityPack 90 | 91 | 92 | false 93 | HtmlAgilityPack 94 | D:\用户目录\下载\htmlgumbo-parser-master\gumbo-parser-master\src;D:\用户目录\下载\htmlgumbo-parser-master\gumbo-parser-master\visualc\include;C:\Users\海绵宝宝\source\repos\libicon\Release;$(IncludePath) 95 | D:\用户目录\下载\htmlgumbo-parser-master\gumbo-parser-master\src;C:\Users\海绵宝宝\source\repos\libiconv-1.15-3-vc15-x86\lib;C:\Users\海绵宝宝\source\repos\libicon\Release;$(LibraryPath) 96 | 97 | 98 | 99 | NotUsing 100 | Level3 101 | Disabled 102 | true 103 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | false 105 | false 106 | 107 | 108 | Console 109 | true 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | Use 119 | Level3 120 | Disabled 121 | true 122 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | true 124 | 125 | 126 | Console 127 | true 128 | 129 | 130 | 131 | 132 | NotUsing 133 | Level3 134 | Disabled 135 | true 136 | true 137 | true 138 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | false 140 | MultiThreaded 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | Source.def 148 | %(AdditionalDependencies) 149 | 150 | 151 | 152 | 153 | NotUsing 154 | Level3 155 | MaxSpeed 156 | true 157 | true 158 | true 159 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 160 | true 161 | 162 | 163 | Console 164 | true 165 | true 166 | true 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | Create 211 | Create 212 | Create 213 | Create 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /STHTMLPP/STHTMLPP.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | 头文件 16 | 17 | 18 | 头文件 19 | 20 | 21 | 源文件 22 | 23 | 24 | 头文件 25 | 26 | 27 | 源文件 28 | 29 | 30 | 源文件 31 | 32 | 33 | 源文件 34 | 35 | 36 | 源文件 37 | 38 | 39 | 源文件 40 | 41 | 42 | 源文件 43 | 44 | 45 | 源文件 46 | 47 | 48 | 源文件 49 | 50 | 51 | 源文件 52 | 53 | 54 | 源文件 55 | 56 | 57 | 源文件 58 | 59 | 60 | 源文件 61 | 62 | 63 | 源文件 64 | 65 | 66 | 源文件 67 | 68 | 69 | 源文件 70 | 71 | 72 | 源文件 73 | 74 | 75 | 源文件 76 | 77 | 78 | 源文件 79 | 80 | 81 | 源文件 82 | 83 | 84 | 头文件 85 | 86 | 87 | 88 | 89 | 源文件 90 | 91 | 92 | 源文件 93 | 94 | 95 | 源文件 96 | 97 | 98 | 源文件 99 | 100 | 101 | 源文件 102 | 103 | 104 | 源文件 105 | 106 | 107 | 源文件 108 | 109 | 110 | 源文件 111 | 112 | 113 | 源文件 114 | 115 | 116 | 源文件 117 | 118 | 119 | 源文件 120 | 121 | 122 | 源文件 123 | 124 | 125 | 源文件 126 | 127 | 128 | 源文件 129 | 130 | 131 | 源文件 132 | 133 | 134 | 源文件 135 | 136 | 137 | 138 | 139 | 源文件 140 | 141 | 142 | 源文件 143 | 144 | 145 | 源文件 146 | 147 | 148 | -------------------------------------------------------------------------------- /STHTMLPP/STHTMLPP.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /STHTMLPP/Source.def: -------------------------------------------------------------------------------- 1 | LIBRARY STHTMLPP 2 | EXPORTS 3 | Find 4 | Find1 5 | CreateHtml 6 | LoadHtml 7 | engineFree 8 | GetNode 9 | GetNodeSize 10 | GetNodeText 11 | GetNodeHtml 12 | GetAttr 13 | GetRootNode 14 | engineClose 15 | GetNodeFree -------------------------------------------------------------------------------- /STHTMLPP/Tools.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/STHTMLPP/Tools.h -------------------------------------------------------------------------------- /STHTMLPP/sds.c: -------------------------------------------------------------------------------- 1 | /* SDSLib, A C dynamic strings library 2 | * 3 | * Copyright (c) 2006-2012, Salvatore Sanfilippo 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "sds.h" 37 | sds sdsnewlen(const void *init, size_t initlen) { 38 | struct sdshdr *sh; 39 | 40 | if (init) { 41 | sh = malloc(sizeof(struct sdshdr) + initlen + 1); 42 | } 43 | else { 44 | sh = calloc(1, sizeof(struct sdshdr) + initlen + 1); 45 | } 46 | if (sh == NULL) return NULL; 47 | sh->len = initlen; 48 | sh->free = 0; 49 | if (initlen && init) 50 | memcpy(sh->buf, init, initlen); 51 | sh->buf[initlen] = '\0'; 52 | return (char*)sh->buf; 53 | } 54 | 55 | sds sdsempty(void) { 56 | return sdsnewlen("", 0); 57 | } 58 | 59 | sds sdsnew(const char *init) { 60 | size_t initlen = (init == NULL) ? 0 : strlen(init); 61 | return sdsnewlen(init, initlen); 62 | } 63 | 64 | sds sdsdup(const sds s) { 65 | return sdsnewlen(s, sdslen(s)); 66 | } 67 | 68 | void sdsfree(sds s) { 69 | if (s == NULL) return; 70 | void* sa = s - sizeof(struct sdshdr); 71 | free(sa); 72 | } 73 | 74 | void sdsupdatelen(sds s) { 75 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 76 | int reallen = strlen(s); 77 | sh->free += (sh->len - reallen); 78 | sh->len = reallen; 79 | } 80 | 81 | void sdsclear(sds s) { 82 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 83 | sh->free += sh->len; 84 | sh->len = 0; 85 | sh->buf[0] = '\0'; 86 | } 87 | 88 | /* Enlarge the free space at the end of the sds string so that the caller 89 | * is sure that after calling this function can overwrite up to addlen 90 | * bytes after the end of the string, plus one more byte for nul term. 91 | * 92 | * Note: this does not change the *size* of the sds string as returned 93 | * by sdslen(), but only the free buffer space we have. */ 94 | sds sdsMakeRoomFor(sds s, size_t addlen) { 95 | struct sdshdr *sh, *newsh; 96 | size_t free = sdsavail(s); 97 | size_t len, newlen; 98 | 99 | if (free >= addlen) return s; 100 | len = sdslen(s); 101 | sh = (void*)(s - (sizeof(struct sdshdr))); 102 | newlen = (len + addlen); 103 | if (newlen < SDS_MAX_PREALLOC) 104 | newlen *= 2; 105 | else 106 | newlen += SDS_MAX_PREALLOC; 107 | newsh = realloc(sh, sizeof(struct sdshdr) + newlen + 1); 108 | if (newsh == NULL) return NULL; 109 | 110 | newsh->free = newlen - len; 111 | return newsh->buf; 112 | } 113 | 114 | /* Reallocate the sds string so that it has no free space at the end. The 115 | * contained string remains not altered, but next concatenation operations 116 | * will require a reallocation. */ 117 | sds sdsRemoveFreeSpace(sds s) { 118 | struct sdshdr *sh; 119 | 120 | sh = (void*)(s - (sizeof(struct sdshdr))); 121 | sh = realloc(sh, sizeof(struct sdshdr) + sh->len + 1); 122 | sh->free = 0; 123 | return sh->buf; 124 | } 125 | 126 | size_t sdsAllocSize(sds s) { 127 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 128 | 129 | return sizeof(*sh) + sh->len + sh->free + 1; 130 | } 131 | 132 | /* Increment the sds length and decrements the left free space at the 133 | * end of the string accordingly to 'incr'. Also set the null term 134 | * in the new end of the string. 135 | * 136 | * This function is used in order to fix the string length after the 137 | * user calls sdsMakeRoomFor(), writes something after the end of 138 | * the current string, and finally needs to set the new length. 139 | * 140 | * Note: it is possible to use a negative increment in order to 141 | * right-trim the string. 142 | * 143 | * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the 144 | * following schema to cat bytes coming from the kernel to the end of an 145 | * sds string new things without copying into an intermediate buffer: 146 | * 147 | * oldlen = sdslen(s); 148 | * s = sdsMakeRoomFor(s, BUFFER_SIZE); 149 | * nread = read(fd, s+oldlen, BUFFER_SIZE); 150 | * ... check for nread <= 0 and handle it ... 151 | * sdsIncrLen(s, nhread); 152 | */ 153 | void sdsIncrLen(sds s, int incr) { 154 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 155 | 156 | assert(sh->free >= incr); 157 | sh->len += incr; 158 | sh->free -= incr; 159 | assert(sh->free >= 0); 160 | s[sh->len] = '\0'; 161 | } 162 | 163 | /* Grow the sds to have the specified length. Bytes that were not part of 164 | * the original length of the sds will be set to zero. */ 165 | sds sdsgrowzero(sds s, size_t len) { 166 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 167 | size_t totlen, curlen = sh->len; 168 | 169 | if (len <= curlen) return s; 170 | s = sdsMakeRoomFor(s, len - curlen); 171 | if (s == NULL) return NULL; 172 | 173 | /* Make sure added region doesn't contain garbage */ 174 | sh = (void*)(s - (sizeof(struct sdshdr))); 175 | memset(s + curlen, 0, (len - curlen + 1)); /* also set trailing \0 byte */ 176 | totlen = sh->len + sh->free; 177 | sh->len = len; 178 | sh->free = totlen - sh->len; 179 | return s; 180 | } 181 | 182 | sds sdscatlen(sds s, const void *t, size_t len) { 183 | struct sdshdr *sh; 184 | size_t curlen = sdslen(s); 185 | 186 | s = sdsMakeRoomFor(s, len); 187 | if (s == NULL) return NULL; 188 | sh = (void*)(s - (sizeof(struct sdshdr))); 189 | memcpy(s + curlen, t, len); 190 | sh->len = curlen + len; 191 | sh->free = sh->free - len; 192 | s[curlen + len] = '\0'; 193 | return s; 194 | } 195 | 196 | sds sdscat(sds s, const char *t) { 197 | return sdscatlen(s, t, strlen(t)); 198 | } 199 | 200 | sds sdscatsds(sds s, const sds t) { 201 | return sdscatlen(s, t, sdslen(t)); 202 | } 203 | 204 | sds sdscpylen(sds s, const char *t, size_t len) { 205 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 206 | size_t totlen = sh->free + sh->len; 207 | 208 | if (totlen < len) { 209 | s = sdsMakeRoomFor(s, len - sh->len); 210 | if (s == NULL) return NULL; 211 | sh = (void*)(s - (sizeof(struct sdshdr))); 212 | totlen = sh->free + sh->len; 213 | } 214 | memcpy(s, t, len); 215 | s[len] = '\0'; 216 | sh->len = len; 217 | sh->free = totlen - len; 218 | return s; 219 | } 220 | 221 | sds sdscpy(sds s, const char *t) { 222 | return sdscpylen(s, t, strlen(t)); 223 | } 224 | 225 | sds sdscatvprintf(sds s, const char *fmt, va_list ap) { 226 | va_list cpy; 227 | char *buf, *t; 228 | size_t buflen = 16; 229 | 230 | while (1) { 231 | buf = malloc(buflen); 232 | if (buf == NULL) return NULL; 233 | buf[buflen - 2] = '\0'; 234 | va_copy(cpy, ap); 235 | vsnprintf(buf, buflen, fmt, cpy); 236 | if (buf[buflen - 2] != '\0') { 237 | free(buf); 238 | buflen *= 2; 239 | continue; 240 | } 241 | break; 242 | } 243 | t = sdscat(s, buf); 244 | free(buf); 245 | return t; 246 | } 247 | 248 | sds sdscatprintf(sds s, const char *fmt, ...) { 249 | va_list ap; 250 | char *t; 251 | va_start(ap, fmt); 252 | t = sdscatvprintf(s, fmt, ap); 253 | va_end(ap); 254 | return t; 255 | } 256 | 257 | sds sdstrim(sds s, const char *cset) { 258 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 259 | char *start, *end, *sp, *ep; 260 | size_t len; 261 | 262 | sp = start = s; 263 | ep = end = s + sdslen(s) - 1; 264 | while (sp <= end && strchr(cset, *sp)) sp++; 265 | while (ep > start && strchr(cset, *ep)) ep--; 266 | len = (sp > ep) ? 0 : ((ep - sp) + 1); 267 | if (sh->buf != sp) memmove(sh->buf, sp, len); 268 | sh->buf[len] = '\0'; 269 | sh->free = sh->free + (sh->len - len); 270 | sh->len = len; 271 | return s; 272 | } 273 | 274 | sds sdsrange(sds s, int start, int end) { 275 | struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr))); 276 | size_t newlen, len = sdslen(s); 277 | 278 | if (len == 0) return s; 279 | if (start < 0) { 280 | start = len + start; 281 | if (start < 0) start = 0; 282 | } 283 | if (end < 0) { 284 | end = len + end; 285 | if (end < 0) end = 0; 286 | } 287 | newlen = (start > end) ? 0 : (end - start) + 1; 288 | if (newlen != 0) { 289 | if (start >= (signed)len) { 290 | newlen = 0; 291 | } 292 | else if (end >= (signed)len) { 293 | end = len - 1; 294 | newlen = (start > end) ? 0 : (end - start) + 1; 295 | } 296 | } 297 | else { 298 | start = 0; 299 | } 300 | if (start && newlen) memmove(sh->buf, sh->buf + start, newlen); 301 | sh->buf[newlen] = 0; 302 | sh->free = sh->free + (sh->len - newlen); 303 | sh->len = newlen; 304 | return s; 305 | } 306 | 307 | void sdstolower(sds s) { 308 | int len = sdslen(s), j; 309 | 310 | for (j = 0; j < len; j++) s[j] = tolower(s[j]); 311 | } 312 | 313 | void sdstoupper(sds s) { 314 | int len = sdslen(s), j; 315 | 316 | for (j = 0; j < len; j++) s[j] = toupper(s[j]); 317 | } 318 | 319 | int sdscmp(const sds s1, const sds s2) { 320 | size_t l1, l2, minlen; 321 | int cmp; 322 | 323 | l1 = sdslen(s1); 324 | l2 = sdslen(s2); 325 | minlen = (l1 < l2) ? l1 : l2; 326 | cmp = memcmp(s1, s2, minlen); 327 | if (cmp == 0) return l1 - l2; 328 | return cmp; 329 | } 330 | 331 | /* Split 's' with separator in 'sep'. An array 332 | * of sds strings is returned. *count will be set 333 | * by reference to the number of tokens returned. 334 | * 335 | * On out of memory, zero length string, zero length 336 | * separator, NULL is returned. 337 | * 338 | * Note that 'sep' is able to split a string using 339 | * a multi-character separator. For example 340 | * sdssplit("foo_-_bar","_-_"); will return two 341 | * elements "foo" and "bar". 342 | * 343 | * This version of the function is binary-safe but 344 | * requires length arguments. sdssplit() is just the 345 | * same function but for zero-terminated strings. 346 | */ 347 | sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) { 348 | int elements = 0, slots = 5, start = 0, j; 349 | sds *tokens; 350 | 351 | if (seplen < 1 || len < 0) return NULL; 352 | 353 | tokens = malloc(sizeof(sds)*slots); 354 | if (tokens == NULL) return NULL; 355 | 356 | if (len == 0) { 357 | *count = 0; 358 | return tokens; 359 | } 360 | for (j = 0; j < (len - (seplen - 1)); j++) { 361 | /* make sure there is room for the next element and the final one */ 362 | if (slots < elements + 2) { 363 | sds *newtokens; 364 | 365 | slots *= 2; 366 | newtokens = realloc(tokens, sizeof(sds)*slots); 367 | if (newtokens == NULL) goto cleanup; 368 | tokens = newtokens; 369 | } 370 | /* search the separator */ 371 | if ((seplen == 1 && *(s + j) == sep[0]) || (memcmp(s + j, sep, seplen) == 0)) { 372 | tokens[elements] = sdsnewlen(s + start, j - start); 373 | if (tokens[elements] == NULL) goto cleanup; 374 | elements++; 375 | start = j + seplen; 376 | j = j + seplen - 1; /* skip the separator */ 377 | } 378 | } 379 | /* Add the final element. We are sure there is room in the tokens array. */ 380 | tokens[elements] = sdsnewlen(s + start, len - start); 381 | if (tokens[elements] == NULL) goto cleanup; 382 | elements++; 383 | *count = elements; 384 | return tokens; 385 | 386 | cleanup: 387 | { 388 | int i; 389 | for (i = 0; i < elements; i++) sdsfree(tokens[i]); 390 | free(tokens); 391 | *count = 0; 392 | return NULL; 393 | } 394 | } 395 | 396 | void sdsfreesplitres(sds *tokens, int count) { 397 | if (!tokens) return; 398 | while (count--) 399 | sdsfree(tokens[count]); 400 | free(tokens); 401 | } 402 | 403 | sds sdsfromlonglong(long long value) { 404 | char buf[32], *p; 405 | unsigned long long v; 406 | 407 | v = (value < 0) ? -value : value; 408 | p = buf + 31; /* point to the last character */ 409 | do { 410 | *p-- = '0' + (v % 10); 411 | v /= 10; 412 | } while (v); 413 | if (value < 0) *p-- = '-'; 414 | p++; 415 | return sdsnewlen(p, 32 - (p - buf)); 416 | } 417 | 418 | sds sdscatrepr(sds s, const char *p, size_t len) { 419 | s = sdscatlen(s, "\"", 1); 420 | while (len--) { 421 | switch (*p) { 422 | case '\\': 423 | case '"': 424 | s = sdscatprintf(s, "\\%c", *p); 425 | break; 426 | case '\n': s = sdscatlen(s, "\\n", 2); break; 427 | case '\r': s = sdscatlen(s, "\\r", 2); break; 428 | case '\t': s = sdscatlen(s, "\\t", 2); break; 429 | case '\a': s = sdscatlen(s, "\\a", 2); break; 430 | case '\b': s = sdscatlen(s, "\\b", 2); break; 431 | default: 432 | if (isprint(*p)) 433 | s = sdscatprintf(s, "%c", *p); 434 | else 435 | s = sdscatprintf(s, "\\x%02x", (unsigned char)*p); 436 | break; 437 | } 438 | p++; 439 | } 440 | return sdscatlen(s, "\"", 1); 441 | } 442 | 443 | /* Helper function for sdssplitargs() that returns non zero if 'c' 444 | * is a valid hex digit. */ 445 | int is_hex_digit(char c) { 446 | return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || 447 | (c >= 'A' && c <= 'F'); 448 | } 449 | 450 | /* Helper function for sdssplitargs() that converts an hex digit into an 451 | * integer from 0 to 15 */ 452 | int hex_digit_to_int(char c) { 453 | switch (c) { 454 | case '0': return 0; 455 | case '1': return 1; 456 | case '2': return 2; 457 | case '3': return 3; 458 | case '4': return 4; 459 | case '5': return 5; 460 | case '6': return 6; 461 | case '7': return 7; 462 | case '8': return 8; 463 | case '9': return 9; 464 | case 'a': case 'A': return 10; 465 | case 'b': case 'B': return 11; 466 | case 'c': case 'C': return 12; 467 | case 'd': case 'D': return 13; 468 | case 'e': case 'E': return 14; 469 | case 'f': case 'F': return 15; 470 | default: return 0; 471 | } 472 | } 473 | 474 | /* Split a line into arguments, where every argument can be in the 475 | * following programming-language REPL-alike form: 476 | * 477 | * foo bar "newline are supported\n" and "\xff\x00otherstuff" 478 | * 479 | * The number of arguments is stored into *argc, and an array 480 | * of sds is returned. 481 | * 482 | * The caller should free the resulting array of sds strings with 483 | * sdsfreesplitres(). 484 | * 485 | * Note that sdscatrepr() is able to convert back a string into 486 | * a quoted string in the same format sdssplitargs() is able to parse. 487 | * 488 | * The function returns the allocated tokens on success, even when the 489 | * input string is empty, or NULL if the input contains unbalanced 490 | * quotes or closed quotes followed by non space characters 491 | * as in: "foo"bar or "foo' 492 | */ 493 | sds *sdssplitargs(const char *line, int *argc) { 494 | const char *p = line; 495 | char *current = NULL; 496 | char **vector = NULL; 497 | 498 | *argc = 0; 499 | while (1) { 500 | /* skip blanks */ 501 | while (*p && isspace(*p)) p++; 502 | if (*p) { 503 | /* get a token */ 504 | int inq = 0; /* set to 1 if we are in "quotes" */ 505 | int insq = 0; /* set to 1 if we are in 'single quotes' */ 506 | int done = 0; 507 | 508 | if (current == NULL) current = sdsempty(); 509 | while (!done) { 510 | if (inq) { 511 | if (*p == '\\' && *(p + 1) == 'x' && 512 | is_hex_digit(*(p + 2)) && 513 | is_hex_digit(*(p + 3))) 514 | { 515 | unsigned char byte; 516 | 517 | byte = (hex_digit_to_int(*(p + 2)) * 16) + 518 | hex_digit_to_int(*(p + 3)); 519 | current = sdscatlen(current, (char*)&byte, 1); 520 | p += 3; 521 | } 522 | else if (*p == '\\' && *(p + 1)) { 523 | char c; 524 | 525 | p++; 526 | switch (*p) { 527 | case 'n': c = '\n'; break; 528 | case 'r': c = '\r'; break; 529 | case 't': c = '\t'; break; 530 | case 'b': c = '\b'; break; 531 | case 'a': c = '\a'; break; 532 | default: c = *p; break; 533 | } 534 | current = sdscatlen(current, &c, 1); 535 | } 536 | else if (*p == '"') { 537 | /* closing quote must be followed by a space or 538 | * nothing at all. */ 539 | if (*(p + 1) && !isspace(*(p + 1))) goto err; 540 | done = 1; 541 | } 542 | else if (!*p) { 543 | /* unterminated quotes */ 544 | goto err; 545 | } 546 | else { 547 | current = sdscatlen(current, p, 1); 548 | } 549 | } 550 | else if (insq) { 551 | if (*p == '\\' && *(p + 1) == '\'') { 552 | p++; 553 | current = sdscatlen(current, "'", 1); 554 | } 555 | else if (*p == '\'') { 556 | /* closing quote must be followed by a space or 557 | * nothing at all. */ 558 | if (*(p + 1) && !isspace(*(p + 1))) goto err; 559 | done = 1; 560 | } 561 | else if (!*p) { 562 | /* unterminated quotes */ 563 | goto err; 564 | } 565 | else { 566 | current = sdscatlen(current, p, 1); 567 | } 568 | } 569 | else { 570 | switch (*p) { 571 | case ' ': 572 | case '\n': 573 | case '\r': 574 | case '\t': 575 | case '\0': 576 | done = 1; 577 | break; 578 | case '"': 579 | inq = 1; 580 | break; 581 | case '\'': 582 | insq = 1; 583 | break; 584 | default: 585 | current = sdscatlen(current, p, 1); 586 | break; 587 | } 588 | } 589 | if (*p) p++; 590 | } 591 | /* add the token to the vector */ 592 | vector = realloc(vector, ((*argc) + 1) * sizeof(char*)); 593 | vector[*argc] = current; 594 | (*argc)++; 595 | current = NULL; 596 | } 597 | else { 598 | /* Even on empty input string return something not NULL. */ 599 | if (vector == NULL) vector = malloc(sizeof(void*)); 600 | return vector; 601 | } 602 | } 603 | 604 | err: 605 | while ((*argc)--) 606 | sdsfree(vector[*argc]); 607 | free(vector); 608 | if (current) sdsfree(current); 609 | *argc = 0; 610 | return NULL; 611 | } 612 | 613 | /* Modify the string substituting all the occurrences of the set of 614 | * characters specified in the 'from' string to the corresponding character 615 | * in the 'to' array. 616 | * 617 | * For instance: sdsmapchars(mystring, "ho", "01", 2) 618 | * will have the effect of turning the string "hello" into "0ell1". 619 | * 620 | * The function returns the sds string pointer, that is always the same 621 | * as the input pointer since no resize is needed. */ 622 | sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) { 623 | size_t j, i, l = sdslen(s); 624 | 625 | for (j = 0; j < l; j++) { 626 | for (i = 0; i < setlen; i++) { 627 | if (s[j] == from[i]) { 628 | s[j] = to[i]; 629 | break; 630 | } 631 | } 632 | } 633 | return s; 634 | } -------------------------------------------------------------------------------- /STHTMLPP/sds.h: -------------------------------------------------------------------------------- 1 | /* SDSLib, A C dynamic strings library 2 | * 3 | * Copyright (c) 2006-2010, Salvatore Sanfilippo 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef __SDS_H 32 | #define __SDS_H 33 | 34 | #define SDS_MAX_PREALLOC (1024*1024) 35 | 36 | #include 37 | #include 38 | 39 | typedef char *sds; 40 | 41 | typedef struct sdshdr { 42 | int len; 43 | int free; 44 | char buf[]; 45 | }sdshdr; 46 | 47 | static inline size_t sdslen(const sds s) { 48 | struct sdshdr *sh = (sdshdr*)(s - (sizeof(struct sdshdr))); 49 | return sh->len; 50 | } 51 | 52 | static inline size_t sdsavail(const sds s) { 53 | struct sdshdr *sh = (sdshdr*)(s - (sizeof(struct sdshdr))); 54 | return sh->free; 55 | } 56 | 57 | sds sdsnewlen(const void *init, size_t initlen); 58 | sds sdsnew(const char *init); 59 | sds sdsempty(); 60 | size_t sdslen(const sds s); 61 | sds sdsdup(const sds s); 62 | void sdsfree(sds s); 63 | size_t sdsavail(const sds s); 64 | sds sdsgrowzero(sds s, size_t len); 65 | sds sdscatlen(sds s, const void *t, size_t len); 66 | sds sdscat(sds s, const char *t); 67 | sds sdscatsds(sds s, const sds t); 68 | sds sdscpylen(sds s, const char *t, size_t len); 69 | sds sdscpy(sds s, const char *t); 70 | 71 | sds sdscatvprintf(sds s, const char *fmt, va_list ap); 72 | #ifdef __GNUC__ 73 | sds sdscatprintf(sds s, const char *fmt, ...) 74 | __attribute__((format(printf, 2, 3))); 75 | #else 76 | sds sdscatprintf(sds s, const char *fmt, ...); 77 | #endif 78 | 79 | sds sdstrim(sds s, const char *cset); 80 | sds sdsrange(sds s, int start, int end); 81 | void sdsupdatelen(sds s); 82 | void sdsclear(sds s); 83 | int sdscmp(const sds s1, const sds s2); 84 | sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); 85 | void sdsfreesplitres(sds *tokens, int count); 86 | void sdstolower(sds s); 87 | void sdstoupper(sds s); 88 | sds sdsfromlonglong(long long value); 89 | sds sdscatrepr(sds s, const char *p, size_t len); 90 | sds *sdssplitargs(const char *line, int *argc); 91 | sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); 92 | 93 | /* Low level functions exposed to the user API */ 94 | sds sdsMakeRoomFor(sds s, size_t addlen); 95 | void sdsIncrLen(sds s, int incr); 96 | sds sdsRemoveFreeSpace(sds s); 97 | size_t sdsAllocSize(sds s); 98 | 99 | #endif -------------------------------------------------------------------------------- /STHTMLPP/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/STHTMLPP/stdafx.cpp -------------------------------------------------------------------------------- /STHTMLPP/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/STHTMLPP/stdafx.h -------------------------------------------------------------------------------- /STHTMLPP/strings.h: -------------------------------------------------------------------------------- 1 | /*Dummy file to satisfy source file dependencies on Windows platform*/ 2 | #define strcasecmp _stricmp 3 | #define strncasecmp _strnicmp 4 | #define inline __inline 5 | -------------------------------------------------------------------------------- /STHTMLPP/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/STHTMLPP/targetver.h -------------------------------------------------------------------------------- /STHTMLPP/utf8_strings.cpp: -------------------------------------------------------------------------------- 1 | #include "utf8_strings.h" 2 | 3 | 4 | litehtml::utf8_to_wchar::utf8_to_wchar(const char* val) 5 | { 6 | m_utf8 = (const byte*)val; 7 | while (true) 8 | { 9 | ucode_t wch = get_char(); 10 | if (!wch) break; 11 | m_str += wch; 12 | } 13 | } 14 | 15 | ucode_t litehtml::utf8_to_wchar::get_char() 16 | { 17 | ucode_t b1 = getb(); 18 | 19 | if (!b1) 20 | { 21 | return 0; 22 | } 23 | 24 | // Determine whether we are dealing 25 | // with a one-, two-, three-, or four- 26 | // byte sequence. 27 | if ((b1 & 0x80) == 0) 28 | { 29 | // 1-byte sequence: 000000000xxxxxxx = 0xxxxxxx 30 | return b1; 31 | } 32 | else if ((b1 & 0xe0) == 0xc0) 33 | { 34 | // 2-byte sequence: 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx 35 | ucode_t r = (b1 & 0x1f) << 6; 36 | r |= get_next_utf8(getb()); 37 | return r; 38 | } 39 | else if ((b1 & 0xf0) == 0xe0) 40 | { 41 | // 3-byte sequence: zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx 42 | ucode_t r = (b1 & 0x0f) << 12; 43 | r |= get_next_utf8(getb()) << 6; 44 | r |= get_next_utf8(getb()); 45 | return r; 46 | } 47 | else if ((b1 & 0xf8) == 0xf0) 48 | { 49 | // 4-byte sequence: 11101110wwwwzzzzyy + 110111yyyyxxxxxx 50 | // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 51 | // (uuuuu = wwww + 1) 52 | int b2 = get_next_utf8(getb()); 53 | int b3 = get_next_utf8(getb()); 54 | int b4 = get_next_utf8(getb()); 55 | return ((b1 & 7) << 18) | ((b2 & 0x3f) << 12) | 56 | ((b3 & 0x3f) << 6) | (b4 & 0x3f); 57 | } 58 | 59 | //bad start for UTF-8 multi-byte sequence 60 | return '?'; 61 | } 62 | 63 | litehtml::wchar_to_utf8::wchar_to_utf8(const wchar_t* val) 64 | { 65 | unsigned int code; 66 | for (int i = 0; val[i]; i++) 67 | { 68 | code = val[i]; 69 | if (code <= 0x7F) 70 | { 71 | m_str += (char)code; 72 | } 73 | else if (code <= 0x7FF) 74 | { 75 | m_str += (code >> 6) + 192; 76 | m_str += (code & 63) + 128; 77 | } 78 | else if (0xd800 <= code && code <= 0xdfff) 79 | { 80 | //invalid block of utf8 81 | } 82 | else if (code <= 0xFFFF) 83 | { 84 | m_str += (code >> 12) + 224; 85 | m_str += ((code >> 6) & 63) + 128; 86 | m_str += (code & 63) + 128; 87 | } 88 | else if (code <= 0x10FFFF) 89 | { 90 | m_str += (code >> 18) + 240; 91 | m_str += ((code >> 12) & 63) + 128; 92 | m_str += ((code >> 6) & 63) + 128; 93 | m_str += (code & 63) + 128; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /STHTMLPP/utf8_strings.h: -------------------------------------------------------------------------------- 1 | #ifndef LH_UTF8_STRINGS_H 2 | #define LH_UTF8_STRINGS_H 3 | 4 | typedef unsigned char byte; 5 | typedef unsigned int ucode_t; 6 | typedef wchar_t tchar_t; 7 | #include 8 | 9 | using namespace std; 10 | namespace litehtml 11 | { 12 | class utf8_to_wchar 13 | { 14 | const byte* m_utf8; 15 | std::wstring m_str; 16 | public: 17 | utf8_to_wchar(const char* val); 18 | operator const wchar_t*() const 19 | { 20 | return m_str.c_str(); 21 | } 22 | private: 23 | ucode_t getb() 24 | { 25 | if (!(*m_utf8)) return 0; 26 | return *m_utf8++; 27 | } 28 | ucode_t get_next_utf8(ucode_t val) 29 | { 30 | return (val & 0x3f); 31 | } 32 | ucode_t get_char(); 33 | }; 34 | 35 | class wchar_to_utf8 36 | { 37 | std::string m_str; 38 | public: 39 | wchar_to_utf8(const wchar_t* val); 40 | operator const char*() const 41 | { 42 | return m_str.c_str(); 43 | } 44 | }; 45 | 46 | #ifdef LITEHTML_UTF8 47 | #define litehtml_from_utf8(str) str 48 | #define litehtml_to_utf8(str) str 49 | #define litehtml_from_wchar(str) wchar_to_utf8(str) 50 | #else 51 | #define litehtml_from_utf8(str) utf8_to_wchar(str) 52 | #define litehtml_from_wchar(str) str 53 | #define litehtml_to_utf8(str) wchar_to_utf8(str) 54 | #endif 55 | } 56 | 57 | #endif // LH_UTF8_STRINGS_H -------------------------------------------------------------------------------- /img/123.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/img/123.PNG -------------------------------------------------------------------------------- /img/456.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1694439208/gumbo-Elss/abd193029bf2747f9882889dd115b5e759911ac2/img/456.PNG --------------------------------------------------------------------------------