├── CMakeLists.txt
├── LICENSE
├── README.md
├── bsdiff
├── bspatch.c
├── bspatch.h
├── vFile.c
└── vFile.h
├── conanfile.py
├── lib
├── crc32.c
├── crc32.h
├── mylib.c
└── mylib.h
├── lzma
├── 7zFile.c
├── 7zFile.h
├── 7zTypes.h
├── Compiler.h
├── LzFind.c
├── LzFind.h
├── LzHash.h
├── LzmaDec.c
├── LzmaDec.h
├── LzmaEnc.c
├── LzmaEnc.h
├── Precomp.h
├── lzma_decompress.c
└── lzma_decompress.h
└── user
├── bs_type.h
├── bs_user_interface.c
└── bs_user_interface.h
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.15)
2 |
3 | ############################################################
4 | # 用户设置部分
5 | ############################################################
6 | set(PROJECT_USER_NAME bsdiff_upgrade)
7 | set(USER_LANGUAGES C)#设置代码中的所有语言类型,如C CXX ASM
8 | # set(PACKAGE_LIST cmsis-dsp)#本包依赖的包
9 | ############################################################
10 | # Create a library
11 | ############################################################
12 | # 查找当前目录下的所有源文件并将名称保存到 DIR_LIB_SRCS 变量
13 | file(GLOB_RECURSE DIR_LIB_SRCS
14 | "${CMAKE_CURRENT_LIST_DIR}/*.c"
15 | )
16 | #搜索后排除不编译的特定文件
17 | # list(REMOVE_ITEM DIR_LIB_SRCS
18 | # "${CMAKE_CURRENT_LIST_DIR}/Source/TransformFunctions/TransformFunctionsF16.c"
19 | # )
20 |
21 | #设置交叉编译环境,必备,否则会出现丢失libxxx的情况
22 | set(CMAKE_SYSTEM_NAME Generic)
23 | set(CMAKE_SYSTEM_PROCESSOR arm)
24 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
25 |
26 | # linux
27 | if(CMAKE_HOST_UNIX)
28 | set(CMAKE_C_COMPILER_WORKS ON)
29 | set(CMAKE_CXX_COMPILER_WORKS ON)
30 | set(CMAKE_ASM_COMPILER_WORKS ON)
31 | endif()
32 |
33 | project(${PROJECT_USER_NAME} LANGUAGES ${USER_LANGUAGES})
34 |
35 | #取DIR_LIB_SRCS中的第一个文件获取文件夹
36 | list(GET DIR_LIB_SRCS 0 FIRST_SRC)
37 | get_filename_component(DIR_LIB_SRCS_DIR ${FIRST_SRC} DIRECTORY)
38 | #获取conan路径
39 | string(REGEX MATCH "([^/]+/[^/]+/[^/]+/[^/]+)" DIR_LIB_SRCS_DIR_CONAN ${DIR_LIB_SRCS_DIR})
40 |
41 | #设置在python基础上增加的编译选项,重点是优化等级
42 | if ("${CMAKE_C_COMPILER_ID}" STREQUAL "IAR")# using IAR
43 | string(APPEND C_FLAGS " -Oh")
44 | string(APPEND CXX_FLAGS " -Oh")
45 | elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "ARMCC")# using ARMCC
46 | string(APPEND C_FLAGS " -O3")
47 | string(APPEND CXX_FLAGS " -O3")
48 | elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")# using GNU
49 | string(APPEND C_FLAGS " -O2 -ffile-prefix-map=${DIR_LIB_SRCS_DIR_CONAN}=.")
50 | string(APPEND CXX_FLAGS " -O2 -ffile-prefix-map=${DIR_LIB_SRCS_DIR_CONAN}=.")
51 | endif()
52 |
53 | if(CMAKE_BUILD_TYPE STREQUAL "Debug")
54 | message(Build type is Debug.)
55 | elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
56 | string(APPEND C_FLAGS " -DNDEBUG")
57 | message(Build type is Release.)
58 | endif()
59 |
60 | message(${CMAKE_C_COMPILER_ID})
61 |
62 | #优化等级
63 | set(CMAKE_C_FLAGS_DEBUG "" CACHE STRING INTERNAL FORCE)
64 | set(CMAKE_C_FLAGS_RELEASE "" CACHE STRING INTERNAL FORCE)
65 |
66 | # 当用了std LIB库的时候,需要处理包含编译器头文件路径
67 | if ("${CMAKE_C_COMPILER_ID}" STREQUAL "IAR")# using IAR
68 | #Set DLib_Config
69 | get_filename_component(COMPILER_DIR ${CMAKE_C_COMPILER} DIRECTORY)
70 | get_filename_component(COMPILER_DIR ${COMPILER_DIR} DIRECTORY)
71 | set(DLIB_CONFIG ${COMPILER_DIR}/inc/c/DLib_Config_Full.h)
72 |
73 | #linux下编译需要将路径转换为windows路径
74 | if(CMAKE_HOST_UNIX)
75 | execute_process (
76 | COMMAND wslpath -w ${DLIB_CONFIG}
77 | OUTPUT_VARIABLE DLIB_CONFIG
78 | )
79 | string(REPLACE "\n" "" DLIB_CONFIG ${DLIB_CONFIG}) #必须去掉换行符
80 | endif()
81 | #最终结果
82 | message(${DLIB_CONFIG})
83 | string(APPEND C_FLAGS " --dlib_config \"${DLIB_CONFIG}\"")
84 | string(APPEND CXX_FLAGS " --dlib_config \"${DLIB_CONFIG}\"")
85 | endif()
86 |
87 | SET(CMAKE_C_FLAGS ${C_FLAGS})
88 | SET(CMAKE_CXX_FLAGS ${CXX_FLAGS})
89 | SET(CMAKE_ASM_FLAGS ${ASM_FLAGS})
90 |
91 | #Generate the static library from the library sources
92 | add_library(${PROJECT_NAME} STATIC ${DIR_LIB_SRCS})
93 |
94 | FOREACH(PACKAGE_LIST ${PACKAGE_LIST})
95 | message("Current search ${PACKAGE_LIST} package...") #循环取值
96 | find_package(${PACKAGE_LIST} CONFIG REQUIRED)
97 | # Global approach
98 | if(${PACKAGE_LIST}_FOUND)
99 | message(${${PACKAGE_LIST}_INCLUDE_DIRS})
100 | target_include_directories(${PROJECT_NAME} PRIVATE ${${PACKAGE_LIST}_INCLUDE_DIRS})
101 | target_link_libraries(${PROJECT_NAME}
102 | PRIVATE
103 | ${${PACKAGE_LIST}_LIB_DIRS_RELEASE}/lib${PACKAGE_LIST}.a
104 | )
105 | endif()
106 | ENDFOREACH(PACKAGE_LIST)
107 |
108 | #head file
109 | file(GLOB_RECURSE Head_Files
110 | "${CMAKE_CURRENT_SOURCE_DIR}/*.h"
111 | )
112 | #查找头文件路径
113 | FOREACH(Head_Files ${Head_Files})
114 | string(REGEX REPLACE "(.*/)" "" HEAD_FILE ${Head_Files})#匹配文件名
115 | string(REPLACE ${HEAD_FILE} "" HEAD_FILE_DIR ${Head_Files})#去除文件名
116 | list(APPEND HEAD_INCLUDE_DIR ${HEAD_FILE_DIR})#添加到列表
117 | ENDFOREACH(Head_Files)
118 | #路径去重
119 | list(REMOVE_DUPLICATES HEAD_INCLUDE_DIR)
120 | #指定编译时包含的头文件路径
121 | target_include_directories(${PROJECT_NAME}
122 | PUBLIC
123 | ${HEAD_INCLUDE_DIR}
124 | )
125 | message(${CMAKE_CURRENT_SOURCE_DIR})
126 | #安装所有头文件
127 | install(FILES ${Head_Files} DESTINATION include)
128 | install(TARGETS ${PROJECT_NAME})
129 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU Affero General Public License is a free, copyleft license for
11 | software and other kinds of works, specifically designed to ensure
12 | cooperation with the community in the case of network server software.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | our General Public Licenses are intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users.
19 |
20 | When we speak of free software, we are referring to freedom, not
21 | price. Our General Public Licenses are designed to make sure that you
22 | have the freedom to distribute copies of free software (and charge for
23 | them if you wish), that you receive source code or can get it if you
24 | want it, that you can change the software or use pieces of it in new
25 | free programs, and that you know you can do these things.
26 |
27 | Developers that use our General Public Licenses protect your rights
28 | with two steps: (1) assert copyright on the software, and (2) offer
29 | you this License which gives you legal permission to copy, distribute
30 | and/or modify the software.
31 |
32 | A secondary benefit of defending all users' freedom is that
33 | improvements made in alternate versions of the program, if they
34 | receive widespread use, become available for other developers to
35 | incorporate. Many developers of free software are heartened and
36 | encouraged by the resulting cooperation. However, in the case of
37 | software used on network servers, this result may fail to come about.
38 | The GNU General Public License permits making a modified version and
39 | letting the public access it on a server without ever releasing its
40 | source code to the public.
41 |
42 | The GNU Affero General Public License is designed specifically to
43 | ensure that, in such cases, the modified source code becomes available
44 | to the community. It requires the operator of a network server to
45 | provide the source code of the modified version running there to the
46 | users of that server. Therefore, public use of a modified version, on
47 | a publicly accessible server, gives the public access to the source
48 | code of the modified version.
49 |
50 | An older license, called the Affero General Public License and
51 | published by Affero, was designed to accomplish similar goals. This is
52 | a different license, not a version of the Affero GPL, but Affero has
53 | released a new version of the Affero GPL which permits relicensing under
54 | this license.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | TERMS AND CONDITIONS
60 |
61 | 0. Definitions.
62 |
63 | "This License" refers to version 3 of the GNU Affero General Public License.
64 |
65 | "Copyright" also means copyright-like laws that apply to other kinds of
66 | works, such as semiconductor masks.
67 |
68 | "The Program" refers to any copyrightable work licensed under this
69 | License. Each licensee is addressed as "you". "Licensees" and
70 | "recipients" may be individuals or organizations.
71 |
72 | To "modify" a work means to copy from or adapt all or part of the work
73 | in a fashion requiring copyright permission, other than the making of an
74 | exact copy. The resulting work is called a "modified version" of the
75 | earlier work or a work "based on" the earlier work.
76 |
77 | A "covered work" means either the unmodified Program or a work based
78 | on the Program.
79 |
80 | To "propagate" a work means to do anything with it that, without
81 | permission, would make you directly or secondarily liable for
82 | infringement under applicable copyright law, except executing it on a
83 | computer or modifying a private copy. Propagation includes copying,
84 | distribution (with or without modification), making available to the
85 | public, and in some countries other activities as well.
86 |
87 | To "convey" a work means any kind of propagation that enables other
88 | parties to make or receive copies. Mere interaction with a user through
89 | a computer network, with no transfer of a copy, is not conveying.
90 |
91 | An interactive user interface displays "Appropriate Legal Notices"
92 | to the extent that it includes a convenient and prominently visible
93 | feature that (1) displays an appropriate copyright notice, and (2)
94 | tells the user that there is no warranty for the work (except to the
95 | extent that warranties are provided), that licensees may convey the
96 | work under this License, and how to view a copy of this License. If
97 | the interface presents a list of user commands or options, such as a
98 | menu, a prominent item in the list meets this criterion.
99 |
100 | 1. Source Code.
101 |
102 | The "source code" for a work means the preferred form of the work
103 | for making modifications to it. "Object code" means any non-source
104 | form of a work.
105 |
106 | A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 |
111 | The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form. A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 |
122 | The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities. However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work. For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 |
135 | The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 |
139 | The Corresponding Source for a work in source code form is that
140 | same work.
141 |
142 | 2. Basic Permissions.
143 |
144 | All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met. This License explicitly affirms your unlimited
147 | permission to run the unmodified Program. The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work. This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 |
152 | You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force. You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright. Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 |
163 | Conveying under any other circumstances is permitted solely under
164 | the conditions stated below. Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 |
167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 |
169 | No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 |
175 | When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 |
183 | 4. Conveying Verbatim Copies.
184 |
185 | You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 |
193 | You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 |
196 | 5. Conveying Modified Source Versions.
197 |
198 | You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 |
202 | a) The work must carry prominent notices stating that you modified
203 | it, and giving a relevant date.
204 |
205 | b) The work must carry prominent notices stating that it is
206 | released under this License and any conditions added under section
207 | 7. This requirement modifies the requirement in section 4 to
208 | "keep intact all notices".
209 |
210 | c) You must license the entire work, as a whole, under this
211 | License to anyone who comes into possession of a copy. This
212 | License will therefore apply, along with any applicable section 7
213 | additional terms, to the whole of the work, and all its parts,
214 | regardless of how they are packaged. This License gives no
215 | permission to license the work in any other way, but it does not
216 | invalidate such permission if you have separately received it.
217 |
218 | d) If the work has interactive user interfaces, each must display
219 | Appropriate Legal Notices; however, if the Program has interactive
220 | interfaces that do not display Appropriate Legal Notices, your
221 | work need not make them do so.
222 |
223 | A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit. Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 |
233 | 6. Conveying Non-Source Forms.
234 |
235 | You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 |
240 | a) Convey the object code in, or embodied in, a physical product
241 | (including a physical distribution medium), accompanied by the
242 | Corresponding Source fixed on a durable physical medium
243 | customarily used for software interchange.
244 |
245 | b) Convey the object code in, or embodied in, a physical product
246 | (including a physical distribution medium), accompanied by a
247 | written offer, valid for at least three years and valid for as
248 | long as you offer spare parts or customer support for that product
249 | model, to give anyone who possesses the object code either (1) a
250 | copy of the Corresponding Source for all the software in the
251 | product that is covered by this License, on a durable physical
252 | medium customarily used for software interchange, for a price no
253 | more than your reasonable cost of physically performing this
254 | conveying of source, or (2) access to copy the
255 | Corresponding Source from a network server at no charge.
256 |
257 | c) Convey individual copies of the object code with a copy of the
258 | written offer to provide the Corresponding Source. This
259 | alternative is allowed only occasionally and noncommercially, and
260 | only if you received the object code with such an offer, in accord
261 | with subsection 6b.
262 |
263 | d) Convey the object code by offering access from a designated
264 | place (gratis or for a charge), and offer equivalent access to the
265 | Corresponding Source in the same way through the same place at no
266 | further charge. You need not require recipients to copy the
267 | Corresponding Source along with the object code. If the place to
268 | copy the object code is a network server, the Corresponding Source
269 | may be on a different server (operated by you or a third party)
270 | that supports equivalent copying facilities, provided you maintain
271 | clear directions next to the object code saying where to find the
272 | Corresponding Source. Regardless of what server hosts the
273 | Corresponding Source, you remain obligated to ensure that it is
274 | available for as long as needed to satisfy these requirements.
275 |
276 | e) Convey the object code using peer-to-peer transmission, provided
277 | you inform other peers where the object code and Corresponding
278 | Source of the work are being offered to the general public at no
279 | charge under subsection 6d.
280 |
281 | A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 |
285 | A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling. In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage. For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product. A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 |
298 | "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source. The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 |
306 | If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information. But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 |
317 | The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed. Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 |
325 | Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 |
331 | 7. Additional Terms.
332 |
333 | "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law. If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 |
342 | When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it. (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.) You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 |
349 | Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 |
353 | a) Disclaiming warranty or limiting liability differently from the
354 | terms of sections 15 and 16 of this License; or
355 |
356 | b) Requiring preservation of specified reasonable legal notices or
357 | author attributions in that material or in the Appropriate Legal
358 | Notices displayed by works containing it; or
359 |
360 | c) Prohibiting misrepresentation of the origin of that material, or
361 | requiring that modified versions of such material be marked in
362 | reasonable ways as different from the original version; or
363 |
364 | d) Limiting the use for publicity purposes of names of licensors or
365 | authors of the material; or
366 |
367 | e) Declining to grant rights under trademark law for use of some
368 | trade names, trademarks, or service marks; or
369 |
370 | f) Requiring indemnification of licensors and authors of that
371 | material by anyone who conveys the material (or modified versions of
372 | it) with contractual assumptions of liability to the recipient, for
373 | any liability that these contractual assumptions directly impose on
374 | those licensors and authors.
375 |
376 | All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10. If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term. If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 |
386 | If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 |
391 | Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 |
395 | 8. Termination.
396 |
397 | You may not propagate or modify a covered work except as expressly
398 | provided under this License. Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 |
403 | However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 |
410 | Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 |
417 | Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License. If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 |
423 | 9. Acceptance Not Required for Having Copies.
424 |
425 | You are not required to accept this License in order to receive or
426 | run a copy of the Program. Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance. However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work. These actions infringe copyright if you do
431 | not accept this License. Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 |
434 | 10. Automatic Licensing of Downstream Recipients.
435 |
436 | Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License. You are not responsible
439 | for enforcing compliance by third parties with this License.
440 |
441 | An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations. If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 |
451 | You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License. For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 |
459 | 11. Patents.
460 |
461 | A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based. The
463 | work thus licensed is called the contributor's "contributor version".
464 |
465 | A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version. For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 |
475 | Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 |
480 | In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement). To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 |
487 | If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients. "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 |
501 | If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 |
509 | A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License. You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 |
524 | Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 |
528 | 12. No Surrender of Others' Freedom.
529 |
530 | If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License. If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all. For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 |
540 | 13. Remote Network Interaction; Use with the GNU General Public License.
541 |
542 | Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software. This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 |
553 | Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work. The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 |
561 | 14. Revised Versions of this License.
562 |
563 | The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time. Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 |
568 | Each version is given a distinguishing version number. If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation. If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 |
577 | If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 |
582 | Later license versions may give you additional or different
583 | permissions. However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 |
587 | 15. Disclaimer of Warranty.
588 |
589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 |
598 | 16. Limitation of Liability.
599 |
600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 |
610 | 17. Interpretation of Sections 15 and 16.
611 |
612 | If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 |
619 | END OF TERMS AND CONDITIONS
620 |
621 | How to Apply These Terms to Your New Programs
622 |
623 | If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 |
627 | To do so, attach the following notices to the program. It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 |
632 |
633 | Copyright (C)
634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published
637 | by the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | 适用于嵌入式单片机的差分升级库,通用所有单片机,如stm32、华大、复旦微、瑞萨等。适合嵌入式的差分升级又叫增量升级,顾名思义就是通过差分算法将源版本与目标版本之间差异的部分提取出来制作成差分包,然后在设备通过还原算法将差异部分在源版本上进行还原从而升级成目标版本的过程。 差分升级方案不仅可以节省MCU内部的资源空间、还可以节省下载流程及下载和升级过程中的功耗。技术支持vx 18219255930,qq791314247
4 |
5 | 我将更详细的教程内容放在了我的博客:
6 |
7 | [代码说明:https://blog.csdn.net/qq_35333978/article/details/128211763?spm=1001.2014.3001.5501](https://blog.csdn.net/qq_35333978/article/details/128211763?spm=1001.2014.3001.5501)
8 |
9 | PS:很多人调不通99%都是因为申请内存那里有问题,要么malloc是自己写的、移植的有问题,要么就是给的堆内存不够。该套源码很多人用了很多工程都没问题的,基本无bug,如果调不通,注意以下几点:
10 |
11 | 1. 可以先用malloc测试,堆内存给20k以上,如果想缩减也是可以,需要修改源码每次还原的长度小一点,目前每次还原1k。
12 | 2. 检查堆、栈,如果调不通,可以先给比较大的值测试,基本不是堆就是栈的问题,源码是没有问题的,大量人测试过的。
13 |
14 | # 修改日志
15 |
16 | V1.0.1:
17 |
18 | 1,增加CMakeList.txt和conanfile.py文件,可以直接生成conan库,用不上conan库的不用关心这两个文件,删除即可
19 |
20 | 2,修改动态内存申请接口,从宏定义的方式升级为注册接口,宏的方式用户始终得修改代码,新版注册的方式,整个代码用户完全不用修改,注册的例子如下:
21 |
22 | ```
23 | /**
24 | * @brief Initializes the upgrade module.
25 | *
26 | * This function sets up the necessary function pointers and registers them with the
27 | * bs_user_func_register() function. It assigns the xmq25qxx_write() function to the
28 | * bs_flash_write function pointer, and assigns the pvPortMalloc() and vPortFree()
29 | * functions to the bs_malloc and bs_free function pointers respectively.
30 | */
31 | void UpgradeInit(void)
32 | {
33 | bs_user_interface bsFunc;
34 |
35 | bsFunc.bs_flash_write = xmq25qxxWrite;
36 | bsFunc.bs_malloc = (bs_malloc_func)pvPortMalloc;
37 | bsFunc.bs_free = vPortFree;
38 | bs_user_func_register(&bsFunc);
39 | }
40 | ```
41 |
42 | 3,该版本整体修改没有动任何逻辑,只是优化了接口
43 |
44 |
45 | # 详细介绍
46 |
47 | # 1. 什么是差分/增量升级?
48 |
49 | 借用网上的介绍:适合嵌入式的差分升级又叫增量升级,顾名思义就是通过差分算法将源版本与目标版本之间差异的部分提取出来制作成差分包,然后在设备通过还原算法将差异部分在源版本上进行还原从而升级成目标版本的过程。 差分升级方案不仅可以节省MCU内部的资源空间、还可以节省下载流程及下载和升级过程中的功耗。
50 |
51 | 也就是说,差分升级是拿以前旧设备内的bin,和当前新版本的bin用某种算法算出他们的差异部分,然后在借助压缩算法,生产一个极其小的差分包,然后将这个差分包下载到设备中,设备在根据解压算法、差分还原算法,生产一个完整的新版本bin,然后将这个新版本bin刷到执行区执行代码。
52 |
53 | 差分升级一般来说,可以极大的减少下载量,特别是对于嵌入式STM32等单片机来说,可以极大的减少维护成本,因为嵌入式设备的升级维护一般都是空中ota升级,比如蓝牙、红外等,下载速度受到波特率、包长等限制,更新固件包非常的慢,而差分升级可以让下载的过程极大的缩小。正常的维护版本,即使改的再多,生成的差分包bin理论上在原bin的5%左右,比如一个300k的bin,改的很多的情况下差分包也不过15k左右,而我实际测试,版本维护平均都在5~10k左右。
54 |
55 | # 2. 差分升级实现原理
56 |
57 | 差分升级过程:
58 |
59 | 1. 使用旧版本bin文件和新版本bin文件制作差分包
60 | 2. 将差分包下载到设备内
61 | 3. 设备使用差分算法还原出新版本bin
62 | 4. 设备将新版本bin进行crc验证后刷到代码执行区
63 | 5. 设备重启并以新版本运行
64 |
65 | 在过程中有2个关键点:
66 |
67 | **第一:如何使用旧版本bin****文件和新版本bin****文件制作差分包?**
68 |
69 | 该过程我们使用稳定的开源差分算法bsdiff+lzma生成差分包,该算法被大量使用,稳定安全,并且我们已在项目中批量使用,经过长时间的验证无任何问题。一般来说,该过程都是使用上位机来完成,嵌入式设备无需关心,我们已经做好了上位机软件,可以供大家随意使用,稍后会进行介绍。
70 |
71 | **第二:设备收到差分包后如何还原出新版本的bin****文件?**
72 |
73 | 该过程就是我们要讲解的重点过程,相对应的,嵌入式设备中,我们依然使用开源差分算法bsdiff+lzma来还原新版本文件,代码全开源,并且我已做成了库、抽象出了极简的接口,移植起来费不了多少功夫,基本是市场上所有的单片机如stm32、瑞萨、华大、复旦微等都可以使用,但是有内存限制,要求ram至少要10k以上,然后是该库本身的消耗大概是5k的rom。
74 |
75 | # 3. 关键点一:差分包制作过程
76 |
77 | 对于差分包的制作,我已经开发好了上位机软件,界面如下图所示:
78 | 
79 | 上位机这边主要实现使用开源算法bsdiff制作旧版本bin和新版本bin的差分包,然后在使用lzma压缩算法来压缩差分包,最终生成一个差分bin,使用方法上位机界面提示的很清楚,最终效果如下图所示:
80 | 
81 | 下载链接:
82 |
83 | 链接:[https://pan.baidu.com/s/1nBpftim8OCUI3i32sP3eOA?pwd=diff ](https://pan.baidu.com/s/1nBpftim8OCUI3i32sP3eOA?pwd=diff)
84 |
85 | 提取码:diff
86 |
87 | # 4. 关键点二:嵌入式设备中差分算法库的移植(还原差分包)
88 |
89 | ## 4.1. 移植开关算法库代码
90 |
91 | 整体代码如下图所示:
92 | 
93 | 如上图所示,99%的代码用户都不用去关心,用户只需要提供一个flash写入接口即可,也就是该库给定用户flash地址、数据内容指针、数据内容长度,用户将该段数据写入到flash即可,移植起来特别简单,花不了几分钟的功夫,这也是我花大力气抽象接口的原因。
94 |
95 | ## 4.2. 使用该库的流程
96 |
97 | ### 4.2.1. 使用库的接口
98 |
99 | 对于整个库的代码,我们只需要关心一个接口iap_patch,iap_patch在文件”bs_user_func.h”中。
100 | 
101 |
102 | 该接口介绍也比较清晰,差分包的还原,只需要调用这一个接口即可。
103 |
104 | ```c
105 | /**
106 | * @brief 用户使用差分升级时唯一需要关心的接口
107 | *
108 | * @param old 设备中执行区代码所在的地址,用户可指定flash执行区的地址,方便算法读出来当前
109 | * 运行中的代码
110 | * @param oldsize 设备中执行区代码的长度,用户可在差分包bin头获取
111 | * @param patch 设备中已经下载的差分包所在的flash地址,或者ram地址,只要能让算法读出来即可
112 | * 注意,下载的差分包自带image_header_t格式的文件头,真正的差分包需要偏
113 | * 移sizeof(image_header_t)的长度
114 | * @param patchsize 设备中已经下载的差分包的长度,用户可在差分包bin头获取
115 | * @param newfile 新文件的大小,用户需填入新版本bin的长度,用户亦可以差分包bin头获取
116 | * @return int 然后错误码,0成功,1失败
117 | */
118 | extern int iap_patch(const uint8_t* old, uint32_t oldsize, const uint8_t* patch,
119 | uint32_t patchsize, uint32_t newfile);
120 | ```
121 |
122 | 另外,使用该接口还原时所需要的一些信息可以在差分包文件头中获取,上位机在制作差分包时,会自动在差分包的bin头加上64字节的文件头,以便于告诉嵌入式设备旧/新版本bin文件的CRC校验、长度等信息。所以用户在收到差分包头时,偏移掉这64个字节的文件头的地址才是需要给到iap_patch接口的真正的bin文件。文件头格式如下代码,用户只需要关心中文注释的部分,其余的都是预留的信息。
123 |
124 | ```c
125 | /* 差分包制作时自带的文件头信息,用户只需要关心中文注释的部分 */
126 | typedef struct image_header
127 | {
128 | uint32_t ih_magic; /* Image Header Magic Number */
129 | uint32_t ih_hcrc; /* Image Header CRC Checksum 差分包包头校验 */
130 | uint32_t ih_time; /* Image Creation Timestamp */
131 | uint32_t ih_size; /* Image Data Size 差分包的大小 */
132 | uint32_t ih_load; /* Data Load Address 上一版本旧文件的大小 */
133 | uint32_t ih_ep; /* Entry Point Address 要升级的新文件的大小 */
134 | uint32_t ih_dcrc; /* Image Data CRC Checksum 新文件的CRC */
135 | uint8_t ih_os; /* Operating System */
136 | uint8_t ih_arch; /* CPU architecture */
137 | uint8_t ih_type; /* Image Type */
138 | uint8_t ih_comp; /* Compression Type */
139 | uint8_t ih_name[IH_NMLEN]; /* Image Name */
140 | uint32_t ih_ocrc; /* Old Image Data CRC Checksum 上一版本旧文件的CRC */
141 | } image_header_t;
142 | /* 差分包制作时自带的文件头信息,用户只需要关心中文注释的部分 */
143 | ```
144 |
145 | ### 4.2.2. 接口使用例子
146 |
147 | 我截取一段我工程中的代码来讲解如何使用该接口还原出新版本bin文件:
148 |
149 | ```c
150 | 1#ifdef BSDIFF_UPGRADE
151 | 2 image_header_t recv_head;
152 | 3 uint32_t recv_hcrc; /* 接收到的文件头CRC */
153 | 4 uint32_t calculation_crc; /* 计算出来的文件头CRC */
154 | 5 uint32_t spi_flash_addr = UPGRADE_PROGRAM_ADDR;
155 | 6
156 | 7 memcpy(&recv_head, (uint8_t *)APPLICATION_A, sizeof(image_header_t));
157 | 8 recv_hcrc = BigtoLittle32(recv_head.ih_hcrc);
158 | 9 recv_head.ih_hcrc = 0;
159 | 10 calculation_crc = crc32((uint8_t *)&recv_head, sizeof(image_header_t));
160 | 11
161 | 12 if (recv_hcrc == calculation_crc)
162 | 13 {
163 | 14 recv_head.ih_hcrc = recv_hcrc;
164 | 15 recv_head.ih_time = BigtoLittle32(recv_head.ih_time);
165 | 16 recv_head.ih_size = BigtoLittle32(recv_head.ih_size);
166 | 17 recv_head.ih_dcrc = BigtoLittle32(recv_head.ih_dcrc);
167 | 18 recv_head.ih_ocrc = BigtoLittle32(recv_head.ih_ocrc);
168 | 19 /* 差分升级包 */
169 | 20 recv_head.ih_hcrc = calculation_crc;
170 | 21 if (crc32((uint8_t *)APPLICATION_RUN, recv_head.ih_load) != recv_head.ih_ocrc)
171 | 22 {
172 | 23 APP_ERR_PRINT("file oldcrc err,calcrc:0X%08X, ih_oldbin_crc:0X%08X,",
173 | 24 crc32((uint8_t *)APPLICATION_RUN,
174 | 25 recv_head.ih_load), recv_head.ih_ocrc);
175 | 26 goto bsdiff_out;
176 | 27 }
177 | 28 RTOS_LOCK();
178 | 29 disable_task_monitoring(ALL_TASK_RUNFLAG_BIT, true);
179 | 30 // flash_erase_sector(UPGRADE_PROGRAM_ADDR, UPGRADE_PROGRAM_PAGE);
180 | 31 recv_hcrc = iap_patch((uint8_t *)APPLICATION_RUN, recv_head.ih_load,
181 | 32 (uint8_t *)(APPLICATION_A + sizeof(image_header_t)),
182 | 33 recv_head.ih_size, UPGRADE_PROGRAM_ADDR);
183 | 34 if (recv_hcrc != recv_head.ih_ep)
184 | 35 {
185 | 36 APP_ERR_PRINT("iap_patch len err.");
186 | 37 APP_ERR_PRINT("iap_patch len: %lu, new_len: %lu", recv_hcrc, recv_head.ih_ep);
187 | 38 goto bsdiff_out;
188 | 39 }
189 | 40 if (erase_program(APPLICATION_A))
190 | 41 {
191 | 42 APP_ERR_PRINT("I erase program failed.");
192 | 43 goto bsdiff_out;
193 | 44 }
194 | 45
195 | 46 current_flash_write_addr = APPLICATION_A;
196 | 47 for (uint32_t i = 0; i < (recv_head.ih_ep / 1024); i++)
197 | 48 {
198 | 49 xmq25qxx_read(spi_flash_addr, spi_read_cache, 1024);
199 | 50 if (xflash_write(current_flash_write_addr, spi_read_cache, 1024))
200 | 51 {
201 | 52 APP_ERR_PRINT("I write program failed.");
202 | 53 goto bsdiff_out;
203 | 54 }
204 | 55 spi_flash_addr += 1024;
205 | 56 current_flash_write_addr += 1024;
206 | 57 APP_PRINT("current_flash_write_addr: 0X%08X", current_flash_write_addr);
207 | 58 }
208 | 59 if (recv_head.ih_ep % 1024 != 0)
209 | 60 {
210 | 61 memset(spi_read_cache, 0XFF, 1024);
211 | 62 xmq25qxx_read(spi_flash_addr, spi_read_cache, recv_head.ih_ep % 1024);
212 | 63
213 | 64 if (xflash_write(current_flash_write_addr, spi_read_cache, 1024))
214 | 65 {
215 | 66 APP_ERR_PRINT("I write program failed.");
216 | 67 goto bsdiff_out;
217 | 68 }
218 | 69 }
219 | 70 if (crc32((uint8_t *)APPLICATION_A, recv_head.ih_ep) != recv_head.ih_dcrc)
220 | 71 {
221 | 72 APP_ERR_PRINT("file newcrc err,calcrc:0X%08X, newcrc:0X%08X, len: %lu",
222 | 73 crc32((uint8_t *)APPLICATION_A, recv_head.ih_ep),
223 | 74 recv_head.ih_load, recv_head.ih_dcrc);
224 | 75 goto bsdiff_out;
225 | 76 }
226 | 77 /* 下载成功,开始升级 */
227 | 78 if (check_bin_file((bin_info_t *)(APPLICATION_A + BIN_INFO_OFFSET))) /* bin文件非法 */
228 | 79 {
229 | 80 APP_ERR_PRINT("check_bin_file err.");
230 | 81 goto bsdiff_out;
231 | 82 }
232 | 83 recv_head.ih_dcrc = CRT_CRC16_check(0, (uint8_t *)APPLICATION_A,
233 | 84 recv_head.ih_ep);
234 | 85 readwrite_app_run_bin_info(0, &recv_head.ih_ep, (uint16_t *)&recv_head.ih_dcrc);
235 | 86 /* 整体校验成功,确认升级 */
236 | 87 if (switch_program_stage(STAGE_1))
237 | 88 {
238 | 89 APP_ERR_PRINT("I write switch_program_stage STAGE_0 failed."); /* 置位升级标志写失败 */
239 | 90 goto bsdiff_out;
240 | 91 }
241 | 92 APP_PRINT("upgrade success.");
242 | 93 bsdiff_out:
243 | 94 SYSTEM_RESET();
244 | 95 }
245 |
246 | ```
247 |
--------------------------------------------------------------------------------
/bsdiff/bspatch.c:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2003-2005 Colin Percival
3 | * Copyright 2012 Matthew Endsley
4 | * All rights reserved
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted providing that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. 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 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 | * POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #include
29 | #include
30 | #include
31 | #include "bspatch.h"
32 | #include "vFile.h"
33 | #include "bs_user_interface.h"
34 |
35 | #define WRITE_BLOCK_SIZE 1024
36 |
37 | int64_t offtin(uint8_t *buf)
38 | {
39 | int64_t y;
40 |
41 | y = buf[7] & 0x7F;
42 | y = y * 256;
43 | y += buf[6];
44 | y = y * 256;
45 | y += buf[5];
46 | y = y * 256;
47 | y += buf[4];
48 | y = y * 256;
49 | y += buf[3];
50 | y = y * 256;
51 | y += buf[2];
52 | y = y * 256;
53 | y += buf[1];
54 | y = y * 256;
55 | y += buf[0];
56 |
57 | if (buf[7] & 0x80)
58 | {
59 | y = -y;
60 | }
61 |
62 | return y;
63 | }
64 |
65 | int bspatch(const uint8_t *old, int64_t oldsize, int64_t newsize, struct bspatch_stream *stream)
66 | {
67 | uint8_t buf[8];
68 | uint8_t *buf_data;
69 | int64_t oldpos, newpos, len;
70 | int64_t ctrl[3];
71 | int64_t i;
72 |
73 | buf_data = (uint8_t *)vmalloc(WRITE_BLOCK_SIZE + 1);
74 |
75 | if (buf_data == NULL)
76 | {
77 | return -1;
78 | }
79 |
80 | oldpos = 0;
81 | newpos = 0;
82 |
83 | while (newpos < newsize)
84 | {
85 | /* Read control data */
86 | for (i = 0; i <= 2; i++)
87 | {
88 | if (stream->read(stream, buf, 8))
89 | {
90 | bs_printf("err%d", __LINE__);
91 | return -1;
92 | }
93 |
94 | ctrl[i] = offtin(buf);
95 | };
96 |
97 | /* Sanity-check */
98 | if (ctrl[0] < 0 || ctrl[0] > INT_MAX ||
99 | ctrl[1] < 0 || ctrl[1] > INT_MAX ||
100 | newpos + ctrl[0] > newsize)
101 | {
102 | bs_printf("err%d", __LINE__);
103 | return -1;
104 | }
105 |
106 | /* Read diff string */
107 | while (ctrl[0] > 0)
108 | {
109 | if (ctrl[0] > WRITE_BLOCK_SIZE)
110 | {
111 | len = WRITE_BLOCK_SIZE;
112 | }
113 | else
114 | {
115 | len = ctrl[0];
116 | }
117 |
118 | if (stream->read(stream, buf_data, len))
119 | {
120 | return -1;
121 | }
122 |
123 | for (i = 0; i < len; i++)
124 | {
125 | if ((oldpos + i >= 0) && (oldpos + i < oldsize))
126 | {
127 | buf_data[i] += old[oldpos + i];
128 | }
129 | }
130 |
131 | stream->write(stream, buf_data, len);
132 | ctrl[0] -= len;
133 | oldpos += len;
134 | newpos += len;
135 | }
136 |
137 | /* Sanity-check */
138 | if (newpos + ctrl[1] > newsize)
139 | {
140 | bs_printf("err%d", __LINE__);
141 | return -1;
142 | }
143 |
144 | /* Read extra string */
145 | while (ctrl[1] > 0)
146 | {
147 | if (ctrl[1] > WRITE_BLOCK_SIZE)
148 | {
149 | len = WRITE_BLOCK_SIZE;
150 | }
151 | else
152 | {
153 | len = ctrl[1];
154 | }
155 |
156 | if (stream->read(stream, buf_data, len))
157 | {
158 | return -1;
159 | }
160 |
161 | stream->write(stream, buf_data, len);
162 | ctrl[1] -= len;
163 | newpos += len;
164 | }
165 |
166 | /* Adjust pointers */
167 | oldpos += ctrl[2];
168 | //printk("newpos = %d, ctrl[0] = %ld, ctrl[1] = %ld, ctrl[2] = %ld\n", newpos, ctrl[0], ctrl[1], ctrl[2]);
169 | };
170 |
171 | if (buf_data != NULL)
172 | {
173 | vfree(buf_data);
174 | }
175 |
176 | return 0;
177 | }
178 |
179 | //===========================================================
180 | #include "lzma_decompress.h"
181 | #include "vFile.h"
182 | #include "bs_user_interface.h"
183 |
184 | #ifndef TRUE
185 | #define TRUE 1
186 | #endif
187 |
188 | #ifndef FALSE
189 | #define FALSE 0
190 | #endif
191 |
192 | #define DCOMPRESS_BUFFER_SIZE 1024
193 | static uint8_t *diff_data_buff;
194 | static int diff_data_len, diff_data_fp;
195 | static int new_data_fp;
196 |
197 | static int patch_data_read(const struct bspatch_stream *stream, void *buffer, int length)
198 | {
199 | uint8_t *dp = (uint8_t *)buffer;
200 | vFile *pf;
201 |
202 | pf = (vFile *) stream->opaque_r;
203 |
204 | for (int i = 0; i < length; i++)
205 | {
206 | if (diff_data_len == 0)
207 | {
208 | diff_data_len = lzma_decompress_read(pf, diff_data_buff, DCOMPRESS_BUFFER_SIZE);
209 |
210 | if (diff_data_len > 0)
211 | {
212 | diff_data_fp = 0;
213 | }
214 | else
215 | {
216 | bs_printf("err%d", __LINE__);
217 | return -1;
218 | }
219 | }
220 |
221 | if (diff_data_len > 0)
222 | {
223 | *(dp++) = diff_data_buff[diff_data_fp++];
224 | diff_data_len--;
225 | }
226 | }
227 |
228 | return 0;
229 | }
230 |
231 | static int new_data_write(const struct bspatch_stream *stream, void *buffer, int length)
232 | {
233 | uint32_t file_addr;
234 |
235 | if (bs_user_func.bs_flash_write == NULL)
236 | {
237 | bs_printf("err");
238 | return (FALSE);
239 | }
240 |
241 | file_addr = *((uint32_t *)stream->opaque_w);
242 |
243 | if (0 != bs_user_func.bs_flash_write(file_addr + new_data_fp, buffer, length))
244 | {
245 | bs_printf("err");
246 | }
247 |
248 | new_data_fp += length;
249 |
250 | return (TRUE);
251 | }
252 |
253 | static void patch_data_read_finish(void)
254 | {
255 | lzma_decompress_finish();
256 |
257 | }
258 |
259 | /**
260 | * @brief 解压并还原文件,用户使用差分升级时唯一需要关心的接口
261 | *
262 | * @param old 设备中执行区代码所在的地址,用户可指定flash执行区的地址,方便算法读出来当前
263 | * 运行中的代码,用户提供
264 | * @param oldsize 设备中执行区代码的长度,用户可在差分包bin头获取,用户提供
265 | * @param patch 设备中已经下载的差分包所在的flash地址,或者ram地址,只要能让算法读出来即可
266 | * 注意,下载的差分包自带image_header_t格式的文件头,真正的差分包需要偏
267 | * 移sizeof(image_header_t)的长度,用户提供
268 | * @param patchsize 设备中已经下载的差分包的长度,用户提供,可在差分包bin头获取
269 | * @param newfile 还原后的bin写入的地址,用户提供
270 | * @return int 还原的文件大小
271 | */
272 | int iap_patch(const uint8_t *old, uint32_t oldsize, const uint8_t *patch, uint32_t patchsize, uint32_t newfile_addr)
273 | {
274 | vFile *patch_fp;
275 | struct bspatch_stream stream;
276 | uint8_t header[24];
277 | int64_t newsize;
278 |
279 | //初始化全局变量
280 | diff_data_len = 0;
281 | diff_data_fp = 0;
282 | new_data_fp = 0;
283 | patch_fp = vfopen(patch, patchsize);
284 |
285 | if (patch_fp == NULL)
286 | {
287 | bs_printf("Line 224 vmalloc err");
288 | return (0);
289 | }
290 |
291 | //读取差分文件头
292 | vfread(patch_fp, header, sizeof(header));
293 | bs_printf("patch_fp->offset:%d", patch_fp->offset);
294 |
295 | if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)
296 | {
297 | bs_printf("ENDSLEY/BSDIFF43 err: %s", header);
298 |
299 | for (uint32_t i = 0; i < sizeof(header); i++)
300 | {
301 | bs_printf("%02X ", header[i]);
302 | }
303 |
304 | return (0);
305 | }
306 |
307 | //计算新固件长度
308 | newsize = offtin(header + 16);
309 |
310 | if (newsize < 0)
311 | {
312 | bs_printf("newsize err");
313 | return (0);
314 | }
315 |
316 | //分配内存
317 | diff_data_buff = vmalloc(DCOMPRESS_BUFFER_SIZE);
318 |
319 | if (diff_data_buff == NULL)
320 | {
321 | bs_printf("\r\nmalloc err");
322 | return (0);
323 | }
324 |
325 | //准备合并文件
326 | stream.read = patch_data_read;
327 | stream.opaque_r = (void *)patch_fp;
328 | stream.write = new_data_write;
329 | stream.opaque_w = &newfile_addr;
330 |
331 | int res = bspatch(old, oldsize, newsize, &stream);
332 | (void)res;
333 | bs_printf("bspatch res:%d", res);
334 |
335 | //释放内存
336 | patch_data_read_finish();
337 | vfree(diff_data_buff);
338 | vfclose(patch_fp);
339 |
340 | return ((int)newsize);
341 | }
342 |
--------------------------------------------------------------------------------
/bsdiff/bspatch.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2003-2005 Colin Percival
3 | * Copyright 2012 Matthew Endsley
4 | * All rights reserved
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted providing that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. 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 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 | * POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #ifndef BSPATCH_H
29 | # define BSPATCH_H
30 |
31 | # include
32 |
33 | struct bspatch_stream
34 | {
35 | void* opaque_r;
36 | int (*read)(const struct bspatch_stream* stream, void* buffer, int length);
37 |
38 | void* opaque_w;
39 | int (*write)(const struct bspatch_stream* stream, void* buffer, int length);
40 | };
41 |
42 | int64_t offtin(uint8_t *buf);
43 | int bspatch(const uint8_t* old, int64_t oldsize, int64_t newsize, struct bspatch_stream* stream);
44 |
45 | #endif
46 |
47 |
--------------------------------------------------------------------------------
/bsdiff/vFile.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file vFile.c
4 | * @author eming
5 | * @version V1.0.0
6 | * @date 2022-03-21
7 | * @brief 虚拟文件接口,将保存在内部Flash的数据虚拟为文件
8 | ******************************************************************************
9 | */
10 |
11 | #include
12 | #include
13 | #include "vFile.h"
14 | #include "bs_user_interface.h"
15 |
16 |
17 | void *vmalloc(size_t size)
18 | {
19 | if (bs_user_func.bs_malloc == NULL)
20 | {
21 | return NULL;
22 | }
23 | return bs_user_func.bs_malloc((size_t)size);
24 | }
25 |
26 | void vfree(void *ptr)
27 | {
28 | if (bs_user_func.bs_free == NULL)
29 | {
30 | return;
31 | }
32 | bs_user_func.bs_free(ptr);
33 | }
34 |
35 | vFile *vfopen(const uint8_t *dp, uint32_t size)
36 | {
37 | vFile *fp = NULL;
38 |
39 | fp = vmalloc(sizeof(vFile));
40 | if (fp != NULL)
41 | {
42 | fp->curptr = (uint8_t *)dp;
43 | fp->offset = 0;
44 | fp->size = size;
45 | }
46 |
47 | return (fp);
48 | }
49 |
50 | int vfread(vFile *fp, uint8_t *buff, int len)
51 | {
52 | if (fp != NULL)
53 | {
54 | if ((fp->offset + len) > fp->size)
55 | {
56 | len = fp->size - fp->offset;
57 | }
58 | memcpy(buff, fp->curptr + fp->offset, len);
59 | fp->offset += len;
60 |
61 | return (len);
62 | }
63 |
64 | return (0);
65 | }
66 |
67 | uint8_t *vfgetpos(vFile *fp, uint32_t *position)
68 | {
69 | if (fp != NULL)
70 | {
71 | *position = fp->offset;
72 |
73 | return (fp->curptr + fp->offset);
74 | }
75 |
76 | return (NULL);
77 | }
78 |
79 | int vfsetpos(vFile *fp, uint32_t position)
80 | {
81 | if (fp != NULL)
82 | {
83 | fp->offset = position;
84 | return (fp->offset);
85 | }
86 | return -1;
87 | }
88 |
89 | int vfclose(vFile *fp)
90 | {
91 | if (fp != NULL)
92 | {
93 | vfree(fp);
94 | }
95 |
96 | return (0);
97 | }
98 |
99 | uint32_t vfgetlen(vFile *fp)
100 | {
101 | return (fp->size);
102 | }
103 |
104 | /*******************************************************************************************************
105 | ** End Of File
106 | ********************************************************************************************************/
107 |
108 |
--------------------------------------------------------------------------------
/bsdiff/vFile.h:
--------------------------------------------------------------------------------
1 | #ifndef __VFILE_H__
2 | #define __VFILE_H__
3 | /*******************************************************************************************************/
4 | #include "stdint.h"
5 |
6 | typedef struct
7 | {
8 | uint8_t *curptr;
9 | uint32_t offset;
10 | uint32_t size;
11 | }vFile;
12 |
13 | /*******************************************************************************************************/
14 | vFile *vfopen(const uint8_t *dp, uint32_t size);
15 | int vfread(vFile *fp, uint8_t *buff, int len);
16 | uint8_t *vfgetpos(vFile *fp, uint32_t *position);
17 | int vfsetpos(vFile *fp, uint32_t position);
18 | int vfclose(vFile *fp);
19 | uint32_t vfgetlen(vFile *fp);
20 | void *vmalloc(size_t size);
21 | void vfree(void *ptr);
22 |
23 | #endif
24 | /*******************************************************************************************************
25 | ** End Of File
26 | ********************************************************************************************************/
27 |
--------------------------------------------------------------------------------
/conanfile.py:
--------------------------------------------------------------------------------
1 | from conan import ConanFile
2 | from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
3 |
4 |
5 | class helloRecipe(ConanFile):
6 | name = "bsdiff_upgrade"
7 | version = "1.0.3"
8 | user = "xian"
9 | channel = "stable" #"stable" or "testing"
10 |
11 | # Sources are located in the same place as this recipe, copy them to the recipe
12 | exports_sources = "CMakeLists.txt", "readme.md", "bsdiff/*", "lib/*", "lzma/*", "user/*"
13 |
14 | #依赖包
15 | #requires = "cmsis-dsp/5.8.0@xian/stable"
16 |
17 | # Optional metadata
18 | license = "zc"
19 | author = "wangrui"
20 | url = ""
21 | description = "static libraries"
22 |
23 | # Binary configuration
24 | settings = "os", "compiler", "build_type", "arch"
25 | options = {"shared": [True, False], "fPIC": [True, False]}
26 | default_options = {"shared": False, "fPIC": False}
27 |
28 | def config_options(self):
29 | if self.settings.os == "Windows":
30 | self.options.rm_safe("fPIC")
31 |
32 | def configure(self):
33 | if self.options.shared:
34 | self.options.rm_safe("fPIC")
35 | #del self.settings.compiler.cppstd
36 | #del self.settings.compiler.libcxx
37 |
38 | def layout(self):
39 | cmake_layout(self)
40 |
41 | def generate(self):
42 | deps = CMakeDeps(self)
43 | deps.generate()
44 | tc = CMakeToolchain(self)
45 | if self.settings.compiler == "keil":
46 | if self.settings.arch == "Cortex-M4F":
47 | tc.variables["C_FLAGS"] = "--cpu Cortex-M4.fp.sp -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
48 | tc.variables["CXX_FLAGS"] = "--cpu Cortex-M4.fp.sp -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
49 | tc.variables["ASM_FLAGS"] = "--cpu Cortex-M4.fp.sp -g --apcs=interwork --pd '__MICROLIB SETA 1'"
50 | elif self.settings.arch == "Cortex-M4":
51 | tc.variables["C_FLAGS"] = "--cpu Cortex-M4 -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
52 | tc.variables["CXX_FLAGS"] = "--cpu Cortex-M4 -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
53 | tc.variables["ASM_FLAGS"] = "--cpu Cortex-M4 -g --apcs=interwork --pd '__MICROLIB SETA 1'"
54 | elif self.settings.arch == "Cortex-M3":
55 | tc.variables["C_FLAGS"] = "--cpu Cortex-M3 -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
56 | tc.variables["CXX_FLAGS"] = "--cpu Cortex-M3 -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
57 | tc.variables["ASM_FLAGS"] = "--cpu Cortex-M3 -g --apcs=interwork --pd '__MICROLIB SETA 1'"
58 | elif self.settings.arch == "Cortex-M0":
59 | tc.variables["C_FLAGS"] = "--cpu Cortex-M0 -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
60 | tc.variables["CXX_FLAGS"] = "--cpu Cortex-M0 -O3 --c99 -c -D__MICROLIB --apcs=interwork --split_sections --diag_suppress=186,66"
61 | tc.variables["ASM_FLAGS"] = "--cpu Cortex-M0 -g --apcs=interwork --pd '__MICROLIB SETA 1'"
62 | elif self.settings.compiler == "iar":
63 | if self.settings.arch == "Cortex-M4F":
64 | tc.variables["C_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M4 --fpu=VFPv4_sp"
65 | tc.variables["CXX_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M4 --fpu=VFPv4_sp"
66 | tc.variables["ASM_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M4 --fpu=VFPv4_sp"
67 | elif self.settings.arch == "Cortex-M4":
68 | tc.variables["C_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M4"
69 | tc.variables["CXX_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M4"
70 | tc.variables["ASM_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M4"
71 | elif self.settings.arch == "Cortex-M0":
72 | tc.variables["C_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M0"
73 | tc.variables["CXX_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M0"
74 | tc.variables["ASM_FLAGS"] = "--silent --no_code_motion --endian=little --cpu=Cortex-M0"
75 | elif self.settings.compiler == "arm-gcc":
76 | if self.settings.arch == "Cortex-M4F": #带fpu
77 | tc.variables["C_FLAGS"] = "-x c -mcpu=cortex-m4 -mthumb -Wstack-protector -mfloat-abi=hard -mfpu=fpv4-sp-d16 -std=gnu99 -fdata-sections -ffunction-sections --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code -Werror"
78 | tc.variables["CXX_FLAGS"] = "-x c -mcpu=cortex-m4 -mthumb -Wstack-protector -mfloat-abi=hard -mfpu=fpv4-sp-d16 -std=gnu99 -fdata-sections -ffunction-sections --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code -Werror"
79 | tc.variables["ASM_FLAGS"] = "-x assembler -c -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -std=gnu99 --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code"
80 | elif self.settings.arch == "Cortex-M4": #不带fpu
81 | tc.variables["C_FLAGS"] = "-x c -mcpu=cortex-m4 -mthumb -Wstack-protector -std=gnu99 -fdata-sections -ffunction-sections --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code -Werror"
82 | tc.variables["CXX_FLAGS"] = "-x c -mcpu=cortex-m4 -mthumb -Wstack-protector -std=gnu99 -fdata-sections -ffunction-sections --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code -Werror"
83 | tc.variables["ASM_FLAGS"] = "-x assembler -c -mcpu=cortex-m4 -mthumb -std=gnu99 --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code"
84 | elif self.settings.arch == "Cortex-M0": #不带fpu
85 | tc.variables["C_FLAGS"] = "-x c -mcpu=cortex-m0 -mthumb -Wstack-protector -std=gnu99 -fdata-sections -ffunction-sections --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code -Werror"
86 | tc.variables["CXX_FLAGS"] = "-x c -mcpu=cortex-m0 -mthumb -Wstack-protector -std=gnu99 -fdata-sections -ffunction-sections --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code -Werror"
87 | tc.variables["ASM_FLAGS"] = "-x assembler -c -mcpu=cortex-m0 -mthumb -std=gnu99 --param max-inline-insns-single=500 -Wall -Wunused -Wuninitialized -Wformat -Wformat-security -Wunknown-pragmas -Wundef -Wbad-function-cast -Wwrite-strings -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wunreachable-code"
88 | else:
89 | print(f"arch发生错误: no arch.")
90 | sys.exit(1) # 退出并返回一个非零状态码
91 | elif self.settings.compiler == "gcc":
92 | tc.variables["C_FLAGS"] = "-x c -fdata-sections -ffunction-sections -Wall -std=gnu99"
93 | tc.variables["CXX_FLAGS"] = "-x c -fdata-sections -ffunction-sections -Wall -std=gnu99"
94 | tc.variables["ASM_FLAGS"] = ""
95 | tc.variables["CMAKE_C_COMPILER_WORKS"] = 1
96 | tc.variables["CMAKE_CXX_COMPILER_WORKS"] = 1
97 | tc.variables["WITH_WINDOWS_GCC"] = True
98 | else:
99 | print(f"compiler发生错误: no compiler.")
100 | sys.exit(1) # 退出并返回一个非零状态码
101 | tc.generate()
102 |
103 | def build(self):
104 | cmake = CMake(self)
105 | cmake.configure()
106 | cmake.build()
107 |
108 | def package(self):
109 | cmake = CMake(self)
110 | cmake.install()
111 |
112 | def package_info(self):
113 | self.cpp_info.libs = [self.name]
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/lib/crc32.c:
--------------------------------------------------------------------------------
1 | /**
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | #include
8 |
9 | const unsigned int crc32tab[] =
10 | {
11 | 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
12 | 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
13 | 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
14 | 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
15 | 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
16 | 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
17 | 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
18 | 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
19 | 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
20 | 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
21 | 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
22 | 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
23 | 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
24 | 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
25 | 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
26 | 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
27 | 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
28 | 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
29 | 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
30 | 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
31 | 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
32 | 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
33 | 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
34 | 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
35 | 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
36 | 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
37 | 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
38 | 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
39 | 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
40 | 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
41 | 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
42 | 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
43 | 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
44 | 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
45 | 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
46 | 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
47 | 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
48 | 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
49 | 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
50 | 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
51 | 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
52 | 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
53 | 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
54 | 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
55 | 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
56 | 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
57 | 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
58 | 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
59 | 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
60 | 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
61 | 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
62 | 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
63 | 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
64 | 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
65 | 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
66 | 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
67 | 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
68 | 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
69 | 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
70 | 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
71 | 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
72 | 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
73 | 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
74 | 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
75 | };
76 |
77 |
78 | unsigned int crc32( const unsigned char *buf, unsigned int size)
79 | {
80 | unsigned int i, crc;
81 | crc = 0xFFFFFFFF;
82 |
83 | for (i = 0; i < size; i++)
84 | {
85 | crc = crc32tab[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
86 | }
87 | return crc ^ 0xFFFFFFFF;
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/lib/crc32.h:
--------------------------------------------------------------------------------
1 | #ifndef __CRC32_H__
2 | #define __CRC32_H__
3 | /*******************************************************************************************************/
4 | extern unsigned int crc32( const unsigned char *buf, unsigned int size);
5 |
6 | #endif
7 | /*******************************************************************************************************
8 | ** End Of File
9 | ********************************************************************************************************/
10 |
--------------------------------------------------------------------------------
/lib/mylib.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file mylib.c
4 | * @author eming
5 | * @version V1.0.0
6 | * @date 2022-03-21
7 | * @brief 定义一些公用函数
8 | ******************************************************************************
9 | */
10 | #include "stdint.h"
11 | // #include "ustdio.h"
12 | #include "stdlib.h"
13 | #include "string.h"
14 | #include "time.h"
15 | #include "bs_type.h"
16 |
17 | /**
18 | * @brief 和校验
19 | * @details 字节数组的和校验函数
20 | *
21 | * @param *p 数组指针
22 | * @param size 数组长度
23 | * @return 求和结果
24 | * @retval 无
25 | */
26 | uint32_t mylib_sum(const uint8_t *p, uint16_t size)
27 | {
28 | uint32_t sum = 0;
29 |
30 | while(size--)
31 | {
32 | sum += *(p++);
33 | }
34 | return(sum);
35 | }
36 |
37 | /**
38 | * @brief 数据比较
39 | * @details 字节数组的数据比较
40 | *
41 | * @param *p1 数组1指针
42 | * @param *p2 数组2指针
43 | * @param size 比较的数据块大小
44 | * @return 比较结果
45 | * @retval TRUE 相等
46 | * @retval FALSE 不相等
47 | */
48 | int mylib_memcmp(const void *p1, const void *p2, int size)
49 | {
50 | uint8_t *bp1, *bp2;
51 |
52 | bp1 = (uint8_t*)p1;
53 | bp2 = (uint8_t*)p2;
54 | while(size--)
55 | {
56 | if(*(bp1++) != *(bp2++))return(FALSE);
57 | }
58 | return(TRUE);
59 | }
60 |
61 | /**
62 | * @brief 数据比较
63 | * @details 字节数组与指定数据比较
64 | *
65 | * @param *p1 数组指针
66 | * @param value 被比较的数值
67 | * @param size 比较的数据块大小
68 | * @return 比较结果
69 | * @retval TRUE 相等
70 | * @retval FALSE 不相等
71 | */
72 | int mylib_memcmp_b(uint8_t *p1, uint8_t value, int size)
73 | {
74 | while(size--)
75 | {
76 | if(*(p1++) != value)return(FALSE);
77 | }
78 | return(TRUE);
79 | }
80 |
81 | /**
82 | * @brief 延时函数
83 | * @details 大概为1uS的延时函数
84 | *
85 | * @param us 需要延时的微秒数
86 | * @return 无
87 | * @retval 无
88 | */
89 | void mylib_uDelay(uint32_t us)
90 | {
91 | int i;
92 |
93 | for(; us > 0; us--)
94 | {
95 | for(i = 0; i < 40; i++);
96 | }
97 | }
98 |
99 | /**
100 | * @brief CRC16函数
101 | * @details 计算字节数组的CRC16
102 | *
103 | * @param *p 数组指针
104 | * @param size 数组长度
105 | * @return 计算结果
106 | * @retval uint16_t CRC16值
107 | */
108 | uint16_t mylib_crc16(uint8_t *p, uint16_t size)
109 | {
110 | uint16_t crc; //校验码
111 | uint16_t i;
112 | uint16_t j;
113 | crc = 0xFFFF;
114 | for (i = 0; i < size; i++)
115 | {
116 | crc ^= *p;
117 | for (j = 0; j < 8; j++)
118 | {
119 | if ((crc & 1) == 1)
120 | {
121 | crc >>= 1;
122 | crc ^= 0xA001;
123 | }
124 | else
125 | {
126 | crc >>= 1;
127 | }
128 | }
129 | p++;
130 | }
131 | return(crc);
132 | }
133 |
134 | /**
135 | * @brief 16位大小端转换
136 | * @details 数据大端小段互相转换函数
137 | *
138 | * @param *frm 源数组指针
139 | * @param *to 目标数组指针
140 | * @param size 转换的数据个数(半字)
141 | * @return 无
142 | * @retval 无
143 | */
144 | void mylib_BigtoLittle16(const void *frm, void *to, uint16_t size)
145 | {
146 | uint8_t buff[2];
147 | uint8_t *fp, *tp;
148 |
149 | fp = (uint8_t *)frm;
150 | tp = (uint8_t *)to;
151 | while(size--)
152 | {
153 | buff[0] = fp[0];
154 | buff[1] = fp[1];
155 | tp[0] = buff[1];
156 | tp[1] = buff[0];
157 |
158 | tp += 2;
159 | fp += 2;
160 | }
161 | }
162 |
163 | /**
164 | * @brief 32位大小端转换
165 | * @details 数据大端小段互相转换函数
166 | *
167 | * @param *frm 源数组指针
168 | * @param *to 目标数组指针
169 | * @param size 转换的数据个数(字)
170 | * @return 无
171 | * @retval 无
172 | */
173 | void mylib_BigtoLittle32(const void *frm, void *to, uint16_t size)
174 | {
175 | uint8_t buff[4];
176 | uint8_t *fp, *tp;
177 |
178 | fp = (uint8_t *)frm;
179 | tp = (uint8_t *)to;
180 | while(size--)
181 | {
182 | buff[0] = fp[0];
183 | buff[1] = fp[1];
184 | buff[2] = fp[2];
185 | buff[3] = fp[3];
186 | tp[0] = buff[3];
187 | tp[1] = buff[2];
188 | tp[2] = buff[1];
189 | tp[3] = buff[0];
190 |
191 | tp += 4;
192 | fp += 4;
193 | }
194 | }
195 |
196 | /**
197 | * @brief 64位浮点数大小端转换
198 | * @details 数据大端小段互相转换函数
199 | *
200 | * @param dat 浮点数
201 | * @return 转换结果
202 | * @retval 转换后的浮点数
203 | */
204 | double mylib_BigtoLittle_fp64(double dat)
205 | {
206 | F64_U8 tmp1, tmp2;
207 |
208 | tmp1.f64 = dat;
209 | tmp2.d8[0] = tmp1.d8[7];
210 | tmp2.d8[1] = tmp1.d8[6];
211 | tmp2.d8[2] = tmp1.d8[5];
212 | tmp2.d8[3] = tmp1.d8[4];
213 | tmp2.d8[4] = tmp1.d8[3];
214 | tmp2.d8[5] = tmp1.d8[2];
215 | tmp2.d8[6] = tmp1.d8[1];
216 | tmp2.d8[7] = tmp1.d8[0];
217 |
218 | return(tmp2.f64);
219 | }
220 |
221 | /**
222 | * @brief BCD编码函数
223 | * @details 二进制数据转BCD码
224 | *
225 | * @param hex 二进制数据
226 | * @return 转换结果
227 | * @retval BCD码
228 | */
229 | uint8_t mylib_HEXtoBCD(uint8_t hex)
230 | {
231 | uint8_t bcd = 0;
232 |
233 | bcd = hex / 10;
234 | bcd <<= 4;
235 | bcd += hex % 10;
236 |
237 | return(bcd);
238 | }
239 |
240 | /**
241 | * @brief BCD解码函数
242 | * @details BCD码转二进制数据
243 | *
244 | * @param bcd BCD码数据
245 | * @return 转换结果
246 | * @retval 二进制数据
247 | */
248 | uint8_t mylib_BCDtoHEX(uint8_t bcd)
249 | {
250 | uint8_t hex = 0;
251 |
252 | hex = ((bcd >> 4) & 0x0F) * 10 + (bcd & 0x0F);
253 | return(hex);
254 | }
255 |
256 | /**
257 | * @brief 数值转字符串
258 | * @details 整形数值转字符串
259 | *
260 | * @param value 整形数值
261 | * @param *str 转换结果字符串指针
262 | * @param radix 进制
263 | * @return 换结果字符串指针
264 | */
265 | char *my_itoa(int value, char *str, uint8_t radix)
266 | {
267 | static char szMap[] =
268 | {
269 | '0', '1', '2', '3', '4', '5',
270 | '6', '7', '8', '9', 'a', 'b',
271 | 'c', 'd', 'e', 'f', 'g', 'h',
272 | 'i', 'j', 'k', 'l', 'm', 'n',
273 | 'o', 'p', 'q', 'r', 's', 't',
274 | 'u', 'v', 'w', 'x', 'y', 'z'
275 | }; // 字符映射表
276 | int nCount = -1, nIndex;
277 | char *pStr = str, nTemp;
278 | unsigned int nValue = *(unsigned *)&value;
279 |
280 | if(radix >= 2 && radix <= 36 ) //限制radix必须在2到36之间
281 | {
282 | if(value < 0 && radix == 10) //如果是负数就在首位添加负号,并将字符串前移
283 | {
284 | *pStr++ = '-';
285 | value = -value; //转为正数,
286 | }
287 | do //循环转换每一个数字,直到结束
288 | {
289 | pStr[++nCount] = szMap[nValue % radix];
290 | nValue /= radix;
291 | }
292 | while(nValue > 0); //转换结束后字符串是翻的
293 | nIndex = (nCount + 1) / 2; //计算出一半的长度
294 | while(nIndex-- > 0) //将字符串的字符序翻转
295 | {
296 | nTemp = pStr[nIndex];
297 | pStr[nIndex] = pStr[nCount - nIndex];
298 | pStr[nCount - nIndex] = nTemp;
299 | }
300 | }
301 | pStr[nCount + 1] = '\0'; // 置结束符
302 | return str;
303 | }
304 |
305 | /**
306 | * @brief 数组转字符串
307 | * @details 字节数组转字符串
308 | *
309 | * @param *str 转换后的字符串
310 | * @param bytes 被转换的字节数组
311 | * @param size 被转换的字节数组长度
312 | * @return 转换出的字符串长度
313 | */
314 | int mylib_bytes_to_string(char *str, const uint8_t *bytes, int size)
315 | {
316 | int i;
317 |
318 | char hexArray[] = "0123456789ABCDEF";
319 |
320 | for (i = 0; i < size; i++)
321 | {
322 | int v = bytes[i] & 0xFF;
323 | str[i * 2] = hexArray[v >> 4];
324 | str[i * 2 + 1] = hexArray[v & 0x0F];
325 | }
326 | str[size * 2] = '\0';
327 |
328 | return (size * 2);
329 | }
330 |
331 | /**
332 | * @brief 字符串转数组
333 | * @details 字符串转字节数组
334 | *
335 | * @param *str 被转换的字符串
336 | * @param bytes 转换出的字节数组
337 | * @return 转换出的字节数组长度
338 | */
339 | int mylib_string_to_bytes(char *str, uint8_t *bytes)
340 | {
341 | uint8_t tmp, tmp1;
342 | uint16_t len;
343 | uint16_t dat_len;
344 |
345 | len = strlen(str);
346 | if(len % 2) //检查是否为偶数
347 | {
348 | str[len] = '0'; //补0
349 | len++;
350 | str[len] = '\0';
351 | }
352 | dat_len = len / 2;
353 | while(len)
354 | {
355 | if((*str > 47) && (*str < 58)) //0~9
356 | {
357 | tmp = *str - 48;
358 | }
359 | else if((*str > 64) && (*str < 71)) //A~F
360 | {
361 | tmp = *str - 55;
362 | }
363 | else if((*str > 96) && (*str < 103)) //a~f
364 | {
365 | tmp = *str - 87;
366 | }
367 | else
368 | {
369 | tmp = 32;
370 | }
371 | tmp <<= 4;
372 | str++;
373 | if((*str > 47) && (*str < 58)) //0~9
374 | {
375 | tmp1 = *str - 48;
376 | }
377 | else if((*str > 64) && (*str < 71)) //A~F
378 | {
379 | tmp1 = *str - 55;
380 | }
381 | else if((*str > 96) && (*str < 103)) //a~f
382 | {
383 | tmp1 = *str - 87;
384 | }
385 | else
386 | {
387 | tmp1 = 32;
388 | }
389 | tmp += tmp1;
390 | *(bytes++) = tmp;
391 | str++;
392 | len -= 2;
393 | }
394 |
395 | return(dat_len);
396 | }
397 |
398 | /**
399 | * @brief 大小写转换
400 | * @details 将字符串中的大写字符变为小写字符
401 | *
402 | * @param *str 被转换的字符串
403 | * @return 转换出的字符串
404 | */
405 | char *strlwr(char *str)
406 | {
407 | uint16_t len;
408 | char *p;
409 |
410 | len = strlen(str);
411 | p = str;
412 | while(len--)
413 | {
414 | if((*p > 64) && (*p < 91))
415 | {
416 | *p += 32;
417 | }
418 | p++;
419 | }
420 | return(str);
421 | }
422 |
423 | /**
424 | * @brief 字符串提取数字
425 | * @details 字符串提取数字字符,去除其他符号
426 | *
427 | * @param *str 被处理的字符串
428 | * @param *num 结果字符串
429 | * @return 提取出的字符串长度
430 | */
431 | int strval(char *str, char *num)
432 | {
433 | int len = 0;
434 |
435 | while(*str != '\0')
436 | {
437 | if((*str > 47) && (*str < 58))
438 | {
439 | *num = *str;
440 | num++;
441 | len++;
442 | }
443 | str++;
444 | }
445 | *num = '\0';
446 |
447 | return(len);
448 | }
449 |
450 | /**
451 | * @brief 打印16进制数据
452 | * @details 由于调试时输出二进制数据
453 | *
454 | * @param *p 二进制数据指针
455 | * @param size 数据长度
456 | * @return 无
457 | */
458 | void printk_hex(const uint8_t *p, int size)
459 | {
460 | // int i;
461 |
462 | // for(i = 0; i < size; i++)
463 | // {
464 | // printk(" %02X", *(p++));
465 | // }
466 | }
467 |
468 | /**
469 | * @brief utc秒转时间
470 | * @details 包含时区参数
471 | *
472 | * @param utc_s utc秒
473 | * @param *t 转换结果
474 | * @param tz 时区
475 | * @return 无
476 | */
477 | void utc_to_time(uint32_t utc_s, struct tm *t, int tz)
478 | {
479 | #define SECOND_OF_DAY 86400 //1天的秒数
480 | uint16_t i, j, iDay;
481 | uint32_t lDay;
482 | const uint8_t DayOfMon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
483 |
484 | utc_s += 3600 * tz; //时区
485 |
486 | lDay = utc_s / SECOND_OF_DAY;
487 | utc_s = utc_s % SECOND_OF_DAY;
488 |
489 | i = 1970; //星期取值为0-6
490 | t->tm_wday = (lDay + 3) % 7; //1970年1月1号是星期4
491 | while(lDay > 365)
492 | {
493 | if(((i % 4 == 0) && (i % 100 != 0)) || (i % 400 == 0)) // 闰年
494 | lDay -= 366;
495 | else
496 | lDay -= 365;
497 | i++;
498 | }
499 | if((lDay == 365) && !(((i % 4 == 0) && (i % 100 != 0)) || (i % 400 == 0))) //平年
500 | {
501 | lDay -= 365;
502 | i++;
503 | }
504 | t->tm_year = i - 1900; //得到年份
505 | for(j = 0; j < 12; j++) //计算月份
506 | {
507 | if((j == 1) && (((i % 4 == 0) && (i % 100 != 0)) || (i % 400 == 0)))
508 | iDay = 29;
509 | else
510 | iDay = DayOfMon[j];
511 | if(lDay >= iDay) lDay -= iDay;
512 | else break;
513 | }
514 | t->tm_mon = j;
515 | t->tm_mday = lDay + 1;
516 | t->tm_hour = utc_s / 3600;
517 | t->tm_min = (utc_s % 3600) / 60;
518 | t->tm_sec = (utc_s % 3600) % 60;
519 | }
520 |
521 | /**
522 | * @brief 计算日期是一年中的那一天
523 | * @details 计算日期的年索引,2月当做29天算
524 | *
525 | * @param utc_s utc秒
526 | * @param *t 转换结果
527 | * @param tz 时区
528 | * @return 无
529 | */
530 | int mylib_day_index(uint8_t mon, uint8_t day)
531 | {
532 | const uint8_t Line_Mon_Len[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
533 | int index = 0;
534 | int i;
535 |
536 | if((mon < 1) || (mon > 12))return(0); //参数判断
537 | if((day < 1) || (day > 31))return(0);
538 |
539 | for(i = 1; i < mon; i++)
540 | {
541 | index += Line_Mon_Len[i - 1];
542 | }
543 | index += day - 1;
544 |
545 | return(index);
546 | }
547 |
548 | /**
549 | * @brief 16进制字符串转数据
550 | * @details 16进制字符串转数据,可以包含"0x"头
551 | *
552 | * @param *s 字符串
553 | * @return 提取的数值
554 | */
555 | int tolower(int c)
556 | {
557 | if (c >= 'A' && c <= 'Z')
558 | {
559 | return c + 'a' - 'A';
560 | }
561 | else
562 | {
563 | return c;
564 | }
565 | }
566 |
567 | uint32_t htoi(const char *s)
568 | {
569 | int i;
570 | uint32_t n = 0;
571 |
572 | if (s[0] == '0' && (s[1]=='x' || s[1]=='X'))
573 | {
574 | i = 2;
575 | }
576 | else
577 | {
578 | i = 0;
579 | }
580 | for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >='A' && s[i] <= 'Z');++i)
581 | {
582 | if (tolower(s[i]) > '9')
583 | {
584 | n = 16 * n + (10 + tolower(s[i]) - 'a');
585 | }
586 | else
587 | {
588 | n = 16 * n + (tolower(s[i]) - '0');
589 | }
590 | }
591 | return n;
592 | }
593 |
594 | /**
595 | * @brief 返回堆内存的大小
596 | * @details 返回堆内存的大小
597 | *
598 | * @param *mp 堆内存指针
599 | * @return 堆内存的大小
600 | */
601 | uint32_t _msize(const void *mp)
602 | {
603 | return(*((int*)((uint32_t)mp - 4)));
604 | }
605 |
606 | /*******************************************************************************************************
607 | ** End Of File
608 | ********************************************************************************************************/
609 |
610 |
611 |
--------------------------------------------------------------------------------
/lib/mylib.h:
--------------------------------------------------------------------------------
1 | #ifndef __MYLIB_H
2 | #define __MYLIB_H
3 | /*********************************************************************************************************/
4 | #include "stdint.h"
5 | #include "time.h"
6 | #include "bs_type.h"
7 |
8 |
9 | uint32_t mylib_sum(const uint8_t *p, uint16_t size);
10 | int mylib_memcmp(const void *p1, const void *p2, int size);
11 | int mylib_memcmp_b(uint8_t *p1, uint8_t value, int size);
12 | void mylib_uDelay(uint32_t us);
13 | uint16_t mylib_crc16(uint8_t *p, uint16_t size);
14 | void mylib_BigtoLittle16(const void *frm, void *to, uint16_t size);
15 | void mylib_BigtoLittle32(const void *frm, void *to, uint16_t size);
16 | double mylib_BigtoLittle_fp64(double dat);
17 | uint8_t mylib_HEXtoBCD(uint8_t hex);
18 | uint8_t mylib_BCDtoHEX(uint8_t bcd);
19 | char *my_itoa(int value, char *str, uint8_t radix);
20 | int mylib_bytes_to_string(char *str, const uint8_t *bytes, int size);
21 | int mylib_string_to_bytes(char *str, uint8_t *bytes);
22 | char *strlwr(char *str);
23 | int strval(char *str, char *num);
24 | void printf_hex(const uint8_t *p, int size);
25 | void utc_to_time(uint32_t utc_s, struct tm *t, int tz);
26 | int mylib_day_index(uint8_t mon, uint8_t day);
27 | uint32_t htoi(const char *s);
28 | uint32_t _msize(const void *mp);
29 |
30 |
31 | /*********************************************************************************************************/
32 | #endif
33 | /*******************************************************************************************************
34 | ** End Of File
35 | ********************************************************************************************************/
36 |
37 |
--------------------------------------------------------------------------------
/lzma/7zFile.c:
--------------------------------------------------------------------------------
1 | /* 7zFile.c -- File IO
2 | 2017-04-03 : Igor Pavlov : Public domain */
3 |
4 | #include "Precomp.h"
5 |
6 | #include "7zFile.h"
7 |
8 | #ifndef USE_WINDOWS_FILE
9 |
10 | #ifndef UNDER_CE
11 | #include
12 | #endif
13 |
14 | #else
15 |
16 | /*
17 | ReadFile and WriteFile functions in Windows have BUG:
18 | If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
19 | from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
20 | (Insufficient system resources exist to complete the requested service).
21 | Probably in some version of Windows there are problems with other sizes:
22 | for 32 MB (maybe also for 16 MB).
23 | And message can be "Network connection was lost"
24 | */
25 |
26 | #define kChunkSizeMax (1 << 22)
27 |
28 | #endif
29 |
30 | void File_Construct(CSzFile *p)
31 | {
32 | #ifdef USE_WINDOWS_FILE
33 | p->handle = INVALID_HANDLE_VALUE;
34 | #else
35 | p->file = NULL;
36 | #endif
37 | }
38 |
39 | #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
40 | static WRes File_Open(CSzFile *p, const char *name, int writeMode)
41 | {
42 | #ifdef USE_WINDOWS_FILE
43 | p->handle = CreateFileA(name,
44 | writeMode ? GENERIC_WRITE : GENERIC_READ,
45 | FILE_SHARE_READ, NULL,
46 | writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
47 | FILE_ATTRIBUTE_NORMAL, NULL);
48 | return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
49 | #else
50 | p->file = fopen(name, writeMode ? "wb+" : "rb");
51 | return (p->file != 0) ? 0 :
52 | #ifdef UNDER_CE
53 | 2; /* ENOENT */
54 | #else
55 | errno;
56 | #endif
57 | #endif
58 | }
59 |
60 | WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
61 | WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
62 | #endif
63 |
64 | #ifdef USE_WINDOWS_FILE
65 | static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
66 | {
67 | p->handle = CreateFileW(name,
68 | writeMode ? GENERIC_WRITE : GENERIC_READ,
69 | FILE_SHARE_READ, NULL,
70 | writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
71 | FILE_ATTRIBUTE_NORMAL, NULL);
72 | return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
73 | }
74 | WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
75 | WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
76 | #endif
77 |
78 | WRes File_Close(CSzFile *p)
79 | {
80 | #ifdef USE_WINDOWS_FILE
81 | if (p->handle != INVALID_HANDLE_VALUE)
82 | {
83 | if (!CloseHandle(p->handle))
84 | return GetLastError();
85 | p->handle = INVALID_HANDLE_VALUE;
86 | }
87 | #else
88 | if (p->file != NULL)
89 | {
90 | int res = fclose(p->file);
91 | if (res != 0)
92 | return res;
93 | p->file = NULL;
94 | }
95 | #endif
96 | return 0;
97 | }
98 |
99 | WRes File_Read(CSzFile *p, void *data, size_t *size)
100 | {
101 | size_t originalSize = *size;
102 | if (originalSize == 0)
103 | return 0;
104 |
105 | #ifdef USE_WINDOWS_FILE
106 |
107 | *size = 0;
108 | do
109 | {
110 | DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
111 | DWORD processed = 0;
112 | BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
113 | data = (void *)((Byte *)data + processed);
114 | originalSize -= processed;
115 | *size += processed;
116 | if (!res)
117 | return GetLastError();
118 | if (processed == 0)
119 | break;
120 | }
121 | while (originalSize > 0);
122 | return 0;
123 |
124 | #else
125 |
126 | *size = fread(data, 1, originalSize, p->file);
127 | if (*size == originalSize)
128 | return 0;
129 | return ferror(p->file);
130 |
131 | #endif
132 | }
133 |
134 | WRes File_Write(CSzFile *p, const void *data, size_t *size)
135 | {
136 | size_t originalSize = *size;
137 | if (originalSize == 0)
138 | return 0;
139 |
140 | #ifdef USE_WINDOWS_FILE
141 |
142 | *size = 0;
143 | do
144 | {
145 | DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
146 | DWORD processed = 0;
147 | BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
148 | data = (void *)((Byte *)data + processed);
149 | originalSize -= processed;
150 | *size += processed;
151 | if (!res)
152 | return GetLastError();
153 | if (processed == 0)
154 | break;
155 | }
156 | while (originalSize > 0);
157 | return 0;
158 |
159 | #else
160 |
161 | *size = fwrite(data, 1, originalSize, p->file);
162 | if (*size == originalSize)
163 | return 0;
164 | return ferror(p->file);
165 |
166 | #endif
167 | }
168 |
169 | WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
170 | {
171 | #ifdef USE_WINDOWS_FILE
172 |
173 | LARGE_INTEGER value;
174 | DWORD moveMethod;
175 | value.LowPart = (DWORD)*pos;
176 | value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */
177 | switch (origin)
178 | {
179 | case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
180 | case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
181 | case SZ_SEEK_END: moveMethod = FILE_END; break;
182 | default: return ERROR_INVALID_PARAMETER;
183 | }
184 | value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
185 | if (value.LowPart == 0xFFFFFFFF)
186 | {
187 | WRes res = GetLastError();
188 | if (res != NO_ERROR)
189 | return res;
190 | }
191 | *pos = ((Int64)value.HighPart << 32) | value.LowPart;
192 | return 0;
193 |
194 | #else
195 |
196 | int moveMethod;
197 | int res;
198 | switch (origin)
199 | {
200 | case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
201 | case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
202 | case SZ_SEEK_END: moveMethod = SEEK_END; break;
203 | default: return 1;
204 | }
205 | res = fseek(p->file, (long)*pos, moveMethod);
206 | *pos = ftell(p->file);
207 | return res;
208 |
209 | #endif
210 | }
211 |
212 | WRes File_GetLength(CSzFile *p, UInt64 *length)
213 | {
214 | #ifdef USE_WINDOWS_FILE
215 |
216 | DWORD sizeHigh;
217 | DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
218 | if (sizeLow == 0xFFFFFFFF)
219 | {
220 | DWORD res = GetLastError();
221 | if (res != NO_ERROR)
222 | return res;
223 | }
224 | *length = (((UInt64)sizeHigh) << 32) + sizeLow;
225 | return 0;
226 |
227 | #else
228 |
229 | long pos = ftell(p->file);
230 | int res = fseek(p->file, 0, SEEK_END);
231 | *length = ftell(p->file);
232 | fseek(p->file, pos, SEEK_SET);
233 | return res;
234 |
235 | #endif
236 | }
237 |
238 |
239 | /* ---------- FileSeqInStream ---------- */
240 |
241 | static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size)
242 | {
243 | CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt);
244 | return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
245 | }
246 |
247 | void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
248 | {
249 | p->vt.Read = FileSeqInStream_Read;
250 | }
251 |
252 |
253 | /* ---------- FileInStream ---------- */
254 |
255 | static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size)
256 | {
257 | CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
258 | return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
259 | }
260 |
261 | static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin)
262 | {
263 | CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
264 | return File_Seek(&p->file, pos, origin);
265 | }
266 |
267 | void FileInStream_CreateVTable(CFileInStream *p)
268 | {
269 | p->vt.Read = FileInStream_Read;
270 | p->vt.Seek = FileInStream_Seek;
271 | }
272 |
273 |
274 | /* ---------- FileOutStream ---------- */
275 |
276 | static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size)
277 | {
278 | CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt);
279 | File_Write(&p->file, data, &size);
280 | return size;
281 | }
282 |
283 | void FileOutStream_CreateVTable(CFileOutStream *p)
284 | {
285 | p->vt.Write = FileOutStream_Write;
286 | }
287 |
--------------------------------------------------------------------------------
/lzma/7zFile.h:
--------------------------------------------------------------------------------
1 | /* 7zFile.h -- File IO
2 | 2017-04-03 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __7Z_FILE_H
5 | #define __7Z_FILE_H
6 |
7 | #ifdef _WIN32
8 | //#define USE_WINDOWS_FILE
9 | #endif
10 |
11 | #ifdef USE_WINDOWS_FILE
12 | #include
13 | #else
14 | #include
15 | #endif
16 |
17 | #include "7zTypes.h"
18 |
19 | EXTERN_C_BEGIN
20 |
21 | /* ---------- File ---------- */
22 |
23 | typedef struct
24 | {
25 | #ifdef USE_WINDOWS_FILE
26 | HANDLE handle;
27 | #else
28 | FILE *file;
29 | #endif
30 | } CSzFile;
31 |
32 | void File_Construct(CSzFile *p);
33 | #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
34 | WRes InFile_Open(CSzFile *p, const char *name);
35 | WRes OutFile_Open(CSzFile *p, const char *name);
36 | #endif
37 | #ifdef USE_WINDOWS_FILE
38 | WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
39 | WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
40 | #endif
41 | WRes File_Close(CSzFile *p);
42 |
43 | /* reads max(*size, remain file's size) bytes */
44 | WRes File_Read(CSzFile *p, void *data, size_t *size);
45 |
46 | /* writes *size bytes */
47 | WRes File_Write(CSzFile *p, const void *data, size_t *size);
48 |
49 | WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
50 | WRes File_GetLength(CSzFile *p, UInt64 *length);
51 |
52 |
53 | /* ---------- FileInStream ---------- */
54 |
55 | typedef struct
56 | {
57 | ISeqInStream vt;
58 | CSzFile file;
59 | } CFileSeqInStream;
60 |
61 | void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
62 |
63 |
64 | typedef struct
65 | {
66 | ISeekInStream vt;
67 | CSzFile file;
68 | } CFileInStream;
69 |
70 | void FileInStream_CreateVTable(CFileInStream *p);
71 |
72 |
73 | typedef struct
74 | {
75 | ISeqOutStream vt;
76 | CSzFile file;
77 | } CFileOutStream;
78 |
79 | void FileOutStream_CreateVTable(CFileOutStream *p);
80 |
81 | EXTERN_C_END
82 |
83 | #endif
84 |
--------------------------------------------------------------------------------
/lzma/7zTypes.h:
--------------------------------------------------------------------------------
1 | /* 7zTypes.h -- Basic types
2 | 2018-08-04 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __7Z_TYPES_H
5 | #define __7Z_TYPES_H
6 |
7 | #ifdef _WIN32
8 | /* #include */
9 | #endif
10 |
11 | #include
12 |
13 | #ifndef EXTERN_C_BEGIN
14 | #ifdef __cplusplus
15 | #define EXTERN_C_BEGIN extern "C" {
16 | #define EXTERN_C_END }
17 | #else
18 | #define EXTERN_C_BEGIN
19 | #define EXTERN_C_END
20 | #endif
21 | #endif
22 |
23 | EXTERN_C_BEGIN
24 |
25 | #define SZ_OK 0
26 |
27 | #define SZ_ERROR_DATA 1
28 | #define SZ_ERROR_MEM 2
29 | #define SZ_ERROR_CRC 3
30 | #define SZ_ERROR_UNSUPPORTED 4
31 | #define SZ_ERROR_PARAM 5
32 | #define SZ_ERROR_INPUT_EOF 6
33 | #define SZ_ERROR_OUTPUT_EOF 7
34 | #define SZ_ERROR_READ 8
35 | #define SZ_ERROR_WRITE 9
36 | #define SZ_ERROR_PROGRESS 10
37 | #define SZ_ERROR_FAIL 11
38 | #define SZ_ERROR_THREAD 12
39 |
40 | #define SZ_ERROR_ARCHIVE 16
41 | #define SZ_ERROR_NO_ARCHIVE 17
42 |
43 | typedef int SRes;
44 |
45 |
46 | #ifdef _WIN32
47 |
48 | /* typedef DWORD WRes; */
49 | typedef unsigned WRes;
50 | #define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
51 |
52 | #else
53 |
54 | typedef int WRes;
55 | #define MY__FACILITY_WIN32 7
56 | #define MY__FACILITY__WRes MY__FACILITY_WIN32
57 | #define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
58 |
59 | #endif
60 |
61 |
62 | #ifndef RINOK
63 | #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
64 | #endif
65 |
66 | typedef unsigned char Byte;
67 | typedef short Int16;
68 | typedef unsigned short UInt16;
69 |
70 | #ifdef _LZMA_UINT32_IS_ULONG
71 | typedef long Int32;
72 | typedef unsigned long UInt32;
73 | #else
74 | typedef int Int32;
75 | typedef unsigned int UInt32;
76 | #endif
77 |
78 | #ifdef _SZ_NO_INT_64
79 |
80 | /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
81 | NOTES: Some code will work incorrectly in that case! */
82 |
83 | typedef long Int64;
84 | typedef unsigned long UInt64;
85 |
86 | #else
87 |
88 | #if defined(_MSC_VER) || defined(__BORLANDC__)
89 | typedef __int64 Int64;
90 | typedef unsigned __int64 UInt64;
91 | #define UINT64_CONST(n) n
92 | #else
93 | typedef long long int Int64;
94 | typedef unsigned long long int UInt64;
95 | #define UINT64_CONST(n) n ## ULL
96 | #endif
97 |
98 | #endif
99 |
100 | #ifdef _LZMA_NO_SYSTEM_SIZE_T
101 | typedef UInt32 SizeT;
102 | #else
103 | typedef size_t SizeT;
104 | #endif
105 |
106 | typedef int BoolInt;
107 | /* typedef BoolInt Bool; */
108 | #define True 1
109 | #define False 0
110 |
111 |
112 | #ifdef _WIN32
113 | #define MY_STD_CALL __stdcall
114 | #else
115 | #define MY_STD_CALL
116 | #endif
117 |
118 | #ifdef _MSC_VER
119 |
120 | #if _MSC_VER >= 1300
121 | #define MY_NO_INLINE __declspec(noinline)
122 | #else
123 | #define MY_NO_INLINE
124 | #endif
125 |
126 | #define MY_FORCE_INLINE __forceinline
127 |
128 | #define MY_CDECL __cdecl
129 | #define MY_FAST_CALL __fastcall
130 |
131 | #else
132 |
133 | #define MY_NO_INLINE
134 | #define MY_FORCE_INLINE
135 | #define MY_CDECL
136 | #define MY_FAST_CALL
137 |
138 | /* inline keyword : for C++ / C99 */
139 |
140 | /* GCC, clang: */
141 | /*
142 | #if defined (__GNUC__) && (__GNUC__ >= 4)
143 | #define MY_FORCE_INLINE __attribute__((always_inline))
144 | #define MY_NO_INLINE __attribute__((noinline))
145 | #endif
146 | */
147 |
148 | #endif
149 |
150 |
151 | /* The following interfaces use first parameter as pointer to structure */
152 |
153 | typedef struct IByteIn IByteIn;
154 | struct IByteIn
155 | {
156 | Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
157 | };
158 | #define IByteIn_Read(p) (p)->Read(p)
159 |
160 |
161 | typedef struct IByteOut IByteOut;
162 | struct IByteOut
163 | {
164 | void (*Write)(const IByteOut *p, Byte b);
165 | };
166 | #define IByteOut_Write(p, b) (p)->Write(p, b)
167 |
168 |
169 | typedef struct ISeqInStream ISeqInStream;
170 | struct ISeqInStream
171 | {
172 | SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
173 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
174 | (output(*size) < input(*size)) is allowed */
175 | };
176 | #define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
177 |
178 | /* it can return SZ_ERROR_INPUT_EOF */
179 | SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
180 | SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
181 | SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
182 |
183 |
184 | typedef struct ISeqOutStream ISeqOutStream;
185 | struct ISeqOutStream
186 | {
187 | size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
188 | /* Returns: result - the number of actually written bytes.
189 | (result < size) means error */
190 | };
191 | #define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
192 |
193 | typedef enum
194 | {
195 | SZ_SEEK_SET = 0,
196 | SZ_SEEK_CUR = 1,
197 | SZ_SEEK_END = 2
198 | } ESzSeek;
199 |
200 |
201 | typedef struct ISeekInStream ISeekInStream;
202 | struct ISeekInStream
203 | {
204 | SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
205 | SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
206 | };
207 | #define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
208 | #define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
209 |
210 |
211 | typedef struct ILookInStream ILookInStream;
212 | struct ILookInStream
213 | {
214 | SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
215 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
216 | (output(*size) > input(*size)) is not allowed
217 | (output(*size) < input(*size)) is allowed */
218 | SRes (*Skip)(const ILookInStream *p, size_t offset);
219 | /* offset must be <= output(*size) of Look */
220 |
221 | SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
222 | /* reads directly (without buffer). It's same as ISeqInStream::Read */
223 | SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
224 | };
225 |
226 | #define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
227 | #define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
228 | #define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
229 | #define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
230 |
231 |
232 | SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
233 | SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset);
234 |
235 | /* reads via ILookInStream::Read */
236 | SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
237 | SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
238 |
239 |
240 |
241 | typedef struct
242 | {
243 | ILookInStream vt;
244 | const ISeekInStream *realStream;
245 |
246 | size_t pos;
247 | size_t size; /* it's data size */
248 |
249 | /* the following variables must be set outside */
250 | Byte *buf;
251 | size_t bufSize;
252 | } CLookToRead2;
253 |
254 | void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
255 |
256 | #define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
257 |
258 |
259 | typedef struct
260 | {
261 | ISeqInStream vt;
262 | const ILookInStream *realStream;
263 | } CSecToLook;
264 |
265 | void SecToLook_CreateVTable(CSecToLook *p);
266 |
267 |
268 |
269 | typedef struct
270 | {
271 | ISeqInStream vt;
272 | const ILookInStream *realStream;
273 | } CSecToRead;
274 |
275 | void SecToRead_CreateVTable(CSecToRead *p);
276 |
277 |
278 | typedef struct ICompressProgress ICompressProgress;
279 |
280 | struct ICompressProgress
281 | {
282 | SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
283 | /* Returns: result. (result != SZ_OK) means break.
284 | Value (UInt64)(Int64)-1 for size means unknown value. */
285 | };
286 | #define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
287 |
288 |
289 |
290 | typedef struct ISzAlloc ISzAlloc;
291 | typedef const ISzAlloc * ISzAllocPtr;
292 |
293 | struct ISzAlloc
294 | {
295 | void *(*Alloc)(ISzAllocPtr p, size_t size);
296 | void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
297 | };
298 |
299 | #define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
300 | #define ISzAlloc_Free(p, a) (p)->Free(p, a)
301 |
302 | /* deprecated */
303 | #define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
304 | #define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
305 |
306 |
307 |
308 |
309 |
310 | #ifndef MY_offsetof
311 | #ifdef offsetof
312 | #define MY_offsetof(type, m) offsetof(type, m)
313 | /*
314 | #define MY_offsetof(type, m) FIELD_OFFSET(type, m)
315 | */
316 | #else
317 | #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
318 | #endif
319 | #endif
320 |
321 |
322 |
323 | #ifndef MY_container_of
324 |
325 | /*
326 | #define MY_container_of(ptr, type, m) container_of(ptr, type, m)
327 | #define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
328 | #define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
329 | #define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
330 | */
331 |
332 | /*
333 | GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
334 | GCC 3.4.4 : classes with constructor
335 | GCC 4.8.1 : classes with non-public variable members"
336 | */
337 |
338 | #define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
339 |
340 |
341 | #endif
342 |
343 | #define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
344 |
345 | /*
346 | #define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
347 | */
348 | #define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
349 |
350 | #define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
351 | /*
352 | #define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
353 | */
354 |
355 |
356 |
357 | #ifdef _WIN32
358 |
359 | #define CHAR_PATH_SEPARATOR '\\'
360 | #define WCHAR_PATH_SEPARATOR L'\\'
361 | #define STRING_PATH_SEPARATOR "\\"
362 | #define WSTRING_PATH_SEPARATOR L"\\"
363 |
364 | #else
365 |
366 | #define CHAR_PATH_SEPARATOR '/'
367 | #define WCHAR_PATH_SEPARATOR L'/'
368 | #define STRING_PATH_SEPARATOR "/"
369 | #define WSTRING_PATH_SEPARATOR L"/"
370 |
371 | #endif
372 |
373 | EXTERN_C_END
374 |
375 | #endif
376 |
--------------------------------------------------------------------------------
/lzma/Compiler.h:
--------------------------------------------------------------------------------
1 | /* Compiler.h
2 | 2017-04-03 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __7Z_COMPILER_H
5 | #define __7Z_COMPILER_H
6 |
7 | #ifdef _MSC_VER
8 |
9 | #ifdef UNDER_CE
10 | #define RPC_NO_WINDOWS_H
11 | /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */
12 | #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
13 | #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int
14 | #endif
15 |
16 | #if _MSC_VER >= 1300
17 | #pragma warning(disable : 4996) // This function or variable may be unsafe
18 | #else
19 | #pragma warning(disable : 4511) // copy constructor could not be generated
20 | #pragma warning(disable : 4512) // assignment operator could not be generated
21 | #pragma warning(disable : 4514) // unreferenced inline function has been removed
22 | #pragma warning(disable : 4702) // unreachable code
23 | #pragma warning(disable : 4710) // not inlined
24 | #pragma warning(disable : 4714) // function marked as __forceinline not inlined
25 | #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
26 | #endif
27 |
28 | #endif
29 |
30 | #define UNUSED_VAR(x) (void)x;
31 | /* #define UNUSED_VAR(x) x=x; */
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/lzma/LzFind.c:
--------------------------------------------------------------------------------
1 | /* LzFind.c -- Match finder for LZ algorithms
2 | 2018-07-08 : Igor Pavlov : Public domain */
3 |
4 | #include "Precomp.h"
5 |
6 | #include
7 |
8 | #include "LzFind.h"
9 | #include "LzHash.h"
10 |
11 | #define kEmptyHashValue 0
12 | #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
13 | #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
14 | #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
15 | #define kMaxHistorySize ((UInt32)7 << 29)
16 |
17 | #define kStartMaxLen 3
18 |
19 | static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
20 | {
21 | if (!p->directInput)
22 | {
23 | ISzAlloc_Free(alloc, p->bufferBase);
24 | p->bufferBase = NULL;
25 | }
26 | }
27 |
28 | /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
29 |
30 | static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)
31 | {
32 | UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
33 | if (p->directInput)
34 | {
35 | p->blockSize = blockSize;
36 | return 1;
37 | }
38 | if (!p->bufferBase || p->blockSize != blockSize)
39 | {
40 | LzInWindow_Free(p, alloc);
41 | p->blockSize = blockSize;
42 | p->bufferBase = (Byte *) ISzAlloc_Alloc(alloc, (size_t) blockSize);
43 | }
44 | return (p->bufferBase != NULL);
45 | }
46 |
47 | Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p)
48 | {
49 | return p->buffer;
50 | }
51 |
52 | UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p)
53 | {
54 | return p->streamPos - p->pos;
55 | }
56 |
57 | void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
58 | {
59 | p->posLimit -= subValue;
60 | p->pos -= subValue;
61 | p->streamPos -= subValue;
62 | }
63 |
64 | static void MatchFinder_ReadBlock(CMatchFinder *p)
65 | {
66 | if (p->streamEndWasReached || p->result != SZ_OK)
67 | return;
68 |
69 | /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
70 |
71 | if (p->directInput)
72 | {
73 | UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
74 | if (curSize > p->directInputRem)
75 | curSize = (UInt32) p->directInputRem;
76 | p->directInputRem -= curSize;
77 | p->streamPos += curSize;
78 | if (p->directInputRem == 0)
79 | p->streamEndWasReached = 1;
80 | return;
81 | }
82 |
83 | for (;;)
84 | {
85 | Byte *dest = p->buffer + (p->streamPos - p->pos);
86 | size_t size = (p->bufferBase + p->blockSize - dest);
87 | if (size == 0)
88 | return;
89 |
90 | p->result = ISeqInStream_Read(p->stream, dest, &size);
91 | if (p->result != SZ_OK)
92 | return;
93 | if (size == 0)
94 | {
95 | p->streamEndWasReached = 1;
96 | return;
97 | }
98 | p->streamPos += (UInt32) size;
99 | if (p->streamPos - p->pos > p->keepSizeAfter)
100 | return;
101 | }
102 | }
103 |
104 | void MatchFinder_MoveBlock(CMatchFinder *p)
105 | {
106 | memmove(p->bufferBase,
107 | p->buffer - p->keepSizeBefore,
108 | (size_t) (p->streamPos - p->pos) + p->keepSizeBefore);
109 | p->buffer = p->bufferBase + p->keepSizeBefore;
110 | }
111 |
112 | int MatchFinder_NeedMove(CMatchFinder *p)
113 | {
114 | if (p->directInput)
115 | return 0;
116 | /* if (p->streamEndWasReached) return 0; */
117 | return ((size_t) (p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
118 | }
119 |
120 | void MatchFinder_ReadIfRequired(CMatchFinder *p)
121 | {
122 | if (p->streamEndWasReached)
123 | return;
124 | if (p->keepSizeAfter >= p->streamPos - p->pos)
125 | MatchFinder_ReadBlock(p);
126 | }
127 |
128 | static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
129 | {
130 | if (MatchFinder_NeedMove(p))
131 | MatchFinder_MoveBlock(p);
132 | MatchFinder_ReadBlock(p);
133 | }
134 |
135 | static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
136 | {
137 | p->cutValue = 32;
138 | p->btMode = 1;
139 | p->numHashBytes = 4;
140 | p->bigHash = 0;
141 | }
142 |
143 | #define kCrcPoly 0xEDB88320
144 |
145 | void MatchFinder_Construct(CMatchFinder *p)
146 | {
147 | unsigned i;
148 | p->bufferBase = NULL;
149 | p->directInput = 0;
150 | p->hash = NULL;
151 | p->expectedDataSize = (UInt64) (Int64) - 1;
152 | MatchFinder_SetDefaultSettings(p);
153 |
154 | for (i = 0; i < 256; i++)
155 | {
156 | UInt32 r = (UInt32) i;
157 | unsigned j;
158 | for (j = 0; j < 8; j++)
159 | r = (r >> 1) ^ (kCrcPoly & ((UInt32) 0 - (r & 1)));
160 | p->crc[i] = r;
161 | }
162 | }
163 |
164 | static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
165 | {
166 | ISzAlloc_Free(alloc, p->hash);
167 | p->hash = NULL;
168 | }
169 |
170 | void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
171 | {
172 | MatchFinder_FreeThisClassMemory(p, alloc);
173 | LzInWindow_Free(p, alloc);
174 | }
175 |
176 | static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
177 | {
178 | size_t sizeInBytes = (size_t) num * sizeof (CLzRef);
179 | if (sizeInBytes / sizeof (CLzRef) != num)
180 | return NULL;
181 | return (CLzRef *) ISzAlloc_Alloc(alloc, sizeInBytes);
182 | }
183 |
184 | int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
185 | UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
186 | ISzAllocPtr alloc)
187 | {
188 | UInt32 sizeReserv;
189 |
190 | if (historySize > kMaxHistorySize)
191 | {
192 | MatchFinder_Free(p, alloc);
193 | return 0;
194 | }
195 |
196 | sizeReserv = historySize >> 1;
197 | if (historySize >= ((UInt32) 3 << 30)) sizeReserv = historySize >> 3;
198 | else if (historySize >= ((UInt32) 2 << 30)) sizeReserv = historySize >> 2;
199 |
200 | sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
201 |
202 | p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
203 | p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
204 |
205 | /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
206 |
207 | if (LzInWindow_Create(p, sizeReserv, alloc))
208 | {
209 | UInt32 newCyclicBufferSize = historySize + 1;
210 | UInt32 hs;
211 | p->matchMaxLen = matchMaxLen;
212 | {
213 | p->fixedHashSize = 0;
214 | if (p->numHashBytes == 2)
215 | hs = (1 << 16) - 1;
216 | else
217 | {
218 | hs = historySize;
219 | if (hs > p->expectedDataSize)
220 | hs = (UInt32) p->expectedDataSize;
221 | if (hs != 0)
222 | hs--;
223 | hs |= (hs >> 1);
224 | hs |= (hs >> 2);
225 | hs |= (hs >> 4);
226 | hs |= (hs >> 8);
227 | hs >>= 1;
228 | hs |= 0xFFFF; /* don't change it! It's required for Deflate */
229 | if (hs > (1 << 24))
230 | {
231 | if (p->numHashBytes == 3)
232 | hs = (1 << 24) - 1;
233 | else
234 | hs >>= 1;
235 | /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
236 | }
237 | }
238 | p->hashMask = hs;
239 | hs++;
240 | if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
241 | if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
242 | if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
243 | hs += p->fixedHashSize;
244 | }
245 |
246 | {
247 | size_t newSize;
248 | size_t numSons;
249 | p->historySize = historySize;
250 | p->hashSizeSum = hs;
251 | p->cyclicBufferSize = newCyclicBufferSize;
252 |
253 | numSons = newCyclicBufferSize;
254 | if (p->btMode)
255 | numSons <<= 1;
256 | newSize = hs + numSons;
257 |
258 | if (p->hash && p->numRefs == newSize)
259 | return 1;
260 |
261 | MatchFinder_FreeThisClassMemory(p, alloc);
262 | p->numRefs = newSize;
263 | p->hash = AllocRefs(newSize, alloc);
264 |
265 | if (p->hash)
266 | {
267 | p->son = p->hash + p->hashSizeSum;
268 | return 1;
269 | }
270 | }
271 | }
272 |
273 | MatchFinder_Free(p, alloc);
274 | return 0;
275 | }
276 |
277 | static void MatchFinder_SetLimits(CMatchFinder *p)
278 | {
279 | UInt32 limit = kMaxValForNormalize - p->pos;
280 | UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
281 |
282 | if (limit2 < limit)
283 | limit = limit2;
284 | limit2 = p->streamPos - p->pos;
285 |
286 | if (limit2 <= p->keepSizeAfter)
287 | {
288 | if (limit2 > 0)
289 | limit2 = 1;
290 | }
291 | else
292 | limit2 -= p->keepSizeAfter;
293 |
294 | if (limit2 < limit)
295 | limit = limit2;
296 |
297 | {
298 | UInt32 lenLimit = p->streamPos - p->pos;
299 | if (lenLimit > p->matchMaxLen)
300 | lenLimit = p->matchMaxLen;
301 | p->lenLimit = lenLimit;
302 | }
303 | p->posLimit = p->pos + limit;
304 | }
305 |
306 | void MatchFinder_Init_LowHash(CMatchFinder *p)
307 | {
308 | size_t i;
309 | CLzRef *items = p->hash;
310 | size_t numItems = p->fixedHashSize;
311 | for (i = 0; i < numItems; i++)
312 | items[i] = kEmptyHashValue;
313 | }
314 |
315 | void MatchFinder_Init_HighHash(CMatchFinder *p)
316 | {
317 | size_t i;
318 | CLzRef *items = p->hash + p->fixedHashSize;
319 | size_t numItems = (size_t) p->hashMask + 1;
320 | for (i = 0; i < numItems; i++)
321 | items[i] = kEmptyHashValue;
322 | }
323 |
324 | void MatchFinder_Init_3(CMatchFinder *p, int readData)
325 | {
326 | p->cyclicBufferPos = 0;
327 | p->buffer = p->bufferBase;
328 | p->pos =
329 | p->streamPos = p->cyclicBufferSize;
330 | p->result = SZ_OK;
331 | p->streamEndWasReached = 0;
332 |
333 | if (readData)
334 | MatchFinder_ReadBlock(p);
335 |
336 | MatchFinder_SetLimits(p);
337 | }
338 |
339 | void MatchFinder_Init(CMatchFinder *p)
340 | {
341 | MatchFinder_Init_HighHash(p);
342 | MatchFinder_Init_LowHash(p);
343 | MatchFinder_Init_3(p, True);
344 | }
345 |
346 | static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
347 | {
348 | return (p->pos - p->historySize - 1) & kNormalizeMask;
349 | }
350 |
351 | void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
352 | {
353 | size_t i;
354 | for (i = 0; i < numItems; i++)
355 | {
356 | UInt32 value = items[i];
357 | if (value <= subValue)
358 | value = kEmptyHashValue;
359 | else
360 | value -= subValue;
361 | items[i] = value;
362 | }
363 | }
364 |
365 | static void MatchFinder_Normalize(CMatchFinder *p)
366 | {
367 | UInt32 subValue = MatchFinder_GetSubValue(p);
368 | MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
369 | MatchFinder_ReduceOffsets(p, subValue);
370 | }
371 |
372 | MY_NO_INLINE
373 | static void MatchFinder_CheckLimits(CMatchFinder *p)
374 | {
375 | if (p->pos == kMaxValForNormalize)
376 | MatchFinder_Normalize(p);
377 | if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
378 | MatchFinder_CheckAndMoveAndRead(p);
379 | if (p->cyclicBufferPos == p->cyclicBufferSize)
380 | p->cyclicBufferPos = 0;
381 | MatchFinder_SetLimits(p);
382 | }
383 |
384 | /*
385 | (lenLimit > maxLen)
386 | */
387 | MY_FORCE_INLINE
388 | static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
389 | UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
390 | UInt32 *distances, unsigned maxLen)
391 | {
392 | /*
393 | son[_cyclicBufferPos] = curMatch;
394 | for (;;)
395 | {
396 | UInt32 delta = pos - curMatch;
397 | if (cutValue-- == 0 || delta >= _cyclicBufferSize)
398 | return distances;
399 | {
400 | const Byte *pb = cur - delta;
401 | curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
402 | if (pb[maxLen] == cur[maxLen] && *pb == *cur)
403 | {
404 | UInt32 len = 0;
405 | while (++len != lenLimit)
406 | if (pb[len] != cur[len])
407 | break;
408 | if (maxLen < len)
409 | {
410 | maxLen = len;
411 | *distances++ = len;
412 | *distances++ = delta - 1;
413 | if (len == lenLimit)
414 | return distances;
415 | }
416 | }
417 | }
418 | }
419 | */
420 |
421 | const Byte *lim = cur + lenLimit;
422 | son[_cyclicBufferPos] = curMatch;
423 | do
424 | {
425 | UInt32 delta = pos - curMatch;
426 | if (delta >= _cyclicBufferSize)
427 | break;
428 | {
429 | ptrdiff_t diff;
430 | curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
431 | diff = (ptrdiff_t) 0 - delta;
432 | if (cur[maxLen] == cur[maxLen + diff])
433 | {
434 | const Byte *c = cur;
435 | while (*c == c[diff])
436 | {
437 | if (++c == lim)
438 | {
439 | distances[0] = (UInt32) (lim - cur);
440 | distances[1] = delta - 1;
441 | return distances + 2;
442 | }
443 | }
444 | {
445 | unsigned len = (unsigned) (c - cur);
446 | if (maxLen < len)
447 | {
448 | maxLen = len;
449 | distances[0] = (UInt32) len;
450 | distances[1] = delta - 1;
451 | distances += 2;
452 | }
453 | }
454 | }
455 | }
456 | }
457 | while (--cutValue);
458 |
459 | return distances;
460 | }
461 |
462 | MY_FORCE_INLINE
463 | UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
464 | UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
465 | UInt32 *distances, UInt32 maxLen)
466 | {
467 | CLzRef *ptr0 = son + ((size_t) _cyclicBufferPos << 1) + 1;
468 | CLzRef *ptr1 = son + ((size_t) _cyclicBufferPos << 1);
469 | unsigned len0 = 0, len1 = 0;
470 | for (;;)
471 | {
472 | UInt32 delta = pos - curMatch;
473 | if (cutValue-- == 0 || delta >= _cyclicBufferSize)
474 | {
475 | *ptr0 = *ptr1 = kEmptyHashValue;
476 | return distances;
477 | }
478 | {
479 | CLzRef *pair = son + ((size_t) (_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
480 | const Byte *pb = cur - delta;
481 | unsigned len = (len0 < len1 ? len0 : len1);
482 | UInt32 pair0 = pair[0];
483 | if (pb[len] == cur[len])
484 | {
485 | if (++len != lenLimit && pb[len] == cur[len])
486 | while (++len != lenLimit)
487 | if (pb[len] != cur[len])
488 | break;
489 | if (maxLen < len)
490 | {
491 | maxLen = (UInt32) len;
492 | *distances++ = (UInt32) len;
493 | *distances++ = delta - 1;
494 | if (len == lenLimit)
495 | {
496 | *ptr1 = pair0;
497 | *ptr0 = pair[1];
498 | return distances;
499 | }
500 | }
501 | }
502 | if (pb[len] < cur[len])
503 | {
504 | *ptr1 = curMatch;
505 | ptr1 = pair + 1;
506 | curMatch = *ptr1;
507 | len1 = len;
508 | }
509 | else
510 | {
511 | *ptr0 = curMatch;
512 | ptr0 = pair;
513 | curMatch = *ptr0;
514 | len0 = len;
515 | }
516 | }
517 | }
518 | }
519 |
520 | static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
521 | UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
522 | {
523 | CLzRef *ptr0 = son + ((size_t) _cyclicBufferPos << 1) + 1;
524 | CLzRef *ptr1 = son + ((size_t) _cyclicBufferPos << 1);
525 | unsigned len0 = 0, len1 = 0;
526 | for (;;)
527 | {
528 | UInt32 delta = pos - curMatch;
529 | if (cutValue-- == 0 || delta >= _cyclicBufferSize)
530 | {
531 | *ptr0 = *ptr1 = kEmptyHashValue;
532 | return;
533 | }
534 | {
535 | CLzRef *pair = son + ((size_t) (_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
536 | const Byte *pb = cur - delta;
537 | unsigned len = (len0 < len1 ? len0 : len1);
538 | if (pb[len] == cur[len])
539 | {
540 | while (++len != lenLimit)
541 | if (pb[len] != cur[len])
542 | break;
543 | {
544 | if (len == lenLimit)
545 | {
546 | *ptr1 = pair[0];
547 | *ptr0 = pair[1];
548 | return;
549 | }
550 | }
551 | }
552 | if (pb[len] < cur[len])
553 | {
554 | *ptr1 = curMatch;
555 | ptr1 = pair + 1;
556 | curMatch = *ptr1;
557 | len1 = len;
558 | }
559 | else
560 | {
561 | *ptr0 = curMatch;
562 | ptr0 = pair;
563 | curMatch = *ptr0;
564 | len0 = len;
565 | }
566 | }
567 | }
568 | }
569 |
570 | #define MOVE_POS \
571 | ++p->cyclicBufferPos; \
572 | p->buffer++; \
573 | if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
574 |
575 | #define MOVE_POS_RET MOVE_POS return (UInt32)offset;
576 |
577 | static void MatchFinder_MovePos(CMatchFinder *p)
578 | {
579 | MOVE_POS;
580 | }
581 |
582 | #define GET_MATCHES_HEADER2(minLen, ret_op) \
583 | unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
584 | lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
585 | cur = p->buffer;
586 |
587 | #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
588 | #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
589 |
590 | #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
591 |
592 | #define GET_MATCHES_FOOTER(offset, maxLen) \
593 | offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
594 | distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
595 |
596 | #define SKIP_FOOTER \
597 | SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
598 |
599 | #define UPDATE_maxLen { \
600 | ptrdiff_t diff = (ptrdiff_t)0 - d2; \
601 | const Byte *c = cur + maxLen; \
602 | const Byte *lim = cur + lenLimit; \
603 | for (; c != lim; c++) if (*(c + diff) != *c) break; \
604 | maxLen = (unsigned)(c - cur); }
605 |
606 | static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
607 | {
608 | unsigned offset;
609 | GET_MATCHES_HEADER(2)
610 | HASH2_CALC;
611 | curMatch = p->hash[hv];
612 | p->hash[hv] = p->pos;
613 | offset = 0;
614 | GET_MATCHES_FOOTER(offset, 1)
615 | }
616 |
617 | UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
618 | {
619 | unsigned offset;
620 | GET_MATCHES_HEADER(3)
621 | HASH_ZIP_CALC;
622 | curMatch = p->hash[hv];
623 | p->hash[hv] = p->pos;
624 | offset = 0;
625 | GET_MATCHES_FOOTER(offset, 2)
626 | }
627 |
628 | static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
629 | {
630 | UInt32 h2, d2, pos;
631 | unsigned maxLen, offset;
632 | UInt32 *hash;
633 | GET_MATCHES_HEADER(3)
634 |
635 | HASH3_CALC;
636 |
637 | hash = p->hash;
638 | pos = p->pos;
639 |
640 | d2 = pos - hash[h2];
641 |
642 | curMatch = (hash + kFix3HashSize)[hv];
643 |
644 | hash[h2] = pos;
645 | (hash + kFix3HashSize)[hv] = pos;
646 |
647 | maxLen = 2;
648 | offset = 0;
649 |
650 | if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
651 | {
652 | UPDATE_maxLen
653 | distances[0] = (UInt32) maxLen;
654 | distances[1] = d2 - 1;
655 | offset = 2;
656 | if (maxLen == lenLimit)
657 | {
658 | SkipMatchesSpec((UInt32) lenLimit, curMatch, MF_PARAMS(p));
659 | MOVE_POS_RET;
660 | }
661 | }
662 |
663 | GET_MATCHES_FOOTER(offset, maxLen)
664 | }
665 |
666 | static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
667 | {
668 | UInt32 h2, h3, d2, d3, pos;
669 | unsigned maxLen, offset;
670 | UInt32 *hash;
671 | GET_MATCHES_HEADER(4)
672 |
673 | HASH4_CALC;
674 |
675 | hash = p->hash;
676 | pos = p->pos;
677 |
678 | d2 = pos - hash [h2];
679 | d3 = pos - (hash + kFix3HashSize)[h3];
680 |
681 | curMatch = (hash + kFix4HashSize)[hv];
682 |
683 | hash [h2] = pos;
684 | (hash + kFix3HashSize)[h3] = pos;
685 | (hash + kFix4HashSize)[hv] = pos;
686 |
687 | maxLen = 0;
688 | offset = 0;
689 |
690 | if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
691 | {
692 | maxLen = 2;
693 | distances[0] = 2;
694 | distances[1] = d2 - 1;
695 | offset = 2;
696 | }
697 |
698 | if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
699 | {
700 | maxLen = 3;
701 | distances[(size_t) offset + 1] = d3 - 1;
702 | offset += 2;
703 | d2 = d3;
704 | }
705 |
706 | if (offset != 0)
707 | {
708 | UPDATE_maxLen
709 | distances[(size_t) offset - 2] = (UInt32) maxLen;
710 | if (maxLen == lenLimit)
711 | {
712 | SkipMatchesSpec((UInt32) lenLimit, curMatch, MF_PARAMS(p));
713 | MOVE_POS_RET;
714 | }
715 | }
716 |
717 | if (maxLen < 3)
718 | maxLen = 3;
719 |
720 | GET_MATCHES_FOOTER(offset, maxLen)
721 | }
722 |
723 | /*
724 | static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
725 | {
726 | UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
727 | UInt32 *hash;
728 | GET_MATCHES_HEADER(5)
729 |
730 | HASH5_CALC;
731 |
732 | hash = p->hash;
733 | pos = p->pos;
734 |
735 | d2 = pos - hash [h2];
736 | d3 = pos - (hash + kFix3HashSize)[h3];
737 | d4 = pos - (hash + kFix4HashSize)[h4];
738 |
739 | curMatch = (hash + kFix5HashSize)[hv];
740 |
741 | hash [h2] = pos;
742 | (hash + kFix3HashSize)[h3] = pos;
743 | (hash + kFix4HashSize)[h4] = pos;
744 | (hash + kFix5HashSize)[hv] = pos;
745 |
746 | maxLen = 0;
747 | offset = 0;
748 |
749 | if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
750 | {
751 | distances[0] = maxLen = 2;
752 | distances[1] = d2 - 1;
753 | offset = 2;
754 | if (*(cur - d2 + 2) == cur[2])
755 | distances[0] = maxLen = 3;
756 | else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
757 | {
758 | distances[2] = maxLen = 3;
759 | distances[3] = d3 - 1;
760 | offset = 4;
761 | d2 = d3;
762 | }
763 | }
764 | else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
765 | {
766 | distances[0] = maxLen = 3;
767 | distances[1] = d3 - 1;
768 | offset = 2;
769 | d2 = d3;
770 | }
771 |
772 | if (d2 != d4 && d4 < p->cyclicBufferSize
773 | && *(cur - d4) == *cur
774 | && *(cur - d4 + 3) == *(cur + 3))
775 | {
776 | maxLen = 4;
777 | distances[(size_t)offset + 1] = d4 - 1;
778 | offset += 2;
779 | d2 = d4;
780 | }
781 |
782 | if (offset != 0)
783 | {
784 | UPDATE_maxLen
785 | distances[(size_t)offset - 2] = maxLen;
786 | if (maxLen == lenLimit)
787 | {
788 | SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
789 | MOVE_POS_RET;
790 | }
791 | }
792 |
793 | if (maxLen < 4)
794 | maxLen = 4;
795 |
796 | GET_MATCHES_FOOTER(offset, maxLen)
797 | }
798 | */
799 |
800 | static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
801 | {
802 | UInt32 h2, h3, d2, d3, pos;
803 | unsigned maxLen, offset;
804 | UInt32 *hash;
805 | GET_MATCHES_HEADER(4)
806 |
807 | HASH4_CALC;
808 |
809 | hash = p->hash;
810 | pos = p->pos;
811 |
812 | d2 = pos - hash [h2];
813 | d3 = pos - (hash + kFix3HashSize)[h3];
814 | curMatch = (hash + kFix4HashSize)[hv];
815 |
816 | hash [h2] = pos;
817 | (hash + kFix3HashSize)[h3] = pos;
818 | (hash + kFix4HashSize)[hv] = pos;
819 |
820 | maxLen = 0;
821 | offset = 0;
822 |
823 | if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
824 | {
825 | maxLen = 2;
826 | distances[0] = 2;
827 | distances[1] = d2 - 1;
828 | offset = 2;
829 | }
830 |
831 | if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
832 | {
833 | maxLen = 3;
834 | distances[(size_t) offset + 1] = d3 - 1;
835 | offset += 2;
836 | d2 = d3;
837 | }
838 |
839 | if (offset != 0)
840 | {
841 | UPDATE_maxLen
842 | distances[(size_t) offset - 2] = (UInt32) maxLen;
843 | if (maxLen == lenLimit)
844 | {
845 | p->son[p->cyclicBufferPos] = curMatch;
846 | MOVE_POS_RET;
847 | }
848 | }
849 |
850 | if (maxLen < 3)
851 | maxLen = 3;
852 |
853 | offset = (unsigned) (Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
854 | distances + offset, maxLen) - (distances));
855 | MOVE_POS_RET
856 | }
857 |
858 | /*
859 | static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
860 | {
861 | UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
862 | UInt32 *hash;
863 | GET_MATCHES_HEADER(5)
864 |
865 | HASH5_CALC;
866 |
867 | hash = p->hash;
868 | pos = p->pos;
869 |
870 | d2 = pos - hash [h2];
871 | d3 = pos - (hash + kFix3HashSize)[h3];
872 | d4 = pos - (hash + kFix4HashSize)[h4];
873 |
874 | curMatch = (hash + kFix5HashSize)[hv];
875 |
876 | hash [h2] = pos;
877 | (hash + kFix3HashSize)[h3] = pos;
878 | (hash + kFix4HashSize)[h4] = pos;
879 | (hash + kFix5HashSize)[hv] = pos;
880 |
881 | maxLen = 0;
882 | offset = 0;
883 |
884 | if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
885 | {
886 | distances[0] = maxLen = 2;
887 | distances[1] = d2 - 1;
888 | offset = 2;
889 | if (*(cur - d2 + 2) == cur[2])
890 | distances[0] = maxLen = 3;
891 | else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
892 | {
893 | distances[2] = maxLen = 3;
894 | distances[3] = d3 - 1;
895 | offset = 4;
896 | d2 = d3;
897 | }
898 | }
899 | else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
900 | {
901 | distances[0] = maxLen = 3;
902 | distances[1] = d3 - 1;
903 | offset = 2;
904 | d2 = d3;
905 | }
906 |
907 | if (d2 != d4 && d4 < p->cyclicBufferSize
908 | && *(cur - d4) == *cur
909 | && *(cur - d4 + 3) == *(cur + 3))
910 | {
911 | maxLen = 4;
912 | distances[(size_t)offset + 1] = d4 - 1;
913 | offset += 2;
914 | d2 = d4;
915 | }
916 |
917 | if (offset != 0)
918 | {
919 | UPDATE_maxLen
920 | distances[(size_t)offset - 2] = maxLen;
921 | if (maxLen == lenLimit)
922 | {
923 | p->son[p->cyclicBufferPos] = curMatch;
924 | MOVE_POS_RET;
925 | }
926 | }
927 |
928 | if (maxLen < 4)
929 | maxLen = 4;
930 |
931 | offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
932 | distances + offset, maxLen) - (distances));
933 | MOVE_POS_RET
934 | }
935 | */
936 |
937 | UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
938 | {
939 | unsigned offset;
940 | GET_MATCHES_HEADER(3)
941 | HASH_ZIP_CALC;
942 | curMatch = p->hash[hv];
943 | p->hash[hv] = p->pos;
944 | offset = (unsigned) (Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
945 | distances, 2) - (distances));
946 | MOVE_POS_RET
947 | }
948 |
949 | static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
950 | {
951 | do
952 | {
953 | SKIP_HEADER(2)
954 | HASH2_CALC;
955 | curMatch = p->hash[hv];
956 | p->hash[hv] = p->pos;
957 | SKIP_FOOTER
958 | }
959 | while (--num != 0);
960 | }
961 |
962 | void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
963 | {
964 | do
965 | {
966 | SKIP_HEADER(3)
967 | HASH_ZIP_CALC;
968 | curMatch = p->hash[hv];
969 | p->hash[hv] = p->pos;
970 | SKIP_FOOTER
971 | }
972 | while (--num != 0);
973 | }
974 |
975 | static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
976 | {
977 | do
978 | {
979 | UInt32 h2;
980 | UInt32 *hash;
981 | SKIP_HEADER(3)
982 | HASH3_CALC;
983 | hash = p->hash;
984 | curMatch = (hash + kFix3HashSize)[hv];
985 | hash[h2] =
986 | (hash + kFix3HashSize)[hv] = p->pos;
987 | SKIP_FOOTER
988 | }
989 | while (--num != 0);
990 | }
991 |
992 | static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
993 | {
994 | do
995 | {
996 | UInt32 h2, h3;
997 | UInt32 *hash;
998 | SKIP_HEADER(4)
999 | HASH4_CALC;
1000 | hash = p->hash;
1001 | curMatch = (hash + kFix4HashSize)[hv];
1002 | hash [h2] =
1003 | (hash + kFix3HashSize)[h3] =
1004 | (hash + kFix4HashSize)[hv] = p->pos;
1005 | SKIP_FOOTER
1006 | }
1007 | while (--num != 0);
1008 | }
1009 |
1010 | /*
1011 | static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1012 | {
1013 | do
1014 | {
1015 | UInt32 h2, h3, h4;
1016 | UInt32 *hash;
1017 | SKIP_HEADER(5)
1018 | HASH5_CALC;
1019 | hash = p->hash;
1020 | curMatch = (hash + kFix5HashSize)[hv];
1021 | hash [h2] =
1022 | (hash + kFix3HashSize)[h3] =
1023 | (hash + kFix4HashSize)[h4] =
1024 | (hash + kFix5HashSize)[hv] = p->pos;
1025 | SKIP_FOOTER
1026 | }
1027 | while (--num != 0);
1028 | }
1029 | */
1030 |
1031 | static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1032 | {
1033 | do
1034 | {
1035 | UInt32 h2, h3;
1036 | UInt32 *hash;
1037 | SKIP_HEADER(4)
1038 | HASH4_CALC;
1039 | hash = p->hash;
1040 | curMatch = (hash + kFix4HashSize)[hv];
1041 | hash [h2] =
1042 | (hash + kFix3HashSize)[h3] =
1043 | (hash + kFix4HashSize)[hv] = p->pos;
1044 | p->son[p->cyclicBufferPos] = curMatch;
1045 | MOVE_POS
1046 | }
1047 | while (--num != 0);
1048 | }
1049 |
1050 | /*
1051 | static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1052 | {
1053 | do
1054 | {
1055 | UInt32 h2, h3, h4;
1056 | UInt32 *hash;
1057 | SKIP_HEADER(5)
1058 | HASH5_CALC;
1059 | hash = p->hash;
1060 | curMatch = hash + kFix5HashSize)[hv];
1061 | hash [h2] =
1062 | (hash + kFix3HashSize)[h3] =
1063 | (hash + kFix4HashSize)[h4] =
1064 | (hash + kFix5HashSize)[hv] = p->pos;
1065 | p->son[p->cyclicBufferPos] = curMatch;
1066 | MOVE_POS
1067 | }
1068 | while (--num != 0);
1069 | }
1070 | */
1071 |
1072 | void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1073 | {
1074 | do
1075 | {
1076 | SKIP_HEADER(3)
1077 | HASH_ZIP_CALC;
1078 | curMatch = p->hash[hv];
1079 | p->hash[hv] = p->pos;
1080 | p->son[p->cyclicBufferPos] = curMatch;
1081 | MOVE_POS
1082 | }
1083 | while (--num != 0);
1084 | }
1085 |
1086 | void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
1087 | {
1088 | vTable->Init = (Mf_Init_Func) MatchFinder_Init;
1089 | vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func) MatchFinder_GetNumAvailableBytes;
1090 | vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func) MatchFinder_GetPointerToCurrentPos;
1091 | if (!p->btMode)
1092 | {
1093 | /* if (p->numHashBytes <= 4) */
1094 | {
1095 | vTable->GetMatches = (Mf_GetMatches_Func) Hc4_MatchFinder_GetMatches;
1096 | vTable->Skip = (Mf_Skip_Func) Hc4_MatchFinder_Skip;
1097 | }
1098 | /*
1099 | else
1100 | {
1101 | vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
1102 | vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
1103 | }
1104 | */
1105 | }
1106 | else if (p->numHashBytes == 2)
1107 | {
1108 | vTable->GetMatches = (Mf_GetMatches_Func) Bt2_MatchFinder_GetMatches;
1109 | vTable->Skip = (Mf_Skip_Func) Bt2_MatchFinder_Skip;
1110 | }
1111 | else if (p->numHashBytes == 3)
1112 | {
1113 | vTable->GetMatches = (Mf_GetMatches_Func) Bt3_MatchFinder_GetMatches;
1114 | vTable->Skip = (Mf_Skip_Func) Bt3_MatchFinder_Skip;
1115 | }
1116 | else /* if (p->numHashBytes == 4) */
1117 | {
1118 | vTable->GetMatches = (Mf_GetMatches_Func) Bt4_MatchFinder_GetMatches;
1119 | vTable->Skip = (Mf_Skip_Func) Bt4_MatchFinder_Skip;
1120 | }
1121 | /*
1122 | else
1123 | {
1124 | vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
1125 | vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
1126 | }
1127 | */
1128 | }
1129 |
--------------------------------------------------------------------------------
/lzma/LzFind.h:
--------------------------------------------------------------------------------
1 | /* LzFind.h -- Match finder for LZ algorithms
2 | 2017-06-10 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __LZ_FIND_H
5 | #define __LZ_FIND_H
6 |
7 | #include "7zTypes.h"
8 |
9 | EXTERN_C_BEGIN
10 |
11 | typedef UInt32 CLzRef;
12 |
13 | typedef struct _CMatchFinder
14 | {
15 | Byte *buffer;
16 | UInt32 pos;
17 | UInt32 posLimit;
18 | UInt32 streamPos;
19 | UInt32 lenLimit;
20 |
21 | UInt32 cyclicBufferPos;
22 | UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
23 |
24 | Byte streamEndWasReached;
25 | Byte btMode;
26 | Byte bigHash;
27 | Byte directInput;
28 |
29 | UInt32 matchMaxLen;
30 | CLzRef *hash;
31 | CLzRef *son;
32 | UInt32 hashMask;
33 | UInt32 cutValue;
34 |
35 | Byte *bufferBase;
36 | ISeqInStream *stream;
37 |
38 | UInt32 blockSize;
39 | UInt32 keepSizeBefore;
40 | UInt32 keepSizeAfter;
41 |
42 | UInt32 numHashBytes;
43 | size_t directInputRem;
44 | UInt32 historySize;
45 | UInt32 fixedHashSize;
46 | UInt32 hashSizeSum;
47 | SRes result;
48 | UInt32 crc[256];
49 | size_t numRefs;
50 |
51 | UInt64 expectedDataSize;
52 | } CMatchFinder;
53 |
54 | #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
55 |
56 | #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
57 |
58 | #define Inline_MatchFinder_IsFinishedOK(p) \
59 | ((p)->streamEndWasReached \
60 | && (p)->streamPos == (p)->pos \
61 | && (!(p)->directInput || (p)->directInputRem == 0))
62 |
63 | int MatchFinder_NeedMove(CMatchFinder *p);
64 | Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
65 | void MatchFinder_MoveBlock(CMatchFinder *p);
66 | void MatchFinder_ReadIfRequired(CMatchFinder *p);
67 |
68 | void MatchFinder_Construct(CMatchFinder *p);
69 |
70 | /* Conditions:
71 | historySize <= 3 GB
72 | keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
73 | */
74 | int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
75 | UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
76 | ISzAllocPtr alloc);
77 | void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
78 | void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
79 | void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
80 |
81 | UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
82 | UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
83 | UInt32 *distances, UInt32 maxLen);
84 |
85 | /*
86 | Conditions:
87 | Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
88 | Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
89 | */
90 |
91 | typedef void (*Mf_Init_Func)(void *object);
92 | typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
93 | typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
94 | typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
95 | typedef void (*Mf_Skip_Func)(void *object, UInt32);
96 |
97 | typedef struct _IMatchFinder
98 | {
99 | Mf_Init_Func Init;
100 | Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
101 | Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
102 | Mf_GetMatches_Func GetMatches;
103 | Mf_Skip_Func Skip;
104 | } IMatchFinder;
105 |
106 | void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
107 |
108 | void MatchFinder_Init_LowHash(CMatchFinder *p);
109 | void MatchFinder_Init_HighHash(CMatchFinder *p);
110 | void MatchFinder_Init_3(CMatchFinder *p, int readData);
111 | void MatchFinder_Init(CMatchFinder *p);
112 |
113 | UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
114 | UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
115 |
116 | void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
117 | void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
118 |
119 | EXTERN_C_END
120 |
121 | #endif
122 |
--------------------------------------------------------------------------------
/lzma/LzHash.h:
--------------------------------------------------------------------------------
1 | /* LzHash.h -- HASH functions for LZ algorithms
2 | 2015-04-12 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __LZ_HASH_H
5 | #define __LZ_HASH_H
6 |
7 | #define kHash2Size (1 << 10)
8 | #define kHash3Size (1 << 16)
9 | #define kHash4Size (1 << 20)
10 |
11 | #define kFix3HashSize (kHash2Size)
12 | #define kFix4HashSize (kHash2Size + kHash3Size)
13 | #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
14 |
15 | #define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
16 |
17 | #define HASH3_CALC { \
18 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
19 | h2 = temp & (kHash2Size - 1); \
20 | hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
21 |
22 | #define HASH4_CALC { \
23 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
24 | h2 = temp & (kHash2Size - 1); \
25 | temp ^= ((UInt32)cur[2] << 8); \
26 | h3 = temp & (kHash3Size - 1); \
27 | hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
28 |
29 | #define HASH5_CALC { \
30 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
31 | h2 = temp & (kHash2Size - 1); \
32 | temp ^= ((UInt32)cur[2] << 8); \
33 | h3 = temp & (kHash3Size - 1); \
34 | temp ^= (p->crc[cur[3]] << 5); \
35 | h4 = temp & (kHash4Size - 1); \
36 | hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
37 |
38 | /* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
39 | #define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
40 |
41 |
42 | #define MT_HASH2_CALC \
43 | h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
44 |
45 | #define MT_HASH3_CALC { \
46 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
47 | h2 = temp & (kHash2Size - 1); \
48 | h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
49 |
50 | #define MT_HASH4_CALC { \
51 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
52 | h2 = temp & (kHash2Size - 1); \
53 | temp ^= ((UInt32)cur[2] << 8); \
54 | h3 = temp & (kHash3Size - 1); \
55 | h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
56 |
57 | #endif
58 |
--------------------------------------------------------------------------------
/lzma/LzmaDec.c:
--------------------------------------------------------------------------------
1 | /* LzmaDec.c -- LZMA Decoder
2 | 2018-07-04 : Igor Pavlov : Public domain */
3 |
4 | #include "Precomp.h"
5 |
6 | #include
7 |
8 | /* #include "CpuArch.h" */
9 | #include "LzmaDec.h"
10 |
11 | #define kNumTopBits 24
12 | #define kTopValue ((UInt32)1 << kNumTopBits)
13 |
14 | #define kNumBitModelTotalBits 11
15 | #define kBitModelTotal (1 << kNumBitModelTotalBits)
16 | #define kNumMoveBits 5
17 |
18 | #define RC_INIT_SIZE 5
19 |
20 | #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
21 |
22 | #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
23 | #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
24 | #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
25 | #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
26 | { UPDATE_0(p); i = (i + i); A0; } else \
27 | { UPDATE_1(p); i = (i + i) + 1; A1; }
28 |
29 | #define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); }
30 |
31 | #define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \
32 | { UPDATE_0(p + i); A0; } else \
33 | { UPDATE_1(p + i); A1; }
34 | #define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; )
35 | #define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; )
36 | #define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; )
37 |
38 | #define TREE_DECODE(probs, limit, i) \
39 | { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
40 |
41 | /* #define _LZMA_SIZE_OPT */
42 |
43 | #ifdef _LZMA_SIZE_OPT
44 | #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
45 | #else
46 | #define TREE_6_DECODE(probs, i) \
47 | { i = 1; \
48 | TREE_GET_BIT(probs, i); \
49 | TREE_GET_BIT(probs, i); \
50 | TREE_GET_BIT(probs, i); \
51 | TREE_GET_BIT(probs, i); \
52 | TREE_GET_BIT(probs, i); \
53 | TREE_GET_BIT(probs, i); \
54 | i -= 0x40; }
55 | #endif
56 |
57 | #define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol)
58 | #define MATCHED_LITER_DEC \
59 | matchByte += matchByte; \
60 | bit = offs; \
61 | offs &= matchByte; \
62 | probLit = prob + (offs + bit + symbol); \
63 | GET_BIT2(probLit, symbol, offs ^= bit; , ;)
64 |
65 |
66 |
67 | #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
68 |
69 | #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
70 | #define UPDATE_0_CHECK range = bound;
71 | #define UPDATE_1_CHECK range -= bound; code -= bound;
72 | #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
73 | { UPDATE_0_CHECK; i = (i + i); A0; } else \
74 | { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
75 | #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
76 | #define TREE_DECODE_CHECK(probs, limit, i) \
77 | { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
78 |
79 |
80 | #define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \
81 | { UPDATE_0_CHECK; i += m; m += m; } else \
82 | { UPDATE_1_CHECK; m += m; i += m; }
83 |
84 |
85 | #define kNumPosBitsMax 4
86 | #define kNumPosStatesMax (1 << kNumPosBitsMax)
87 |
88 | #define kLenNumLowBits 3
89 | #define kLenNumLowSymbols (1 << kLenNumLowBits)
90 | #define kLenNumHighBits 8
91 | #define kLenNumHighSymbols (1 << kLenNumHighBits)
92 |
93 | #define LenLow 0
94 | #define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits))
95 | #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
96 |
97 | #define LenChoice LenLow
98 | #define LenChoice2 (LenLow + (1 << kLenNumLowBits))
99 |
100 | #define kNumStates 12
101 | #define kNumStates2 16
102 | #define kNumLitStates 7
103 |
104 | #define kStartPosModelIndex 4
105 | #define kEndPosModelIndex 14
106 | #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
107 |
108 | #define kNumPosSlotBits 6
109 | #define kNumLenToPosStates 4
110 |
111 | #define kNumAlignBits 4
112 | #define kAlignTableSize (1 << kNumAlignBits)
113 |
114 | #define kMatchMinLen 2
115 | #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)
116 |
117 | /* External ASM code needs same CLzmaProb array layout. So don't change it. */
118 |
119 | /* (probs_1664) is faster and better for code size at some platforms */
120 | /*
121 | #ifdef MY_CPU_X86_OR_AMD64
122 | */
123 | #define kStartOffset 1664
124 | #define GET_PROBS p->probs_1664
125 | /*
126 | #define GET_PROBS p->probs + kStartOffset
127 | #else
128 | #define kStartOffset 0
129 | #define GET_PROBS p->probs
130 | #endif
131 | */
132 |
133 | #define SpecPos (-kStartOffset)
134 | #define IsRep0Long (SpecPos + kNumFullDistances)
135 | #define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax))
136 | #define LenCoder (RepLenCoder + kNumLenProbs)
137 | #define IsMatch (LenCoder + kNumLenProbs)
138 | #define Align (IsMatch + (kNumStates2 << kNumPosBitsMax))
139 | #define IsRep (Align + kAlignTableSize)
140 | #define IsRepG0 (IsRep + kNumStates)
141 | #define IsRepG1 (IsRepG0 + kNumStates)
142 | #define IsRepG2 (IsRepG1 + kNumStates)
143 | #define PosSlot (IsRepG2 + kNumStates)
144 | #define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
145 | #define NUM_BASE_PROBS (Literal + kStartOffset)
146 |
147 | #if Align != 0 && kStartOffset != 0
148 | #error Stop_Compiling_Bad_LZMA_kAlign
149 | #endif
150 |
151 | #if NUM_BASE_PROBS != 1984
152 | #error Stop_Compiling_Bad_LZMA_PROBS
153 | #endif
154 |
155 |
156 | #define LZMA_LIT_SIZE 0x300
157 |
158 | #define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
159 |
160 |
161 | #define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4)
162 | #define COMBINED_PS_STATE (posState + state)
163 | #define GET_LEN_STATE (posState)
164 |
165 | #define LZMA_DIC_MIN (1 << 12)
166 |
167 | /*
168 | p->remainLen : shows status of LZMA decoder:
169 | < kMatchSpecLenStart : normal remain
170 | = kMatchSpecLenStart : finished
171 | = kMatchSpecLenStart + 1 : need init range coder
172 | = kMatchSpecLenStart + 2 : need init range coder and state
173 | */
174 |
175 | /* ---------- LZMA_DECODE_REAL ---------- */
176 | /*
177 | LzmaDec_DecodeReal_3() can be implemented in external ASM file.
178 | 3 - is the code compatibility version of that function for check at link time.
179 | */
180 |
181 | #define LZMA_DECODE_REAL LzmaDec_DecodeReal_3
182 |
183 | /*
184 | LZMA_DECODE_REAL()
185 | In:
186 | RangeCoder is normalized
187 | if (p->dicPos == limit)
188 | {
189 | LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.
190 | So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol
191 | is not END_OF_PAYALOAD_MARKER, then function returns error code.
192 | }
193 |
194 | Processing:
195 | first LZMA symbol will be decoded in any case
196 | All checks for limits are at the end of main loop,
197 | It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit),
198 | RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.
199 |
200 | Out:
201 | RangeCoder is normalized
202 | Result:
203 | SZ_OK - OK
204 | SZ_ERROR_DATA - Error
205 | p->remainLen:
206 | < kMatchSpecLenStart : normal remain
207 | = kMatchSpecLenStart : finished
208 | */
209 |
210 |
211 | #ifdef _LZMA_DEC_OPT
212 |
213 | int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit);
214 |
215 | #else
216 |
217 | static
218 | int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
219 | {
220 | CLzmaProb *probs = GET_PROBS;
221 | unsigned state = (unsigned) p->state;
222 | UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
223 | unsigned pbMask = ((unsigned) 1 << (p->prop.pb)) - 1;
224 | unsigned lc = p->prop.lc;
225 | unsigned lpMask = ((unsigned) 0x100 << p->prop.lp) - ((unsigned) 0x100 >> lc);
226 |
227 | Byte *dic = p->dic;
228 | SizeT dicBufSize = p->dicBufSize;
229 | SizeT dicPos = p->dicPos;
230 |
231 | UInt32 processedPos = p->processedPos;
232 | UInt32 checkDicSize = p->checkDicSize;
233 | unsigned len = 0;
234 |
235 | const Byte *buf = p->buf;
236 | UInt32 range = p->range;
237 | UInt32 code = p->code;
238 |
239 | do
240 | {
241 | CLzmaProb *prob;
242 | UInt32 bound;
243 | unsigned ttt;
244 | unsigned posState = CALC_POS_STATE(processedPos, pbMask);
245 |
246 | prob = probs + IsMatch + COMBINED_PS_STATE;
247 |
248 | IF_BIT_0(prob)
249 | {
250 | unsigned symbol;
251 | UPDATE_0(prob);
252 | prob = probs + Literal;
253 | if (processedPos != 0 || checkDicSize != 0)
254 | prob += (UInt32) 3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);
255 | processedPos++;
256 |
257 | if (state < kNumLitStates)
258 | {
259 | state -= (state < 4) ? state : 3;
260 | symbol = 1;
261 | #ifdef _LZMA_SIZE_OPT
262 | do
263 | {
264 | NORMAL_LITER_DEC
265 | }
266 | while (symbol < 0x100);
267 | #else
268 | NORMAL_LITER_DEC
269 | NORMAL_LITER_DEC
270 | NORMAL_LITER_DEC
271 | NORMAL_LITER_DEC
272 | NORMAL_LITER_DEC
273 | NORMAL_LITER_DEC
274 | NORMAL_LITER_DEC
275 | NORMAL_LITER_DEC
276 | #endif
277 | }
278 | else
279 | {
280 | unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
281 | unsigned offs = 0x100;
282 | state -= (state < 10) ? 3 : 6;
283 | symbol = 1;
284 | #ifdef _LZMA_SIZE_OPT
285 | do
286 | {
287 | unsigned bit;
288 | CLzmaProb *probLit;
289 | MATCHED_LITER_DEC
290 | }
291 | while (symbol < 0x100);
292 | #else
293 | {
294 | unsigned bit;
295 | CLzmaProb *probLit;
296 | MATCHED_LITER_DEC
297 | MATCHED_LITER_DEC
298 | MATCHED_LITER_DEC
299 | MATCHED_LITER_DEC
300 | MATCHED_LITER_DEC
301 | MATCHED_LITER_DEC
302 | MATCHED_LITER_DEC
303 | MATCHED_LITER_DEC
304 | }
305 | #endif
306 | }
307 |
308 | dic[dicPos++] = (Byte) symbol;
309 | continue;
310 | }
311 |
312 | {
313 | UPDATE_1(prob);
314 | prob = probs + IsRep + state;
315 |
316 | IF_BIT_0(prob)
317 | {
318 | UPDATE_0(prob);
319 | state += kNumStates;
320 | prob = probs + LenCoder;
321 | }
322 | else
323 | {
324 | UPDATE_1(prob);
325 | /*
326 | // that case was checked before with kBadRepCode
327 | if (checkDicSize == 0 && processedPos == 0)
328 | return SZ_ERROR_DATA;
329 | */
330 | prob = probs + IsRepG0 + state;
331 |
332 | IF_BIT_0(prob)
333 | {
334 | UPDATE_0(prob);
335 | prob = probs + IsRep0Long + COMBINED_PS_STATE;
336 |
337 | IF_BIT_0(prob)
338 | {
339 | UPDATE_0(prob);
340 | dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
341 | dicPos++;
342 | processedPos++;
343 | state = state < kNumLitStates ? 9 : 11;
344 | continue;
345 | }
346 | UPDATE_1(prob);
347 | }
348 | else
349 | {
350 | UInt32 distance;
351 | UPDATE_1(prob);
352 | prob = probs + IsRepG1 + state;
353 |
354 | IF_BIT_0(prob)
355 | {
356 | UPDATE_0(prob);
357 | distance = rep1;
358 | }
359 | else
360 | {
361 | UPDATE_1(prob);
362 | prob = probs + IsRepG2 + state;
363 |
364 | IF_BIT_0(prob)
365 | {
366 | UPDATE_0(prob);
367 | distance = rep2;
368 | }
369 | else
370 | {
371 | UPDATE_1(prob);
372 | distance = rep3;
373 | rep3 = rep2;
374 | }
375 | rep2 = rep1;
376 | }
377 | rep1 = rep0;
378 | rep0 = distance;
379 | }
380 | state = state < kNumLitStates ? 8 : 11;
381 | prob = probs + RepLenCoder;
382 | }
383 |
384 | #ifdef _LZMA_SIZE_OPT
385 | {
386 | unsigned lim, offset;
387 | CLzmaProb *probLen = prob + LenChoice;
388 |
389 | IF_BIT_0(probLen)
390 | {
391 | UPDATE_0(probLen);
392 | probLen = prob + LenLow + GET_LEN_STATE;
393 | offset = 0;
394 | lim = (1 << kLenNumLowBits);
395 | }
396 | else
397 | {
398 | UPDATE_1(probLen);
399 | probLen = prob + LenChoice2;
400 |
401 | IF_BIT_0(probLen)
402 | {
403 | UPDATE_0(probLen);
404 | probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
405 | offset = kLenNumLowSymbols;
406 | lim = (1 << kLenNumLowBits);
407 | }
408 | else
409 | {
410 | UPDATE_1(probLen);
411 | probLen = prob + LenHigh;
412 | offset = kLenNumLowSymbols * 2;
413 | lim = (1 << kLenNumHighBits);
414 | }
415 | }
416 | TREE_DECODE(probLen, lim, len);
417 | len += offset;
418 | }
419 | #else
420 | {
421 | CLzmaProb *probLen = prob + LenChoice;
422 |
423 | IF_BIT_0(probLen)
424 | {
425 | UPDATE_0(probLen);
426 | probLen = prob + LenLow + GET_LEN_STATE;
427 | len = 1;
428 | TREE_GET_BIT(probLen, len);
429 | TREE_GET_BIT(probLen, len);
430 | TREE_GET_BIT(probLen, len);
431 | len -= 8;
432 | }
433 | else
434 | {
435 | UPDATE_1(probLen);
436 | probLen = prob + LenChoice2;
437 |
438 | IF_BIT_0(probLen)
439 | {
440 | UPDATE_0(probLen);
441 | probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
442 | len = 1;
443 | TREE_GET_BIT(probLen, len);
444 | TREE_GET_BIT(probLen, len);
445 | TREE_GET_BIT(probLen, len);
446 | }
447 | else
448 | {
449 | UPDATE_1(probLen);
450 | probLen = prob + LenHigh;
451 | TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
452 | len += kLenNumLowSymbols * 2;
453 | }
454 | }
455 | }
456 | #endif
457 |
458 | if (state >= kNumStates)
459 | {
460 | UInt32 distance;
461 | prob = probs + PosSlot +
462 | ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
463 | TREE_6_DECODE(prob, distance);
464 | if (distance >= kStartPosModelIndex)
465 | {
466 | unsigned posSlot = (unsigned) distance;
467 | unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));
468 | distance = (2 | (distance & 1));
469 | if (posSlot < kEndPosModelIndex)
470 | {
471 | distance <<= numDirectBits;
472 | prob = probs + SpecPos;
473 | {
474 | UInt32 m = 1;
475 | distance++;
476 | do
477 | {
478 | REV_BIT_VAR(prob, distance, m);
479 | }
480 | while (--numDirectBits);
481 | distance -= m;
482 | }
483 | }
484 | else
485 | {
486 | numDirectBits -= kNumAlignBits;
487 | do
488 | {
489 | NORMALIZE
490 | range >>= 1;
491 |
492 | {
493 | UInt32 t;
494 | code -= range;
495 | t = (0 - ((UInt32) code >> 31)); /* (UInt32)((Int32)code >> 31) */
496 | distance = (distance << 1) + (t + 1);
497 | code += range & t;
498 | }
499 | /*
500 | distance <<= 1;
501 | if (code >= range)
502 | {
503 | code -= range;
504 | distance |= 1;
505 | }
506 | */
507 | }
508 | while (--numDirectBits);
509 | prob = probs + Align;
510 | distance <<= kNumAlignBits;
511 | {
512 | unsigned i = 1;
513 | REV_BIT_CONST(prob, i, 1);
514 | REV_BIT_CONST(prob, i, 2);
515 | REV_BIT_CONST(prob, i, 4);
516 | REV_BIT_LAST(prob, i, 8);
517 | distance |= i;
518 | }
519 | if (distance == (UInt32) 0xFFFFFFFF)
520 | {
521 | len = kMatchSpecLenStart;
522 | state -= kNumStates;
523 | break;
524 | }
525 | }
526 | }
527 |
528 | rep3 = rep2;
529 | rep2 = rep1;
530 | rep1 = rep0;
531 | rep0 = distance + 1;
532 | state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
533 | if (distance >= (checkDicSize == 0 ? processedPos : checkDicSize))
534 | {
535 | p->dicPos = dicPos;
536 | return SZ_ERROR_DATA;
537 | }
538 | }
539 |
540 | len += kMatchMinLen;
541 |
542 | {
543 | SizeT rem;
544 | unsigned curLen;
545 | SizeT pos;
546 |
547 | if ((rem = limit - dicPos) == 0)
548 | {
549 | p->dicPos = dicPos;
550 | return SZ_ERROR_DATA;
551 | }
552 |
553 | curLen = ((rem < len) ? (unsigned) rem : len);
554 | pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
555 |
556 | processedPos += (UInt32) curLen;
557 |
558 | len -= curLen;
559 | if (curLen <= dicBufSize - pos)
560 | {
561 | Byte *dest = dic + dicPos;
562 | ptrdiff_t src = (ptrdiff_t) pos - (ptrdiff_t) dicPos;
563 | const Byte *lim = dest + curLen;
564 | dicPos += (SizeT) curLen;
565 | do
566 | *(dest) = (Byte) * (dest + src);
567 | while (++dest != lim);
568 | }
569 | else
570 | {
571 | do
572 | {
573 | dic[dicPos++] = dic[pos];
574 | if (++pos == dicBufSize)
575 | pos = 0;
576 | }
577 | while (--curLen != 0);
578 | }
579 | }
580 | }
581 | }
582 | while (dicPos < limit && buf < bufLimit);
583 |
584 | NORMALIZE;
585 |
586 | p->buf = buf;
587 | p->range = range;
588 | p->code = code;
589 | p->remainLen = (UInt32) len;
590 | p->dicPos = dicPos;
591 | p->processedPos = processedPos;
592 | p->reps[0] = rep0;
593 | p->reps[1] = rep1;
594 | p->reps[2] = rep2;
595 | p->reps[3] = rep3;
596 | p->state = (UInt32) state;
597 |
598 | return SZ_OK;
599 | }
600 | #endif
601 |
602 | static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
603 | {
604 | if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
605 | {
606 | Byte *dic = p->dic;
607 | SizeT dicPos = p->dicPos;
608 | SizeT dicBufSize = p->dicBufSize;
609 | unsigned len = (unsigned) p->remainLen;
610 | SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
611 | SizeT rem = limit - dicPos;
612 | if (rem < len)
613 | len = (unsigned)(rem);
614 |
615 | if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
616 | p->checkDicSize = p->prop.dicSize;
617 |
618 | p->processedPos += (UInt32) len;
619 | p->remainLen -= (UInt32) len;
620 | while (len != 0)
621 | {
622 | len--;
623 | dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
624 | dicPos++;
625 | }
626 | p->dicPos = dicPos;
627 | }
628 | }
629 |
630 |
631 | #define kRange0 0xFFFFFFFF
632 | #define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))
633 | #define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))
634 | #if kBadRepCode != (0xC0000000 - 0x400)
635 | #error Stop_Compiling_Bad_LZMA_Check
636 | #endif
637 |
638 | static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
639 | {
640 | do
641 | {
642 | SizeT limit2 = limit;
643 | if (p->checkDicSize == 0)
644 | {
645 | UInt32 rem = p->prop.dicSize - p->processedPos;
646 | if (limit - p->dicPos > rem)
647 | limit2 = p->dicPos + rem;
648 |
649 | if (p->processedPos == 0)
650 | if (p->code >= kBadRepCode)
651 | return SZ_ERROR_DATA;
652 | }
653 |
654 | RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit));
655 |
656 | if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
657 | p->checkDicSize = p->prop.dicSize;
658 |
659 | LzmaDec_WriteRem(p, limit);
660 | }
661 | while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
662 |
663 | return 0;
664 | }
665 |
666 | typedef enum
667 | {
668 | DUMMY_ERROR, /* unexpected end of input stream */
669 | DUMMY_LIT,
670 | DUMMY_MATCH,
671 | DUMMY_REP
672 | } ELzmaDummy;
673 |
674 | static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
675 | {
676 | UInt32 range = p->range;
677 | UInt32 code = p->code;
678 | const Byte *bufLimit = buf + inSize;
679 | const CLzmaProb *probs = GET_PROBS;
680 | unsigned state = (unsigned) p->state;
681 | ELzmaDummy res;
682 |
683 | {
684 | const CLzmaProb *prob;
685 | UInt32 bound;
686 | unsigned ttt;
687 | unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1);
688 |
689 | prob = probs + IsMatch + COMBINED_PS_STATE;
690 |
691 | IF_BIT_0_CHECK(prob)
692 | {
693 | UPDATE_0_CHECK
694 |
695 | /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
696 |
697 | prob = probs + Literal;
698 | if (p->checkDicSize != 0 || p->processedPos != 0)
699 | prob += ((UInt32) LZMA_LIT_SIZE *
700 | ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
701 | (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
702 |
703 | if (state < kNumLitStates)
704 | {
705 | unsigned symbol = 1;
706 | do
707 | {
708 | GET_BIT_CHECK(prob + symbol, symbol)
709 | }
710 | while (symbol < 0x100);
711 | }
712 | else
713 | {
714 | unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
715 | (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];
716 | unsigned offs = 0x100;
717 | unsigned symbol = 1;
718 | do
719 | {
720 | unsigned bit;
721 | const CLzmaProb *probLit;
722 | matchByte += matchByte;
723 | bit = offs;
724 | offs &= matchByte;
725 | probLit = prob + (offs + bit + symbol);
726 | GET_BIT2_CHECK(probLit, symbol, offs ^= bit;,;)
727 | }
728 | while (symbol < 0x100);
729 | }
730 | res = DUMMY_LIT;
731 | }
732 | else
733 | {
734 | unsigned len;
735 | UPDATE_1_CHECK;
736 |
737 | prob = probs + IsRep + state;
738 |
739 | IF_BIT_0_CHECK(prob)
740 | {
741 | UPDATE_0_CHECK;
742 | state = 0;
743 | prob = probs + LenCoder;
744 | res = DUMMY_MATCH;
745 | }
746 | else
747 | {
748 | UPDATE_1_CHECK;
749 | res = DUMMY_REP;
750 | prob = probs + IsRepG0 + state;
751 |
752 | IF_BIT_0_CHECK(prob)
753 | {
754 | UPDATE_0_CHECK;
755 | prob = probs + IsRep0Long + COMBINED_PS_STATE;
756 |
757 | IF_BIT_0_CHECK(prob)
758 | {
759 | UPDATE_0_CHECK;
760 | NORMALIZE_CHECK;
761 | return DUMMY_REP;
762 | }
763 | else
764 | {
765 | UPDATE_1_CHECK;
766 | }
767 | }
768 | else
769 | {
770 | UPDATE_1_CHECK;
771 | prob = probs + IsRepG1 + state;
772 |
773 | IF_BIT_0_CHECK(prob)
774 | {
775 | UPDATE_0_CHECK;
776 | }
777 | else
778 | {
779 | UPDATE_1_CHECK;
780 | prob = probs + IsRepG2 + state;
781 |
782 | IF_BIT_0_CHECK(prob)
783 | {
784 | UPDATE_0_CHECK;
785 | }
786 | else
787 | {
788 | UPDATE_1_CHECK;
789 | }
790 | }
791 | }
792 | state = kNumStates;
793 | prob = probs + RepLenCoder;
794 | }
795 | {
796 | unsigned limit, offset;
797 | const CLzmaProb *probLen = prob + LenChoice;
798 |
799 | IF_BIT_0_CHECK(probLen)
800 | {
801 | UPDATE_0_CHECK;
802 | probLen = prob + LenLow + GET_LEN_STATE;
803 | offset = 0;
804 | limit = 1 << kLenNumLowBits;
805 | }
806 | else
807 | {
808 | UPDATE_1_CHECK;
809 | probLen = prob + LenChoice2;
810 |
811 | IF_BIT_0_CHECK(probLen)
812 | {
813 | UPDATE_0_CHECK;
814 | probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
815 | offset = kLenNumLowSymbols;
816 | limit = 1 << kLenNumLowBits;
817 | }
818 | else
819 | {
820 | UPDATE_1_CHECK;
821 | probLen = prob + LenHigh;
822 | offset = kLenNumLowSymbols * 2;
823 | limit = 1 << kLenNumHighBits;
824 | }
825 | }
826 | TREE_DECODE_CHECK(probLen, limit, len);
827 | len += offset;
828 | }
829 |
830 | if (state < 4)
831 | {
832 | unsigned posSlot;
833 | prob = probs + PosSlot +
834 | ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<
835 | kNumPosSlotBits);
836 | TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
837 | if (posSlot >= kStartPosModelIndex)
838 | {
839 | unsigned numDirectBits = ((posSlot >> 1) - 1);
840 |
841 | /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
842 |
843 | if (posSlot < kEndPosModelIndex)
844 | {
845 | prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);
846 | }
847 | else
848 | {
849 | numDirectBits -= kNumAlignBits;
850 | do
851 | {
852 | NORMALIZE_CHECK
853 | range >>= 1;
854 | code -= range & (((code - range) >> 31) - 1);
855 | /* if (code >= range) code -= range; */
856 | }
857 | while (--numDirectBits);
858 | prob = probs + Align;
859 | numDirectBits = kNumAlignBits;
860 | }
861 | {
862 | unsigned i = 1;
863 | unsigned m = 1;
864 | do
865 | {
866 | REV_BIT_CHECK(prob, i, m);
867 | }
868 | while (--numDirectBits);
869 | }
870 | }
871 | }
872 | }
873 | }
874 | NORMALIZE_CHECK;
875 | return res;
876 | }
877 |
878 | void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)
879 | {
880 | p->remainLen = kMatchSpecLenStart + 1;
881 | p->tempBufSize = 0;
882 |
883 | if (initDic)
884 | {
885 | p->processedPos = 0;
886 | p->checkDicSize = 0;
887 | p->remainLen = kMatchSpecLenStart + 2;
888 | }
889 | if (initState)
890 | p->remainLen = kMatchSpecLenStart + 2;
891 | }
892 |
893 | void LzmaDec_Init(CLzmaDec *p)
894 | {
895 | p->dicPos = 0;
896 | LzmaDec_InitDicAndState(p, True, True);
897 | }
898 |
899 | SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
900 | ELzmaFinishMode finishMode, ELzmaStatus *status)
901 | {
902 | SizeT inSize = *srcLen;
903 | (*srcLen) = 0;
904 |
905 | *status = LZMA_STATUS_NOT_SPECIFIED;
906 | if (p->remainLen > kMatchSpecLenStart)
907 | {
908 | for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
909 | p->tempBuf[p->tempBufSize++] = *src++;
910 | if (p->tempBufSize != 0 && p->tempBuf[0] != 0)
911 | return SZ_ERROR_DATA;
912 | if (p->tempBufSize < RC_INIT_SIZE)
913 | {
914 | *status = LZMA_STATUS_NEEDS_MORE_INPUT;
915 | return SZ_OK;
916 | }
917 | p->code =
918 | ((UInt32) p->tempBuf[1] << 24)
919 | | ((UInt32) p->tempBuf[2] << 16)
920 | | ((UInt32) p->tempBuf[3] << 8)
921 | | ((UInt32) p->tempBuf[4]);
922 | p->range = 0xFFFFFFFF;
923 | p->tempBufSize = 0;
924 |
925 | if (p->remainLen > kMatchSpecLenStart + 1)
926 | {
927 | SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
928 | SizeT i;
929 | CLzmaProb *probs = p->probs;
930 | for (i = 0; i < numProbs; i++)
931 | probs[i] = kBitModelTotal >> 1;
932 | p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
933 | p->state = 0;
934 | }
935 |
936 | p->remainLen = 0;
937 | }
938 | LzmaDec_WriteRem(p, dicLimit);
939 |
940 | while (p->remainLen != kMatchSpecLenStart)
941 | {
942 | int checkEndMarkNow = 0;
943 |
944 | if (p->dicPos >= dicLimit)
945 | {
946 | if (p->remainLen == 0 && p->code == 0)
947 | {
948 | *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
949 | return SZ_OK;
950 | }
951 | if (finishMode == LZMA_FINISH_ANY)
952 | {
953 | *status = LZMA_STATUS_NOT_FINISHED;
954 | return SZ_OK;
955 | }
956 | if (p->remainLen != 0)
957 | {
958 | *status = LZMA_STATUS_NOT_FINISHED;
959 | return SZ_ERROR_DATA;
960 | }
961 | checkEndMarkNow = 1;
962 | }
963 |
964 | if (p->tempBufSize == 0)
965 | {
966 | SizeT processed;
967 | const Byte *bufLimit;
968 | if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
969 | {
970 | int dummyRes = LzmaDec_TryDummy(p, src, inSize);
971 | if (dummyRes == DUMMY_ERROR)
972 | {
973 | memcpy(p->tempBuf, src, inSize);
974 | p->tempBufSize = (unsigned) inSize;
975 | (*srcLen) += inSize;
976 | *status = LZMA_STATUS_NEEDS_MORE_INPUT;
977 | return SZ_OK;
978 | }
979 | if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
980 | {
981 | *status = LZMA_STATUS_NOT_FINISHED;
982 | return SZ_ERROR_DATA;
983 | }
984 | bufLimit = src;
985 | }
986 | else
987 | bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
988 | p->buf = src;
989 | if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
990 | return SZ_ERROR_DATA;
991 | processed = (SizeT)(p->buf - src);
992 | (*srcLen) += processed;
993 | src += processed;
994 | inSize -= processed;
995 | }
996 | else
997 | {
998 | unsigned rem = p->tempBufSize, lookAhead = 0;
999 | while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
1000 | p->tempBuf[rem++] = src[lookAhead++];
1001 | p->tempBufSize = rem;
1002 | if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
1003 | {
1004 | int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT) rem);
1005 | if (dummyRes == DUMMY_ERROR)
1006 | {
1007 | (*srcLen) += (SizeT) lookAhead;
1008 | *status = LZMA_STATUS_NEEDS_MORE_INPUT;
1009 | return SZ_OK;
1010 | }
1011 | if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
1012 | {
1013 | *status = LZMA_STATUS_NOT_FINISHED;
1014 | return SZ_ERROR_DATA;
1015 | }
1016 | }
1017 | p->buf = p->tempBuf;
1018 | if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
1019 | return SZ_ERROR_DATA;
1020 |
1021 | {
1022 | unsigned kkk = (unsigned)(p->buf - p->tempBuf);
1023 | if (rem < kkk)
1024 | return SZ_ERROR_FAIL; /* some internal error */
1025 | rem -= kkk;
1026 | if (lookAhead < rem)
1027 | return SZ_ERROR_FAIL; /* some internal error */
1028 | lookAhead -= rem;
1029 | }
1030 | (*srcLen) += (SizeT) lookAhead;
1031 | src += lookAhead;
1032 | inSize -= (SizeT) lookAhead;
1033 | p->tempBufSize = 0;
1034 | }
1035 | }
1036 |
1037 | if (p->code != 0)
1038 | return SZ_ERROR_DATA;
1039 | *status = LZMA_STATUS_FINISHED_WITH_MARK;
1040 | return SZ_OK;
1041 | }
1042 |
1043 | SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
1044 | {
1045 | SizeT outSize = *destLen;
1046 | SizeT inSize = *srcLen;
1047 | *srcLen = *destLen = 0;
1048 | for (;;)
1049 | {
1050 | SizeT inSizeCur = inSize, outSizeCur, dicPos;
1051 | ELzmaFinishMode curFinishMode;
1052 | SRes res;
1053 |
1054 | if (p->dicPos == p->dicBufSize)
1055 | p->dicPos = 0;
1056 | dicPos = p->dicPos;
1057 |
1058 | if (outSize > p->dicBufSize - dicPos)
1059 | {
1060 | outSizeCur = p->dicBufSize;
1061 | curFinishMode = LZMA_FINISH_ANY;
1062 | }
1063 | else
1064 | {
1065 | outSizeCur = dicPos + outSize;
1066 | curFinishMode = finishMode;
1067 | }
1068 |
1069 | res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
1070 | src += inSizeCur;
1071 | inSize -= inSizeCur;
1072 | *srcLen += inSizeCur;
1073 | outSizeCur = p->dicPos - dicPos;
1074 | memcpy(dest, p->dic + dicPos, outSizeCur);
1075 | dest += outSizeCur;
1076 | outSize -= outSizeCur;
1077 | *destLen += outSizeCur;
1078 | if (res != 0)
1079 | return res;
1080 | if (outSizeCur == 0 || outSize == 0)
1081 | return SZ_OK;
1082 | }
1083 | }
1084 |
1085 | void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc)
1086 | {
1087 | ISzAlloc_Free(alloc, p->probs);
1088 | p->probs = NULL;
1089 | }
1090 |
1091 | static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc)
1092 | {
1093 | ISzAlloc_Free(alloc, p->dic);
1094 | p->dic = NULL;
1095 | }
1096 |
1097 | void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc)
1098 | {
1099 | LzmaDec_FreeProbs(p, alloc);
1100 | LzmaDec_FreeDict(p, alloc);
1101 | }
1102 |
1103 | SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
1104 | {
1105 | UInt32 dicSize;
1106 | Byte d;
1107 |
1108 | if (size < LZMA_PROPS_SIZE)
1109 | return SZ_ERROR_UNSUPPORTED;
1110 | else
1111 | dicSize = data[1] | ((UInt32) data[2] << 8) | ((UInt32) data[3] << 16) | ((UInt32) data[4] << 24);
1112 |
1113 | if (dicSize < LZMA_DIC_MIN)
1114 | dicSize = LZMA_DIC_MIN;
1115 | p->dicSize = dicSize;
1116 |
1117 | d = data[0];
1118 | if (d >= (9 * 5 * 5))
1119 | return SZ_ERROR_UNSUPPORTED;
1120 |
1121 | p->lc = (Byte)(d % 9);
1122 | d /= 9;
1123 | p->pb = (Byte)(d / 5);
1124 | p->lp = (Byte)(d % 5);
1125 |
1126 | return SZ_OK;
1127 | }
1128 |
1129 | static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc)
1130 | {
1131 | UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
1132 | if (!p->probs || numProbs != p->numProbs)
1133 | {
1134 | LzmaDec_FreeProbs(p, alloc);
1135 | p->probs = (CLzmaProb *) ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb));
1136 | if (!p->probs)
1137 | return SZ_ERROR_MEM;
1138 | p->probs_1664 = p->probs + 1664;
1139 | p->numProbs = numProbs;
1140 | }
1141 | return SZ_OK;
1142 | }
1143 |
1144 | SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
1145 | {
1146 | CLzmaProps propNew;
1147 | RINOK(LzmaProps_Decode(&propNew, props, propsSize));
1148 | RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
1149 | p->prop = propNew;
1150 | return SZ_OK;
1151 | }
1152 |
1153 | SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
1154 | {
1155 | CLzmaProps propNew;
1156 | SizeT dicBufSize;
1157 | RINOK(LzmaProps_Decode(&propNew, props, propsSize));
1158 | RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
1159 |
1160 | {
1161 | UInt32 dictSize = propNew.dicSize;
1162 | SizeT mask = ((UInt32) 1 << 12) - 1;
1163 | if (dictSize >= ((UInt32) 1 << 30)) mask = ((UInt32) 1 << 22) - 1;
1164 | else if (dictSize >= ((UInt32) 1 << 22)) mask = ((UInt32) 1 << 20) - 1;
1165 | ;
1166 | dicBufSize = ((SizeT) dictSize + mask) & ~mask;
1167 | if (dicBufSize < dictSize)
1168 | dicBufSize = dictSize;
1169 | }
1170 |
1171 | if (!p->dic || dicBufSize != p->dicBufSize)
1172 | {
1173 | LzmaDec_FreeDict(p, alloc);
1174 | p->dic = (Byte *) ISzAlloc_Alloc(alloc, dicBufSize);
1175 | if (!p->dic)
1176 | {
1177 | LzmaDec_FreeProbs(p, alloc);
1178 | return SZ_ERROR_MEM;
1179 | }
1180 | }
1181 | p->dicBufSize = dicBufSize;
1182 | p->prop = propNew;
1183 | return SZ_OK;
1184 | }
1185 |
1186 | SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
1187 | const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
1188 | ELzmaStatus *status, ISzAllocPtr alloc)
1189 | {
1190 | CLzmaDec p;
1191 | SRes res;
1192 | SizeT outSize = *destLen, inSize = *srcLen;
1193 | *destLen = *srcLen = 0;
1194 | *status = LZMA_STATUS_NOT_SPECIFIED;
1195 | if (inSize < RC_INIT_SIZE)
1196 | return SZ_ERROR_INPUT_EOF;
1197 | LzmaDec_Construct(&p);
1198 | RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));
1199 | p.dic = dest;
1200 | p.dicBufSize = outSize;
1201 | LzmaDec_Init(&p);
1202 | *srcLen = inSize;
1203 | res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
1204 | *destLen = p.dicPos;
1205 | if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
1206 | res = SZ_ERROR_INPUT_EOF;
1207 | LzmaDec_FreeProbs(&p, alloc);
1208 | return res;
1209 | }
1210 |
--------------------------------------------------------------------------------
/lzma/LzmaDec.h:
--------------------------------------------------------------------------------
1 | /* LzmaDec.h -- LZMA Decoder
2 | 2018-04-21 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __LZMA_DEC_H
5 | #define __LZMA_DEC_H
6 |
7 | #include "7zTypes.h"
8 |
9 | EXTERN_C_BEGIN
10 |
11 | /* #define _LZMA_PROB32 */
12 | /* _LZMA_PROB32 can increase the speed on some CPUs,
13 | but memory usage for CLzmaDec::probs will be doubled in that case */
14 |
15 | typedef
16 | #ifdef _LZMA_PROB32
17 | UInt32
18 | #else
19 | UInt16
20 | #endif
21 | CLzmaProb;
22 |
23 |
24 | /* ---------- LZMA Properties ---------- */
25 |
26 | #define LZMA_PROPS_SIZE 5
27 |
28 | typedef struct _CLzmaProps
29 | {
30 | Byte lc;
31 | Byte lp;
32 | Byte pb;
33 | Byte _pad_;
34 | UInt32 dicSize;
35 | } CLzmaProps;
36 |
37 | /* LzmaProps_Decode - decodes properties
38 | Returns:
39 | SZ_OK
40 | SZ_ERROR_UNSUPPORTED - Unsupported properties
41 | */
42 |
43 | SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
44 |
45 |
46 | /* ---------- LZMA Decoder state ---------- */
47 |
48 | /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
49 | Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
50 |
51 | #define LZMA_REQUIRED_INPUT_MAX 20
52 |
53 | typedef struct
54 | {
55 | /* Don't change this structure. ASM code can use it. */
56 | CLzmaProps prop;
57 | CLzmaProb *probs;
58 | CLzmaProb *probs_1664;
59 | Byte *dic;
60 | SizeT dicBufSize;
61 | SizeT dicPos;
62 | const Byte *buf;
63 | UInt32 range;
64 | UInt32 code;
65 | UInt32 processedPos;
66 | UInt32 checkDicSize;
67 | UInt32 reps[4];
68 | UInt32 state;
69 | UInt32 remainLen;
70 |
71 | UInt32 numProbs;
72 | unsigned tempBufSize;
73 | Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
74 | } CLzmaDec;
75 |
76 | #define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
77 |
78 | void LzmaDec_Init(CLzmaDec *p);
79 |
80 | /* There are two types of LZMA streams:
81 | - Stream with end mark. That end mark adds about 6 bytes to compressed size.
82 | - Stream without end mark. You must know exact uncompressed size to decompress such stream. */
83 |
84 | typedef enum
85 | {
86 | LZMA_FINISH_ANY, /* finish at any point */
87 | LZMA_FINISH_END /* block must be finished at the end */
88 | } ELzmaFinishMode;
89 |
90 | /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
91 |
92 | You must use LZMA_FINISH_END, when you know that current output buffer
93 | covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
94 |
95 | If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
96 | and output value of destLen will be less than output buffer size limit.
97 | You can check status result also.
98 |
99 | You can use multiple checks to test data integrity after full decompression:
100 | 1) Check Result and "status" variable.
101 | 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
102 | 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
103 | You must use correct finish mode in that case. */
104 |
105 | typedef enum
106 | {
107 | LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
108 | LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
109 | LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
110 | LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
111 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
112 | } ELzmaStatus;
113 |
114 | /* ELzmaStatus is used only as output value for function call */
115 |
116 |
117 | /* ---------- Interfaces ---------- */
118 |
119 | /* There are 3 levels of interfaces:
120 | 1) Dictionary Interface
121 | 2) Buffer Interface
122 | 3) One Call Interface
123 | You can select any of these interfaces, but don't mix functions from different
124 | groups for same object. */
125 |
126 |
127 | /* There are two variants to allocate state for Dictionary Interface:
128 | 1) LzmaDec_Allocate / LzmaDec_Free
129 | 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
130 | You can use variant 2, if you set dictionary buffer manually.
131 | For Buffer Interface you must always use variant 1.
132 |
133 | LzmaDec_Allocate* can return:
134 | SZ_OK
135 | SZ_ERROR_MEM - Memory allocation error
136 | SZ_ERROR_UNSUPPORTED - Unsupported properties
137 | */
138 |
139 | SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
140 | void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
141 |
142 | SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
143 | void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
144 |
145 | /* ---------- Dictionary Interface ---------- */
146 |
147 | /* You can use it, if you want to eliminate the overhead for data copying from
148 | dictionary to some other external buffer.
149 | You must work with CLzmaDec variables directly in this interface.
150 |
151 | STEPS:
152 | LzmaDec_Construct()
153 | LzmaDec_Allocate()
154 | for (each new stream)
155 | {
156 | LzmaDec_Init()
157 | while (it needs more decompression)
158 | {
159 | LzmaDec_DecodeToDic()
160 | use data from CLzmaDec::dic and update CLzmaDec::dicPos
161 | }
162 | }
163 | LzmaDec_Free()
164 | */
165 |
166 | /* LzmaDec_DecodeToDic
167 |
168 | The decoding to internal dictionary buffer (CLzmaDec::dic).
169 | You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
170 |
171 | finishMode:
172 | It has meaning only if the decoding reaches output limit (dicLimit).
173 | LZMA_FINISH_ANY - Decode just dicLimit bytes.
174 | LZMA_FINISH_END - Stream must be finished after dicLimit.
175 |
176 | Returns:
177 | SZ_OK
178 | status:
179 | LZMA_STATUS_FINISHED_WITH_MARK
180 | LZMA_STATUS_NOT_FINISHED
181 | LZMA_STATUS_NEEDS_MORE_INPUT
182 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
183 | SZ_ERROR_DATA - Data error
184 | */
185 |
186 | SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
187 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
188 |
189 |
190 | /* ---------- Buffer Interface ---------- */
191 |
192 | /* It's zlib-like interface.
193 | See LzmaDec_DecodeToDic description for information about STEPS and return results,
194 | but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
195 | to work with CLzmaDec variables manually.
196 |
197 | finishMode:
198 | It has meaning only if the decoding reaches output limit (*destLen).
199 | LZMA_FINISH_ANY - Decode just destLen bytes.
200 | LZMA_FINISH_END - Stream must be finished after (*destLen).
201 | */
202 |
203 | SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
204 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
205 |
206 |
207 | /* ---------- One Call Interface ---------- */
208 |
209 | /* LzmaDecode
210 |
211 | finishMode:
212 | It has meaning only if the decoding reaches output limit (*destLen).
213 | LZMA_FINISH_ANY - Decode just destLen bytes.
214 | LZMA_FINISH_END - Stream must be finished after (*destLen).
215 |
216 | Returns:
217 | SZ_OK
218 | status:
219 | LZMA_STATUS_FINISHED_WITH_MARK
220 | LZMA_STATUS_NOT_FINISHED
221 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
222 | SZ_ERROR_DATA - Data error
223 | SZ_ERROR_MEM - Memory allocation error
224 | SZ_ERROR_UNSUPPORTED - Unsupported properties
225 | SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
226 | */
227 |
228 | SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
229 | const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
230 | ELzmaStatus *status, ISzAllocPtr alloc);
231 |
232 | EXTERN_C_END
233 |
234 | #endif
235 |
--------------------------------------------------------------------------------
/lzma/LzmaEnc.h:
--------------------------------------------------------------------------------
1 | /* LzmaEnc.h -- LZMA Encoder
2 | 2017-07-27 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __LZMA_ENC_H
5 | #define __LZMA_ENC_H
6 |
7 | #include "7zTypes.h"
8 |
9 | EXTERN_C_BEGIN
10 |
11 | #define LZMA_PROPS_SIZE 5
12 |
13 | typedef struct _CLzmaEncProps
14 | {
15 | int level; /* 0 <= level <= 9 */
16 | UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
17 | (1 << 12) <= dictSize <= (3 << 29) for 64-bit version
18 | default = (1 << 24) */
19 | int lc; /* 0 <= lc <= 8, default = 3 */
20 | int lp; /* 0 <= lp <= 4, default = 0 */
21 | int pb; /* 0 <= pb <= 4, default = 2 */
22 | int algo; /* 0 - fast, 1 - normal, default = 1 */
23 | int fb; /* 5 <= fb <= 273, default = 32 */
24 | int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
25 | int numHashBytes; /* 2, 3 or 4, default = 4 */
26 | UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
27 | unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
28 | int numThreads; /* 1 or 2, default = 2 */
29 |
30 | UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
31 | Encoder uses this value to reduce dictionary size */
32 | } CLzmaEncProps;
33 |
34 | void LzmaEncProps_Init(CLzmaEncProps *p);
35 | void LzmaEncProps_Normalize(CLzmaEncProps *p);
36 | UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
37 |
38 |
39 | /* ---------- CLzmaEncHandle Interface ---------- */
40 |
41 | /* LzmaEnc* functions can return the following exit codes:
42 | SRes:
43 | SZ_OK - OK
44 | SZ_ERROR_MEM - Memory allocation error
45 | SZ_ERROR_PARAM - Incorrect paramater in props
46 | SZ_ERROR_WRITE - ISeqOutStream write callback error
47 | SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
48 | SZ_ERROR_PROGRESS - some break from progress callback
49 | SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
50 | */
51 |
52 | typedef void * CLzmaEncHandle;
53 |
54 | CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
55 | void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
56 |
57 | SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
58 | void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
59 | SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
60 | unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
61 |
62 | SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
63 | ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
64 | SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
65 | int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
66 |
67 |
68 | /* ---------- One Call Interface ---------- */
69 |
70 | SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
71 | const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
72 | ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
73 |
74 | EXTERN_C_END
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/lzma/Precomp.h:
--------------------------------------------------------------------------------
1 | /* Precomp.h -- StdAfx
2 | 2013-11-12 : Igor Pavlov : Public domain */
3 |
4 | #ifndef __7Z_PRECOMP_H
5 | #define __7Z_PRECOMP_H
6 |
7 | #define _7ZIP_ST
8 | #include "Compiler.h"
9 | /* #include "7zTypes.h" */
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/lzma/lzma_decompress.c:
--------------------------------------------------------------------------------
1 | // #include
2 | #include
3 | #include
4 | #include
5 | #include "bs_user_interface.h"
6 | #include "LzmaDec.h"
7 | #include "LzmaEnc.h"
8 | #include "7zFile.h"
9 | #include "vFile.h"
10 | #include "mylib.h"
11 |
12 | //#define LZMA_RAM_USE_DEBUG
13 |
14 | #ifdef LZMA_RAM_USE_DEBUG
15 | static int ram_used_size = 0;
16 | static int ram_used_max = 0;
17 | #endif
18 |
19 | void *lzma_alloc(ISzAllocPtr p, size_t size)
20 | {
21 | void *mp;
22 |
23 | if (size == 0)
24 | {
25 | return NULL;
26 | }
27 |
28 | mp = vmalloc(size);
29 |
30 | #ifdef LZMA_RAM_USE_DEBUG
31 | ram_used_size += _msize(mp);
32 | if (ram_used_max < ram_used_size)ram_used_max = ram_used_size;
33 | printk("ram used: now / max = %d / %d\n", ram_used_size, ram_used_max);
34 | #endif
35 |
36 | return mp;
37 | }
38 |
39 | void lzma_free(ISzAllocPtr p, void *address)
40 | {
41 | if (address != NULL)
42 | {
43 | #ifdef LZMA_RAM_USE_DEBUG
44 | ram_used_size -= _msize(address);
45 | printk("ram used: now / max = %d / %d\n", ram_used_size, ram_used_max);
46 | #endif
47 | vfree(address);
48 | }
49 | }
50 |
51 | ISzAlloc allocator = {lzma_alloc, lzma_free};
52 | static CLzmaDec *lz_state = NULL;
53 |
54 | static int lzma_decompress_init(vFile *pf)
55 | {
56 | if (lz_state != NULL) return 0;
57 |
58 | extern ISzAlloc allocator;
59 | UInt64 unpack_size = 0;
60 | uint8_t header[LZMA_PROPS_SIZE + 8];;
61 | size_t headerSize = sizeof(header);
62 |
63 | vfread(pf, header, headerSize);
64 | // debug_array(header, headerSize);
65 | // for (char i = 0; i < 8; i++)
66 | // {
67 | // unpack_size |= (UInt64)(header[LZMA_PROPS_SIZE + i] << (i * 8));
68 | // }
69 | /* 以下为过静态检查写法 */
70 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 0]) << 0;
71 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 1]) << 8;
72 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 2]) << 16;
73 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 3]) << 24;
74 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 4]) << 32;
75 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 5]) << 40;
76 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 6]) << 48;
77 | unpack_size |= ((uint64_t)header[LZMA_PROPS_SIZE + 7]) << 56;
78 | // bs_printf("unpack_size:0X%08X", unpack_size);
79 |
80 | //分配解码内存
81 | lz_state = (CLzmaDec *)lzma_alloc(NULL, sizeof(CLzmaDec));
82 |
83 | if (lz_state != NULL)
84 | {
85 | LzmaDec_Construct(lz_state);
86 | LzmaDec_Allocate(lz_state, header, LZMA_PROPS_SIZE, &allocator);
87 | LzmaDec_Init(lz_state);
88 |
89 | return 0;
90 | }
91 | else
92 | {
93 | bs_printf("lzma_alloc err");
94 | }
95 |
96 | return -1;
97 | }
98 |
99 | int lzma_decompress_read(vFile *pf, uint8_t *buffer, int size)
100 | {
101 | /* Start to decompress file */
102 | uint32_t position, file_size;
103 | size_t dcmprs_size = 0;
104 | uint8_t *inBuf;
105 | SizeT inProcessed;
106 | SizeT outProcessed = size;
107 | ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
108 | ELzmaStatus status;
109 | SRes res;
110 |
111 | res = lzma_decompress_init(pf);
112 | if (res != 0)
113 | {
114 | bs_printf("err%d", __LINE__);
115 | }
116 |
117 | //获取当前文件读指针
118 | inBuf = vfgetpos(pf, &position);
119 | //检查文件还剩下多少字节
120 | file_size = vfgetlen(pf);
121 | // bs_printf("file_size:%d", file_size);
122 | if ((position + size) > file_size)
123 | {
124 | inProcessed = file_size - position;
125 | }
126 | else
127 | {
128 | inProcessed = size;
129 | }
130 | // bs_printf("inProcessed:%d", inProcessed);
131 |
132 | //解压数据
133 | if (inProcessed > 0 || inProcessed == 0)
134 | {
135 | res = LzmaDec_DecodeToBuf(lz_state, buffer, &outProcessed, inBuf, &inProcessed, finishMode, &status);
136 | // debug_array((uint8_t *)lz_state, 200);
137 | // debug_array(buffer, 255);
138 | // bs_printf("outProcessed: %d", outProcessed);
139 | // debug_array(inBuf, 255);
140 | // bs_printf("inProcessed: %d", inProcessed);
141 | // bs_printf("finishMode: %d", finishMode);
142 | // bs_printf("status: %d", status);
143 | // bs_printf("LzmaDec_DecodeToBuf res: %d", res);
144 | if (res)
145 | {
146 | // bs_printf("err%d,res: %d", __LINE__, res);
147 | }
148 | dcmprs_size = outProcessed;
149 |
150 | //重新设置文件读指针
151 | position += inProcessed;
152 | vfsetpos(pf, position);
153 | }
154 | // bs_printf("dcmprs_size: %d", dcmprs_size);
155 | return dcmprs_size;
156 | }
157 |
158 | void lzma_decompress_finish(void)
159 | {
160 | LzmaDec_Free(lz_state, &allocator);
161 |
162 | if (lz_state != NULL)
163 | {
164 | lzma_free(NULL, lz_state);
165 | lz_state = NULL;
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/lzma/lzma_decompress.h:
--------------------------------------------------------------------------------
1 | #ifndef __LZMA_SAMPLE_H__
2 | #define __LZMA_SAMPLE_H__
3 |
4 | #ifdef __cplusplus
5 | extern "C"
6 | {
7 | #endif
8 | #include
9 | #include "vFile.h"
10 |
11 | int lzma_decompress_read(vFile* pf, uint8_t *buffer, int size);
12 | void lzma_decompress_finish(void);
13 |
14 | #ifdef __cplusplus
15 | }
16 | #endif
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/user/bs_type.h:
--------------------------------------------------------------------------------
1 | #ifndef __TYPE_H__
2 | #define __TYPE_H__
3 | /********************************************************************************************************/
4 | #include
5 | #include
6 | #include
7 |
8 | #ifndef TRUE
9 | #define TRUE 1
10 | #endif
11 |
12 | #ifndef FALSE
13 | #define FALSE 0
14 | #endif
15 |
16 | #ifndef ERROR
17 | #define ERROR 0xFF
18 | #endif
19 |
20 | // typedef unsigned char bool;
21 | // typedef unsigned char uint8_t; /* defined for unsigned 8-bits integer variable 无符号8位整型变量 */
22 | // typedef signed char int8; /* defined for signed 8-bits integer variable 有符号8位整型变量 */
23 | // typedef unsigned short uint16_t; /* defined for unsigned 16-bits integer variable 无符号16位整型变量 */
24 | // typedef signed short int16; /* defined for signed 16-bits integer variable 有符号16位整型变量 */
25 | // typedef unsigned long uint32_t; /* defined for unsigned 32-bits integer variable 无符号32位整型变量 */
26 | // typedef signed long int32; /* defined for signed 32-bits integer variable 有符号32位整型变量 */
27 | // typedef float fp32; /* single precision floating point variable (32bits)单精度浮点数(32位长度) */
28 | // typedef unsigned long long uint64; /* defined for unsigned 64-bits integer variable 无符号64位整型变量 */
29 | // typedef signed long long int64; /* defined for signed 64-bits integer variable 有符号64位整型变量 */
30 | // typedef double fp64; /* double precision floating point variable (64bits)双精度浮点数(64位长度) */
31 | /********************************************************************************************************/
32 | #define BigtoLittle16(x) ((((uint16_t)(x) & 0xff00) >> 8) | (((uint16_t)(x) & 0x00ff) << 8))
33 | #define BigtoLittle32(x) ((((uint32_t)(x) & 0xff000000) >> 24) | \
34 | (((uint32_t)(x) & 0x00ff0000) >> 8) | \
35 | (((uint32_t)(x) & 0x0000ff00) << 8) | \
36 | (((uint32_t)(x) & 0x000000ff) << 24))
37 | /********************************************************************************************************/
38 | //定义一个联合,将一个64位数分拆成4个8位数,以便于计算
39 | //M3内核为小端方式,即低字节在低位,高字节在高位
40 | typedef union
41 | {
42 | uint64_t d64;
43 | uint8_t d8[8];
44 | } U64_U8;
45 | //定义一个联合,将一个64位数分拆成4个8位数,以便于计算
46 | //M3内核为小端方式,即低字节在低位,高字节在高位
47 | typedef union
48 | {
49 | double f64;
50 | uint8_t d8[8];
51 | } F64_U8;
52 | //定义一个联合,将一个32位数分拆成4个8位数,以便于计算
53 | //M3内核为小端方式,即低字节在低位,高字节在高位
54 | typedef union
55 | {
56 | uint32_t d32;
57 | uint8_t d8[4];
58 | } U32_U8;
59 | /********************************************************************************************************/
60 | //定义一个联合,将一个16位数分拆成2个8位数,以便于计算
61 | typedef union
62 | {
63 | uint16_t d16;
64 | uint8_t d8[2];
65 | } U16_U8;
66 | /********************************************************************************************************/
67 | //定义一个联合,将一个16位数分拆成2个8位数,以便于计算
68 | typedef union
69 | {
70 | int16_t d16;
71 | uint8_t d8[2];
72 | } I16_U8;
73 | /********************************************************************************************************/
74 | #endif
75 |
--------------------------------------------------------------------------------
/user/bs_user_interface.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @file bs_user_func.c
3 | * @author your name (you@domain.com)
4 | * @brief
5 | * @version 0.1
6 | * @date 2022-11-09
7 | *
8 | * @copyright Copyright (c) 2022
9 | *
10 | */
11 | #include "bs_user_interface.h"
12 | #include "bs_type.h"
13 |
14 | bs_user_interface bs_user_func;
15 |
16 | /**
17 | * @brief 用户需要注册的函数
18 | *
19 | * @param user_func 用户创建一个结构体然后将功能依次注册
20 | * @return 0成功 1失败
21 | */
22 | int bs_user_func_register(bs_user_interface *user_func)
23 | {
24 | if (user_func == NULL || user_func->bs_flash_write == NULL
25 | || user_func->bs_malloc == NULL
26 | || user_func->bs_free == NULL
27 | )
28 | {
29 | return 1;
30 | }
31 | bs_user_func.bs_flash_write = user_func->bs_flash_write;
32 | bs_user_func.bs_malloc = user_func->bs_malloc;
33 | bs_user_func.bs_free = user_func->bs_free;
34 | return 0;
35 | }
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/user/bs_user_interface.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file bs_user_func.h
3 | * @author your name (you@domain.com)
4 | * @brief
5 | * @version 0.1
6 | * @date 2022-11-09
7 | *
8 | * @copyright Copyright (c) 2022
9 | *
10 | */
11 |
12 | #ifndef __USER_INTERFACE_H_
13 | #define __USER_INTERFACE_H_
14 |
15 | #include
16 | #include
17 | #include "bs_type.h"
18 | #include "bspatch.h"
19 | #include "crc32.h"
20 |
21 | #ifdef __DEBUG
22 | #define bs_printf(...) printf("\r\n"format, ##__VA_ARGS__)
23 | #else
24 | #define bs_printf(...)
25 | #endif
26 |
27 | #define IH_NMLEN (32 - 4) /* Image Name Length */
28 | typedef struct image_header
29 | {
30 | uint32_t ih_magic; /* Image Header Magic Number */
31 | uint32_t ih_hcrc; /* Image Header CRC Checksum 差分包包头校验 大端 */
32 | uint32_t ih_time; /* Image Creation Timestamp */
33 | uint32_t ih_size; /* Image Data Size 差分包的大小 大端 */
34 | uint32_t ih_load; /* Data Load Address 上一版本旧文件的大小 */
35 | uint32_t ih_ep; /* Entry Point Address 要升级的新文件的大小 */
36 | uint32_t ih_dcrc; /* Image Data CRC Checksum 新文件的CRC 大端 */
37 | uint8_t ih_os; /* Operating System */
38 | uint8_t ih_arch; /* CPU architecture */
39 | uint8_t ih_type; /* Image Type */
40 | uint8_t ih_comp; /* Compression Type */
41 | uint8_t ih_name[IH_NMLEN]; /* Image Name */
42 | uint32_t ih_ocrc; /* Old Image Data CRC Checksum 上一版本旧文件的CRC 大端*/
43 | } image_header_t;
44 |
45 | /**
46 | * @brief 用户需注册的flash写入功能函数,bs会调用该函数写入用户的flash,特别注意在写入之前
47 | * 用户需要擦除,也就是该函数需自带擦除功能
48 | * @param addr bs将要写入的flash地址
49 | * @param p bs传入要写入的内容
50 | * @param len bs传入要写的长度
51 | * @return int 0代表成功,其他为错误码
52 | */
53 | typedef int (*bs_flash_write_func)(uint32_t addr, const unsigned char *p, uint32_t len);
54 |
55 | /**
56 | * @brief 用户需注册的内存申请函数,bs会调用该函数申请内存,请注意,最大可能会申请20k左右堆空间
57 | * @param size 要申请的内存大小
58 | * @return void* 返回非NULL代表成功
59 | */
60 | typedef void *(*bs_malloc_func)(uint32_t size);
61 |
62 | /**
63 | * @brief 用户需注册的内存释放函数,bs会调用该函数释放内存
64 | * @param ptr 要释放的内存地址
65 | */
66 | typedef void (*bs_free_func)(void *ptr);
67 |
68 | typedef struct
69 | {
70 | bs_flash_write_func bs_flash_write;
71 | bs_malloc_func bs_malloc;
72 | bs_free_func bs_free;
73 | } bs_user_interface;
74 | extern bs_user_interface bs_user_func;
75 |
76 |
77 |
78 | /******************************************************************************/
79 | /************************************ 用户提供 *********************************/
80 | /**
81 | * @brief 用户需要注册的函数
82 | *
83 | * @param user_func 用户创建一个结构体然后将功能依次注册
84 | * @return 0成功 1失败
85 | */
86 | int bs_user_func_register(bs_user_interface *user_func);
87 |
88 | /******************************************************************************/
89 | /************************************ 用户接口 *********************************/
90 | /**
91 | * @brief 解压并还原文件,用户使用差分升级时唯一需要关心的接口
92 | *
93 | * @param old 设备中执行区代码所在的地址,用户可指定flash执行区的地址,方便算法读出来当前
94 | * 运行中的代码,用户提供
95 | * @param oldsize 设备中执行区代码的长度,用户可在差分包bin头获取,用户提供
96 | * @param patch 设备中已经下载的差分包所在的flash地址,或者ram地址,只要能让算法读出来即可
97 | * 注意,下载的差分包自带image_header_t格式的文件头,真正的差分包需要偏
98 | * 移sizeof(image_header_t)的长度,用户提供
99 | * @param patchsize 设备中已经下载的差分包的长度,用户提供,可在差分包bin头获取
100 | * @param newfile_addr 还原后的bin写入的地址,用户提供
101 | * @return int 还原的文件大小
102 | */
103 | extern int iap_patch(const uint8_t *old, uint32_t oldsize, const uint8_t *patch,
104 | uint32_t patchsize, uint32_t newfile_addr);
105 |
106 | /* bs所使用到的crc32校验函数,用户可酌情使用 */
107 | extern unsigned int crc32( const unsigned char *buf, unsigned int size);
108 |
109 | #endif // !__USER_INTERFACE_H_
110 |
111 |
--------------------------------------------------------------------------------