рдЬрд┐рдк рдлрд╛рдЗрд▓реЗрдВ: рдЗрддрд┐рд╣рд╛рд╕, рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди



рдореИрдВ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдбреЗрдЯрд╛ рдХреИрд╕реЗ рд╕рдВрдкреАрдбрд╝рд┐рдд рд╣реИред рдПрдХ рдмрд╛рд░ рдЬрдм рдореИрдВрдиреЗ рдЕрдкрдиреА рдЬрд┐рдЬреНрдЮрд╛рд╕рд╛ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛: рдпрд╣ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╕рдВрдкреАрдбрд╝рди рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдЬрд╝рд┐рдк рдХрд╛рд░реНрдпрдХреНрд░рдо рд▓рд┐рдЦреЗрдВред рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдПрдХ рд░реЛрдорд╛рдВрдЪрдХ рдЕрднреНрдпрд╛рд╕ рдмрди рдЧрдпрд╛ рд╣реИред рдЖрдкрдХреЛ рдбреАрдмрдЧ рдХреА рдЧрдИ рдорд╢реАрди рдмрдирд╛рдиреЗ рд╕реЗ рдмрд╣реБрдд рдЦреБрд╢реА рдорд┐рд▓рддреА рд╣реИ рдЬреЛ рдбреЗрдЯрд╛ рд▓реЗрддреА рд╣реИ, рдЕрдкрдиреЗ рдмрд┐рдЯреНрд╕ рдХреЛ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреА рд╣реИ, рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдЗрдХрдЯреНрдард╛ рдХрд░рддреА рд╣реИред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЖрдк рднреА рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрдврд╝рдиреЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд▓реЗрдВрдЧреЗред

рд▓реЗрдЦ рдмрд╣реБрдд рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдЬрд╝рд┐рдк рдлрд╛рдЗрд▓реЗрдВ рдФрд░ рд╕рдВрдкреАрдбрд╝рди рдпреЛрдЬрдирд╛ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИ: LZ77 рд╕рдВрдкреАрдбрд╝рди, рд╣рдлрд╝рдореИрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо, рдбреАрдлрд╝реНрд▓реИрдЯ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдФрд░ рдмрд╣реБрдд рдХреБрдЫред рдЖрдк рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХреЛ рдЬрд╛рдиреЗрдВрдЧреЗ рдФрд░ рд╕реА рдореЗрдВ рдЦрд░реЛрдВрдЪ рд╕реЗ рд▓рд┐рдЦреЗ рдЧрдП рдкреНрд░рднрд╛рд╡реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рджреЗрдЦреЗрдВрдЧреЗ ред рд╕реНрд░реЛрдд рдХреЛрдб рдпрд╣рд╛рдБ рд╣реИ: hwzip-1.0.zip ред

рдореИрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЖрднрд╛рд░реА рд╣реВрдБ Ange рдПрд▓реНрдмрд░реНрдЯрд┐рдиреА , Gynvael Coldwind , рдлреИрдмрд┐рдпрди Giesen , рдЬреЛрдирд╛рд╕ Skeppstedt ( рд╡реЗрдм ), Primiano Tucci рдФрд░ рдирд┐рдХреЛ рд╡реЗрдмрд░ , рдЬреЛ рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдбреНрд░рд╛рдлреНрдЯ рдкрд░ рдмрд╣реБрдореВрд▓реНрдп рд░рд╛рдп рджреЗ рджреА рд╣реИред

рд╕рд╛рдордЧреНрд░реА



рдХрд╣рд╛рдиреА


PKZip


рдЕрд╕реНрд╕реА рдФрд░ рд╢реБрд░реБрдЖрддреА рдирдмреНрдмреЗ рдХреЗ рджрд╢рдХ рдореЗрдВ, рдЗрдВрдЯрд░рдиреЗрдЯ рдХреЗ рд╡реНрдпрд╛рдкрдХ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдХрдВрдкреНрдпреВрдЯрд░ рдХреЗ рдЙрддреНрд╕рд╛рд╣реА рд▓реЛрдЧреЛрдВ рдиреЗ рдЯреЗрд▓реАрдлреЛрди рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмреБрд▓реЗрдЯрд┐рди рдмреЛрд░реНрдб рд╕рд┐рд╕реНрдЯрдо (рдмреАрдмреАрдПрд╕) рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдЬреБрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд╛рдпрд▓-рдЕрдк рдореЛрдбреЗрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред BBS рдПрдХ рдЗрдВрдЯрд░реИрдХреНрдЯрд┐рд╡ рдХрдВрдкреНрдпреВрдЯрд░ рд╕рд┐рд╕реНрдЯрдо рдерд╛ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ, рдЧреЗрдо рдЦреЗрд▓рдиреЗ рдФрд░ рдлрд╝рд╛рдЗрд▓реЗрдВ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рдерд╛ред рдСрдирд▓рд╛рдЗрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдВрдкреНрдпреВрдЯрд░, рдореЙрдбреЗрдо рдФрд░ рдПрдХ рдЕрдЪреНрдЫрд╛ BBS рдлрд╝реЛрди рдирдВрдмрд░ рд╣реЛрдирд╛ рдкрд░реНрдпрд╛рдкреНрдд рдерд╛ред рдХрдВрдкреНрдпреВрдЯрд░ рдкрддреНрд░рд┐рдХрд╛рдУрдВ рдореЗрдВ рдФрд░ рдЕрдиреНрдп рдмреАрдмреАрдПрд╕ рдкрд░ рдирдВрдмрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд┐рдП рдЧрдП рдереЗ ред

рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд╡рд┐рддрд░рдг рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЙрдкрдХрд░рдг рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ рдерд╛ ред рдпрд╣ рдЖрдкрдХреЛ рдПрдХрд▓ рд╕рдВрдЧреНрд░рд╣ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИрдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд░реВрдк рд╕реЗ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдпрд╛ рд╕реВрдЪрдирд╛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдФрд░ рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ, рд╕рдВрдЧреНрд░рд╣ рднреА рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рд╕рдВрдЪрд░рдг рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рди рдФрд░ рд╕рдордп рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░рддрд╛ рд╣реИред рдмреАрдмреАрдПрд╕ рдХреЗ рджрд┐рдиреЛрдВ рдореЗрдВ, рдЖрд░реНрдХ рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ рд▓реЛрдХрдкреНрд░рд┐рдп рдерд╛, рдЬрд┐рд╕реЗ рдЯреЙрдо рд╣рд┐рдВрдбрд░реНрд╕рди рдСрдл рд╕рд┐рд╕реНрдЯрдо рдПрдиреНрд╣рд╛рдВрд╕рдореЗрдВрдЯ рдПрд╕реЛрд╕рд┐рдПрдЯреНрд╕ (рдПрд╕рдИрдП) рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛, рдПрдХ рдЫреЛрдЯреА рд╕реА рдХрдВрдкрдиреА рдЬрд┐рд╕реЗ рдЙрдиреНрд╣реЛрдВрдиреЗ рдЕрдкрдиреЗ рдмрд╣рдиреЛрдИ рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдерд╛ред

1980 рдХреЗ рджрд╢рдХ рдХреЗ рдЙрддреНрддрд░рд╛рд░реНрдз рдореЗрдВ, рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдлрд┐рд▓ рдХрд╛рдЯреНрдЬ рдиреЗ рдЖрд░реНрдХ, PKArc рдХрд╛ рдЕрдкрдирд╛ рд╕рдВрд╕реНрдХрд░рдг рдЬрд╛рд░реА рдХрд┐рдпрд╛ред рдпрд╣ рдПрд╕рдИрдП рдЖрд░реНрдХ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рдерд╛, рд▓реЗрдХрд┐рди рдЗрд╕рдиреЗ рдЕрд╕реЗрдВрдмрд▓реА рднрд╛рд╖рд╛ рдореЗрдВ рд▓рд┐рдЦрд┐рдд рд╕рдмрд░реВрдЯреАрдиреНрд╕ рдХреЗ рд▓рд┐рдП рддреЗрдЬреА рд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдФрд░ рдПрдХ рдирдИ рд╕рдВрдкреАрдбрд╝рди рд╡рд┐рдзрд┐ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ред рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд░рдо рд▓реЛрдХрдкреНрд░рд┐рдп рд╣реЛ рдЧрдпрд╛, рдХрд╛рдЯреНрдЬрд╝ рдиреЗ рдЕрдкрдиреА рдиреМрдХрд░реА рдЫреЛрдбрд╝ рджреА рдФрд░ рдкреАрдХреЗрд╡реЗрдпрд░ рдХреЛ рдЖрдЧреЗ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ред рдХрд┐рдВрд╡рджрдВрддреА рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдЬреНрдпрд╛рджрд╛рддрд░ рдХрд╛рдо рд╡рд┐рд╕реНрдХреЙрдиреНрд╕рд┐рди рдХреЗ рдЧреНрд▓реЗрдирдбреЗрд▓ рдореЗрдВ рдЙрдирдХреА рдорд╛рдВ рдХреА рд░рд╕реЛрдИ рдореЗрдВ рд╣реБрдЖред


рдорд┐рд▓реНрд╡реМрдХреА рдкреНрд░рд╣рд░реА рдХреЗ рдПрдХ рд▓реЗрдЦ рд╕реЗ рдлрд┐рд▓ рдХрд╛рдЯреНрдЬ рджреНрд╡рд╛рд░рд╛ рдлреЛрдЯреЛ , 19 рд╕рд┐рддрдВрдмрд░, 1994ред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрд╕рдИрдП рдХрд╛рдЯреНрдЬ рдХреА рдкрд╣рд▓ рд╕реЗ рдЦреБрд╢ рдирд╣реАрдВ рдерд╛ред рдХрдВрдкрдиреА рдиреЗ рдЙрди рдкрд░ рдЯреНрд░реЗрдбрдорд╛рд░реНрдХ рдФрд░ рдХреЙрдкреАрд░рд╛рдЗрдЯ рдХреЗ рдЙрд▓реНрд▓рдВрдШрди рдХрд╛ рдЖрд░реЛрдк рд▓рдЧрд╛рдпрд╛ред рдмреАрдмреАрдПрд╕ рдиреЗрдЯрд╡рд░реНрдХ рдФрд░ рдкреАрд╕реА рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ рдореБрдХрджрдореЗрдмрд╛рдЬреА рдФрд░ рд╡рд┐рд╡рд╛рдж рдХреЛ рдЖрд░реНрдХ рд╡реЙрд░реНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдЕрдВрдд рдореЗрдВ, рдПрд╕рдИрдП рдХреЗ рдкрдХреНрд╖ рдореЗрдВ рд╡рд┐рд╡рд╛рдж рдХрд╛ рдирд┐рдкрдЯрд╛рд░рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ ред

рдЖрд░реНрдХ рдХреЛ рддреНрдпрд╛рдЧрдХрд░, рдХрд╛рдЯреНрдЬрд╝ рдиреЗ 1989 рдореЗрдВ рдПрдХ рдирдпрд╛ рд╕рдВрдЧреНрд░рд╣ рдкреНрд░рд╛рд░реВрдк рддреИрдпрд╛рд░ рдХрд┐рдпрд╛, рдЬрд┐рд╕реЗ рдЙрдиреНрд╣реЛрдВрдиреЗ рдЬрд╝рд┐рдк рдХрд╣рд╛ рдФрд░ рдЬрдирддрд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рдХрд░рд╛рдпрд╛ :

, , , . , ".ZIP", , , , , , , , , .

рдРрд╕реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдЯрдЬрд╝ рдХреЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ PKZip рдХрд╣рд╛ рдЧрдпрд╛ рдФрд░ рдЬрд▓реНрдж рд╣реА рдпрд╣ BBS рдФрд░ PC рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ рдлреИрд▓ рдЧрдпрд╛ред

рдЬрд╝рд┐рдк рдкреНрд░рд╛рд░реВрдк рдХреА рд╕рдлрд▓рддрд╛ рдореЗрдВ рдпреЛрдЧрджрд╛рди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдкрд╣рд▓реБрдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░рд▓реЗрдЦрди PKZip, рдПрдкреНрд▓реАрдХреЗрд╢рди рдиреЛрдЯ рдХреЗ рд╕рд╛рде рдЖрдпрд╛ рдерд╛ , рдЬрд┐рд╕рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдХрд┐ рдкреНрд░рд╛рд░реВрдк рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдиреЗ рджреВрд╕рд░реЛрдВ рдХреЛ рдкреНрд░рд╛рд░реВрдк рд╕реАрдЦрдиреЗ рдФрд░ рдРрд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреА рдЬреЛ рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ, рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ, рдпрд╛ рдЕрдиреНрдпрдерд╛ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рддреЗ рд╣реИрдВред

рдЬрд╝рд┐рдк - рдиреБрдХрд╕рд╛рди рдХреЗ рдмрд┐рдирд╛ рдПрдХ рд╕рдВрдкреАрдбрд╝рди рдкреНрд░рд╛рд░реВрдк : рдбреЗрдЯрд╛ рдХреЛ рдЕрдирдкреИрдХ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╕рдВрдкреАрдбрд╝рди рд╕реЗ рдкрд╣рд▓реЗ рдЬреИрд╕рд╛ рд╣реЛрдЧрд╛ред рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдореЗрдВ рдЕрддрд┐рд░реЗрдХ рдХреА рддрд▓рд╛рд╢ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдзрд┐рдХ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣рд╛рдирд┐рдкреВрд░реНрдг рд╕рдВрдкреАрдбрд╝рди рд╕реЗ рдЕрд▓рдЧ рд╣реИ ред, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ JPEG рдФрд░ MP3 рдЬреИрд╕реЗ рдкреНрд░рд╛рд░реВрдкреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдЬрдм рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХреБрдЫ рдЬрд╛рдирдХрд╛рд░реА рдЬреЛ рдорд╛рдирд╡ рдЖрдВрдЦ рдпрд╛ рдХрд╛рди рдХреЗ рд▓рд┐рдП рдХрдо рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реЛрддреА рд╣реИ, рдлреЗрдВрдХ рджреА рдЬрд╛рддреА рд╣реИред

PKZip рдХреЛ рд╢реЗрдпрд░рд╡реЗрдпрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛: рдЗрд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдФрд░ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд▓реЗрдЦрдХ рдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ "рд░рдЬрд┐рд╕реНрдЯрд░" рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ред $ 47 рдХреЗ рд▓рд┐рдП, рдЖрдк рдореБрджреНрд░рд┐рдд рдирд┐рд░реНрджреЗрд╢, рдкреНрд░реАрдорд┐рдпрдо рд╕рдорд░реНрдерди рдФрд░ рдРрдк рдХрд╛ рдПрдХ рдмрдврд╝рд╛рдпрд╛ рд╕рдВрд╕реНрдХрд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


PKZip рдХреЗ рдкреНрд░рдореБрдЦ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ 2.04c рдерд╛, рдЬрд┐рд╕реЗ 28 рджрд┐рд╕рдВрдмрд░, 1992 рдХреЛ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ (рдХреБрдЫ рд╣реА рд╕рдордп рдмрд╛рдж рд╕рдВрд╕реНрдХрд░рдг 2.04g рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ )ред рдЗрд╕рдореЗрдВ рдбрд┐рдлреЙрд▓реНрдЯ рдбрд┐рдлреНрд▓реЗрдЯ рдЕрд▓реНрдЧреЛрд░рд┐рджреНрдо рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ред рд╕рдВрд╕реНрдХрд░рдг рдиреЗ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ ( рд░рд┐рд▓реАрдЬ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд▓реЗрдЦ ) рдореЗрдВ рд╕рдВрдкреАрдбрд╝рди рдХреЗ рдЖрдЧреЗ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ ред


рддрдм рд╕реЗ, рдХрдИ рдЕрдиреНрдп рдлрд╝рд╛рдЗрд▓ рд╕реНрд╡рд░реВрдкреЛрдВ рдореЗрдВ рдЬрд╝рд┐рдк рдкреНрд░рд╛рд░реВрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрд╛рд╡рд╛ рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ (.jar), рдПрдВрдбреНрд░реЙрдЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреИрдХреЗрдЬ (.apk), рдФрд░ Microsoft Office .docx рдлрд╛рдЗрд▓реЗрдВ рдЬрд╝рд┐рдк рдкреНрд░рд╛рд░реВрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИрдВред рдХрдИ рдкреНрд░рд╛рд░реВрдк рдФрд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╕рдорд╛рди рд╕рдВрдкреАрдбрд╝рди рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдбреАрдлрд╝реНрд▓реИрдЯ рдХрд░рддреЗ рд╣реИрдВред рдХрд╣рддреЗ рд╣реИрдВ, рд╡реЗрдм рдкреЗрдЬ рд╢рд╛рдпрдж рдЖрдкрдХреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдПрдХ gzip рдлрд╝рд╛рдЗрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ Deflate рд╕рдВрдкреАрдбрд╝рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдлрд┐рд▓ рдХрд╛рдЯреНрдЬ рдХрд╛ рдирд┐рдзрди 2000 рдореЗрдВ рд╣реБрдЖ рдерд╛ред PKWare рдЕрднреА рднреА рдореМрдЬреВрдж рд╣реИ рдФрд░ рдЬрд╝рд┐рдк рдкреНрд░рд╛рд░реВрдк рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдХрдВрдкрдиреА рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдбреЗрдЯрд╛ рд╕реБрд░рдХреНрд╖рд╛ рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рддреА рд╣реИред

рдЬрд╛рдирдХрд╛рд░реА- zip рдФрд░ zlib


1989 рдореЗрдВ PKZip рдХреА рд░рд┐рд▓реАрдЬрд╝ рдХреЗ рдХреБрдЫ рд╕рдордп рдмрд╛рдж, рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЕрдирдкреИрдХ рдХрд░рдиреЗ рдХреЗ рдЕрдиреНрдп рдХрд╛рд░реНрдпрдХреНрд░рдо рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд▓рдЧреЗред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдЕрдирдЬрд╝рд┐рдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЬреЛ рдпреВрдирд┐рдХреНрд╕ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдЕрдирдкреИрдХ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдорд╛рд░реНрдЪ 1990 рдореЗрдВ, Info-ZIP рдирд╛рдордХ рдПрдХ рдореЗрд▓рд┐рдВрдЧ рд╕реВрдЪреА рдмрдирд╛рдИ рдЧрдИ рдереАред Info-ZIP

рд╕рдореВрд╣ рдиреЗ рдореБрдлреНрдд рдУрдкрди рд╕реЛрд░реНрд╕ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЕрдирдЬрд╝рд┐рдк рдФрд░ рдЬрд╝рд┐рдк рдЬрд╛рд░реА рдХрд┐рдП рд╣реИрдВ , рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЕрдирдкреИрдХ рдХрд░рдиреЗ рдФрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдХреЛрдб рдХреЛ рдХрдИ рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдореЗрдВ рдкреЛрд░реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдЕрднреА рднреА рдпреВрдирд┐рдХреНрд╕ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рдЬрд┐рдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рд▓рд┐рдП рдорд╛рдирдХ рд╣реИред рдЗрд╕рдиреЗ рдмрд╛рдж рдореЗрдВ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рдмрдврд╝рд╛рдиреЗ рдореЗрдВ рдорджрдж рдХреАред рдПрдХ рдмрд╛рд░ рд╕реВрдЪрдирд╛-рдЬрд╝рд┐рдк рдХреЛрдб рдЬрд┐рд╕рдиреЗ рдЕрдкрд╕реНрдлреАрддрд┐ рдФрд░ рдЕрдкрдШрдЯрди рдХреЛ рдЕрдкрд╡рд┐рддреНрд░ рдХрд┐рдпрд╛, рдПрдХ рдЕрд▓рдЧ рдЬрд╝реНрд▓рд┐рдм рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рд▓реЗ рдЬрд╛рдпрд╛ рдЧрдпрд╛ рдЬреЛ рдЙрдиреНрд╣реЛрдВрдиреЗ рд▓рд┐рдЦрд╛ рдерд╛

рдЬреАрди-рд▓реВрдк рдЧреЗрд▓реНрд▓реА (рд╕рдВрдкреАрдбрд╝рди) рдФрд░ рдорд╛рд░реНрдХ рдПрдбрд▓рд░ (рдЕрдирдкреИрдХрд┐рдВрдЧ)ред


2009 рдХреЗ USENIX STUG рдЕрд╡рд╛рд░реНрдб рдореЗрдВ рдЬреАрди- рд▓рд╛рдЙрдк рдЧреЗрд▓реНрд▓реА (рдмрд╛рдПрдВ) рдФрд░ рдорд╛рд░реНрдХ рдПрдбрд▓рд░ (рджрд╛рдПрдВ) ред

рдкреБрд╕реНрддрдХрд╛рд▓рдп рдмрдирд╛рдиреЗ рдХреЗ рдХрд╛рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рдерд╛ рдХрд┐ рдпрд╣ рдЕрдиреНрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдФрд░ рдкреНрд░рд╛рд░реВрдкреЛрдВ рдореЗрдВ рдбреАрдлрд╝реНрд▓реИрдЯ рд╕рдВрдкреАрдбрд╝рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рдерд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирдП gzip рдФрд░ PNG рдореЗрдВ ред рдЗрди рдирдП рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдХрдВрдкреНрд░реЗрд╢рди рдФрд░ рдЬреАрдЖрдИрдПрдл рдХреЛ рдмрджрд▓рдирд╛ рдерд╛ , рдЬреЛ рдкреЗрдЯреЗрдВрдЯ-рд╕рдВрд░рдХреНрд╖рд┐рдд рдПрд▓рдЬреЗрдбрдбрдмреНрд▓реНрдпреВ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рдерд╛ред

рдЗрди рд╕реНрд╡рд░реВрдкреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рдПрдХ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ, рдкреАрдЯрд░ рдбрд┐рдлреНрд▓реЗрдЯ рдиреЗ рдбрд┐рдлрд▓реЗрдЯ рд╕реНрдкреЗрд╕рд┐рдлрд┐рдХреЗрд╢рди рд▓рд┐рдЦрд╛ рдФрд░ рдЗрд╕реЗ рдордИ 1996 рдореЗрдВ рдЗрдВрдЯрд░рдиреЗрдЯ рдЖрд░рдПрдлрд╕реА 1951 рдХреЗ рдирд╛рдо рд╕реЗ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд┐рдпрд╛ ред рдпрд╣ рдореВрд▓ PKZip рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдиреЛрдЯ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реБрд▓рдн рд╡рд┐рд╡рд░рдг рдирд┐рдХрд▓рд╛ред

рдЖрдЬ рдЬрд╝рд╛рд▓рд┐рдм рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рд╣рд░ рдЬрдЧрд╣ рд╣реЛрддрд╛ рд╣реИред рд╢рд╛рдпрдж рд╡рд╣ рдЕрдм рдЗрд╕ рдкреГрд╖реНрда рдХреЛ рдПрдХ рд╡реЗрдм рд╕рд░реНрд╡рд░ рдкрд░ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░рдиреЗ рдФрд░ рдЖрдкрдХреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЕрдирдкреИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдЖрдЬ, рдЕрдзрд┐рдХрд╛рдВрд╢ рдЬрд╝рд┐рдк рдлрд╛рдЗрд▓реЗрдВ zlib рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдкреАрдбрд╝рд┐рдд рдФрд░ рд╡рд┐рдШрдЯрд┐рдд рд╣реИрдВред

WinZip


рдЬреЛ рд▓реЛрдЧ PKZip рдирд╣реАрдВ рдЦреЛрдЬ рдкрд╛рдП рдЙрдирдореЗрдВ рд╕реЗ рдХрдИ рдиреЗ WinZip рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдкреАрд╕реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдиреЗ рдбреЙрд╕ рд╕реЗ рд╡рд┐рдВрдбреЛрдЬ рддрдХ, рдФрд░ рдкреАрдХреЗрдЬрд┐рдк рд╕реЗ рд╡рд┐рдирдЬрд┐рдк рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдХрд┐рдпрд╛ред

рдпрд╣ рд╕рдм рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдирд┐рдХреЛ рдореИрдХ рджреНрд╡рд╛рд░рд╛ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реБрдЖ, рдЬрд┐рд╕рдиреЗ рдХрдиреЗрдХреНрдЯрд░реНрд╕-рдореИрдирдлреАрд▓реНрдб, рдХрдиреЗрдХреНрдЯрд┐рдХрдЯ рдореЗрдВ рдореИрдиреНрд╕рдлреАрд▓реНрдб рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдЧреНрд░реБрдк рдореЗрдВ рдУрдПрд╕ / 2 рдХреЗ рд▓рд┐рдП рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдмрдирд╛рдпрд╛ред Nico рдиреЗ рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдореИрдиреЗрдЬрд░ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛, рдпрд╣ OS / 2 рдореЗрдВ рдПрдХ рдЧреНрд░рд╛рдлрд┐рдХрд▓ рдпреВрдЬрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рд╣реИ, рдФрд░ рд╡рд╣ рдЗрд╕ рдмрд╛рдд рд╕реЗ рдкрд░реЗрд╢рд╛рди рдерд╛ рдХрд┐ рдЙрд╕реЗ рд╣рд░ рдмрд╛рд░ рдЬрдм рд╡рд╣ рдЬрд╝рд┐рдк рдлрд╛рдЗрд▓ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рддреЛ рдЙрд╕реЗ рдПрдХ рдлрд╛рдЗрд▓ рдореИрдиреЗрдЬрд░ рд╕реЗ DOS рдХрдорд╛рдВрдб рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рдерд╛ред

рдореИрдХ рдиреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг GUI рдкреНрд░реЛрдЧреНрд░рд╛рдо рд▓рд┐рдЦрд╛, рдЬреЛ рд╕реАрдзреЗ рдЬрд┐рдк рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдореИрдиреЗрдЬрд░ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рдерд╛, рдЗрд╕реЗ PMZip рдирд╛рдо рджрд┐рдпрд╛ рдФрд░ рдЗрд╕реЗ 1990 рдХреЗ рджрд╢рдХ рдореЗрдВ рд╢реЗрдпрд░рд╡реЗрдпрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рд░реА рдХрд┐рдпрд╛ред

рдУрдПрд╕ / 2 рд╕рдлрд▓ рдирд╣реАрдВ рд╣реБрдЖ, рдФрд░ рдкреАрд╕реА рджреБрдирд┐рдпрд╛ рдиреЗ рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлреНрдЯ рд╡рд┐рдВрдбреЛрдЬ рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░ рд▓рд┐рдпрд╛ред 1991 рдореЗрдВ, рдореИрдХ рдиреЗ рд╡рд┐рдВрдбреЛрдЬ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд▓рд┐рдЦрдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рд╕реАрдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдФрд░ рдЙрд╕рдХрд╛ рдкрд╣рд▓рд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЕрдкрдиреЗ рдЬрд╝рд┐рдк рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдПрдХ рдирдП рдУрдПрд╕ рдореЗрдВ рдкреЛрд░реНрдЯ рдХрд░рдирд╛ рдерд╛ред рдЕрдкреНрд░реИрд▓ 1991 рдореЗрдВ, WinZip 1.00 рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рдпрд╣ рдПрдХ 21-рджрд┐рд╡рд╕реАрдп рдкрд░реАрдХреНрд╖рдг рдЕрд╡рдзрд┐ рдФрд░ $ 29 рдХреЗ рдкрдВрдЬреАрдХрд░рдг рд╢реБрд▓реНрдХ рдХреЗ рд╕рд╛рде рд╢реЗрдпрд░рд╡реЗрдпрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╡рд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреА:


WinZip рдХреЗ рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ, PKZip рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реБрдб рдХреЗ рддрд╣рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд▓реЗрдХрд┐рди 1993 рдореЗрдВ рд╕рдВрд╕реНрдХрд░рдг 5.0 рд╕реЗ, рдЬрд╝рд┐рдк-рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рдкреНрд░рддреНрдпрдХреНрд╖ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП Info-ZIP рдХреЗ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд▓рдЧрд╛ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рднреА рдзреАрд░реЗ-рдзреАрд░реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реБрдЖ рд╣реИред


WinZip 6.3 рдХрд╛рд░реНрдпрд╕рдореВрд╣реЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рдВрдбреЛрдЬ 3.11 рдХреЗ рддрд╣рддред

WinZip 1990 рдХреЗ рджрд╢рдХ рдореЗрдВ рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рд╢реЗрдпрд░рд╡реЗрдпрд░ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдерд╛ред рд▓реЗрдХрд┐рди рдЕрдВрдд рдореЗрдВ, рдпрд╣ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдПрдореНрдмреЗрдб рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░рдг рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХрддрд╛ рдЦреЛ рдЧрдпрд╛ред рд╡рд┐рдВрдбреЛрдЬ рдЙрдирдХреЗ рд╕рд╛рде 2001 (рд╡рд┐рдВрдбреЛрдЬ рдПрдХреНрд╕рдкреА) рдХреЗ рд░реВрдк рдореЗрдВ "рд╕рдВрдХреБрдЪрд┐рдд рдлрд╝реЛрд▓реНрдбрд░" рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП DynaZip рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдореИрдХ рдХреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рдирд┐рдХреЛ рдореИрдХ рдХрдореНрдкреНрдпреВрдЯрд┐рдВрдЧ рдХрд╣рд╛ рдЬрд╛рддрд╛ рдерд╛ред 2000 рдореЗрдВ, рдЗрд╕рдХрд╛ рдирд╛рдо рдмрджрд▓рдХрд░ WinZip рдХрдореНрдкреНрдпреВрдЯрд┐рдВрдЧ рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛, рдФрд░ рдЙрди рд╡рд░реНрд╖реЛрдВ рдХреЗ рджреМрд░рд╛рди рдореИрдХ рдиреЗ рдЗрд╕реЗ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ред 2005 рдореЗрдВ, рд╡реЗрдХреНрдЯрд░ рдХреИрдкрд┐рдЯрд▓ рдиреЗ рдХрдВрдкрдиреА рдХреЛ рдмреЗрдЪ рджрд┐рдпрд╛ , рдФрд░ рдЕрдВрдд рдореЗрдВ, рдпрд╣ Corel рдХреЗ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдореЗрдВ рдмрди рдЧрдпрд╛, рдЬреЛ рдЕрднреА рднреА WinZip рдХреЛ рдПрдХ рдЙрддреНрдкрд╛рдж рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рд░реА рдХрд░рддрд╛ рд╣реИред

рд▓реЗрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡ рд╕рдВрдкреАрдбрд╝рди (LZ77)


рдЬрд╝рд┐рдк рд╕рдВрдкреАрдбрд╝рди рдореЗрдВ рджреЛ рдореБрдЦреНрдп рддрддреНрд╡ рд╣реЛрддреЗ рд╣реИрдВ: рд▓реЗрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡ рд╕рдВрдкреАрдбрд╝рди рдФрд░ рд╣рдлрд╝рдореИрди рдХреЛрдбред

рдкрд╛рда рдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдкрд╛рда рдХреЗ рднреАрддрд░ рдЗрди рд╢рдмреНрджреЛрдВ рдХреА рдХрд┐рд╕реНрдореЛрдВ рдХреЗ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд╕рд╛рде рдЖрдо рд╢рдмреНрджреЛрдВ рдпрд╛ рд╡рд╛рдХреНрдпрд╛рдВрд╢реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдмрдирд╛рдИ рдЬрд╛рдП, рдЬрд┐рд╕рдореЗрдВ рд╢рдмреНрджрдХреЛрд╢ рдХреЗ рд▓рд┐рдВрдХ рд╣реЛрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реНрд░реЛрдд рдкрд╛рда рдореЗрдВ рд▓рдВрдмреЗ рд╢рдмреНрдж "рд╕рдВрдкреАрдбрд╝рди" рдХреЛ # 1234 рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ 1234 рд╕реВрдЪреА рдореЗрдВ рд╢рдмреНрдж рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕реЗ рдбрд┐рдХреНрд╢рдирд░реА рдХрдореНрдкреНрд░реЗрд╢рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ред

рд▓реЗрдХрд┐рди рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╕рдВрдкреАрдбрд╝рди рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рдЗрд╕ рдкрджреНрдзрддрд┐ рдореЗрдВ рдХрдИ рдХрдорд┐рдпрд╛рдВ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рдорд┐рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП? рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рд╡рд┐рднрд┐рдиреНрди рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдпрд╣ рдорд╛рдирд╡-рдкрдардиреАрдп рдкрд╛рда рднреА рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдФрд░ рдЕрдЧрд░ рд╢рдмреНрджрдХреЛрд╢ рдХреЛ рд╕рдВрдкреАрдбрд╝рди рдФрд░ рд╡рд┐рдШрдЯрди рдХреЗ рдмреАрдЪ рдЕрдЧреНрд░рд┐рдо рдореЗрдВ рд╕рд╣рдорддрд┐ рдирд╣реАрдВ рд╣реИ, рддреЛ рдЗрд╕реЗ рд╕рдВрдкреАрдбрд╝рд┐рдд рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рд╕рдВрдЧреНрд░рд╣реАрдд рдФрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ рд╕рдВрдкреАрдбрд╝рди рдХреЗ рд▓рд╛рдн рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИред

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдПрдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╕рдорд╛рдзрд╛рди рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдХреЛ рд╢рдмреНрджрдХреЛрд╢ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рдореЗрдВ 1977, рдПрдХ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдЕрдиреБрдХреНрд░рдорд┐рдХ рдбреЗрдЯрд╛ рд╕рдВрдкреАрдбрд╝рди рдХреЗ рд▓рд┐рдП , рдпрд╛рдХреВрдм рдЬреАрд╡ рдФрд░ рдЕрдмреНрд░рд╛рд╣рдо рд▓реЗрдореНрдкреЗрд▓ (рдЬреЛ рдЯреЗрдХреНрдирд┐рдпреЙрди рдореЗрдВ рдХрд╛рдо рдХрд┐рдпрд╛), рдЬрд┐рд╕рдореЗрдВ рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рддреНрд░рд┐рдХ рдХреЗ рдПрдХ рджреГрд╢реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдПрдХ рд╕рдВрдкреАрдбрд╝рди рдпреЛрдЬрдирд╛ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рд░рдЦрд╛:

(, , )

рдЬрд╣рд╛рдБ рд╡реЗ рд╡рд░реНрдгреЛрдВ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд┐рдЫрдбрд╝реА рд╣реБрдИ рдХрдбрд╝реА рдмрдирд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдЖрдк рдореВрд▓ рдкрд╛рда рдореЗрдВ рдкрд┐рдЫрд▓реА рд╕реНрдерд┐рддрд┐ рд╕реЗ рдХреЙрдкреА рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдпрд╣ рдЙрддреНрдкрдиреНрди рдбреЗрдЯрд╛ рдореЗрдВ рдЕрдЧрд▓рд╛ рд╡рд░реНрдг рд╣реИред


рдЕрдмреНрд░рд╛рд╣рдо рд▓реЗрдореНрдкреЗрд▓ рдФрд░ рдЬреИрдХрдм рдЬрд╝рд┐рд╡ред

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрдВрдХреНрддрд┐рдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:

It was the best of times,
it was the worst of times,

рджреВрд╕рд░реА рдкрдВрдХреНрддрд┐ рдореЗрдВ, рдЕрдиреБрдХреНрд░рдо "t the w рдерд╛" рдХреЛ (26, 10, w) рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕реЗ 26 рд╡рд░реНрдгреЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рд╕реЗ 10 рд╡рд░реНрдгреЛрдВ рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдХрд░ рдЕрдХреНрд╖рд░ "w" рдореЗрдВ рдкреБрди: рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрди рдкрд╛рддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЕрднреА рддрдХ рдкреНрд░рдХрдЯ рдирд╣реАрдВ рд╣реБрдП рд╣реИрдВ, рд╢реВрдиреНрдп-рд▓рдВрдмрд╛рдИ рд╡рд╛рд▓реЗ рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреНрд░рд╛рд░рдВрднрд┐рдХ "I" рдХреЛ (0, 0, I) рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЗрд╕ рдпреЛрдЬрдирд╛ рдХреЛ рд▓реЗрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡ рд╕рдВрдкреАрдбрд╝рди, рдпрд╛ LZ77 рд╕рдВрдкреАрдбрд╝рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХреЗ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдЯреНрд░рд┐рдкрд▓реЗрдЯ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдЖрдорддреМрд░ рдкрд░ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╡рд░реНрдг рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ ( , ) рдЬреЛрдбрд╝реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдпрд╣ рд╡рд┐рдХрд▓реНрдк LZSS рд╕рдВрдкреАрдбрд╝рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ )ред рд╢рд╛рдмреНрджрд┐рдХ рдФрд░ рдмреИрдХрд▓рд┐рдВрдХ рдХреИрд╕реЗ рдПрдиреНрдХреЛрдбреЗрдб рд╣реИрдВ рдпрд╣ рдПрдХ рдЕрд▓рдЧ рдореБрджреНрджрд╛ рд╣реИ, рд╣рдо рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╕рдордп рдЗрд╕реЗ рдиреАрдЪреЗ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗрдж рдбрд┐рдлреНрд▓реЗрдЯ ред

рдпрд╣ рд▓рд┐рдЦрд╛рд╡рдЯ:

It was the best of times,
it was the worst of times,
it was the age of wisdom,
it was the age of foolishness,
it was the epoch of belief,
it was the epoch of incredulity,
it was the season of Light,
it was the season of Darkness,
it was the spring of hope,
it was the winter of despair,
we had everything before us,
we had nothing before us,
we were all going direct to Heaven,
we were all going direct the other way

рдЖрдк рдЗрд╕рдореЗрдВ рд╕реЗрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

It was the best of times,
i(26,10)wor(27,24)age(25,4)wisdom(26,20)
foolishnes(57,14)epoch(33,4)belief(28,22)incredulity
(33,13)season(34,4)Light(28,23)Dark(120,17)
spring(31,4)hope(231,14)inter(27,4)despair,
we had everyth(57,4)before us(29,9)no(26,20)
we(12,3)all go(29,4)direct to Heaven
(36,28)(139,3)(83,3)(138,3)way

рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХрд╛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЧреБрдг рдпрд╣ рд╣реИ рдХрд┐ рд╡реЗ рдУрд╡рд░рд▓реИрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рд▓рдВрдмрд╛рдИ рджреВрд░реА рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛрддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

Fa-la-la-la-la

рдЖрдк рдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

Fa-la(3,9)

рдпрд╣ рдЖрдкрдХреЛ рдЕрдЬреАрдм рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд┐рдзрд┐ рдХрд╛рдо рдХрд░рддреА рд╣реИ: рдкрд╣рд▓реЗ рддреАрди "-рдмреА" рдХреЗ рдмрд╛рдЗрдЯреНрд╕ рдХреЙрдкреА рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдирдП рдЙрддреНрдкрдиреНрди рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдЬрд╛рд░реА рд░рд╣рддреА рд╣реИред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреА рд▓рдВрдмрд╛рдИ рдХрд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдХреЛрдбрд┐рдВрдЧ рд╣реИ , рдЬрд┐рд╕рдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рд▓рдВрдмрд╛рдИ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреЗ рднрд╛рдЧ рдХреЛ рдмрд╛рд░-рдмрд╛рд░ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдЧреАрдд рдХреЗ рд▓рд┐рдП Lempel-Ziv рд╕рдВрдкреАрдбрд╝рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЗрдВрдЯрд░реЗрдХреНрдЯрд┐рд╡ рдЙрджрд╛рд╣рд░рдг рдХреЙрд▓рд┐рди рдореЙрд░рд┐рд╕ рджреНрд╡рд╛рд░рд╛ рдПрдХ рд▓реЗрдЦ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдкреЙрдк рд▓рд┐рд░рд┐рдХреНрд╕ рдЕрдзрд┐рдХ рджреЛрд╣рд░рд╛рдП рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ? ред

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реА рдореЗрдВ рдмреИрдХрд▓рд┐рдВрдХ рдХреА рдирдХрд▓ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рдВрднрд╡ рдУрд╡рд░рд▓реИрдк рдХреЗ рдХрд╛рд░рдг, рд╣рдо рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ memcpyрдпрд╛ memmoveред

/* Output the (dist,len) backref at dst_pos in dst. */
static inline void lz77_output_backref(uint8_t *dst, size_t dst_pos,
                                       size_t dist, size_t len)
{
        size_t i;

        assert(dist <= dst_pos && "cannot reference before beginning of dst");

        for (i = 0; i < len; i++) {
                dst[dst_pos] = dst[dst_pos - dist];
                dst_pos++;
        }
}

рд╢рд╛рдмреНрджрд┐рдХ рд╕реГрдЬрди рдЖрд╕рд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдкреВрд░реНрдгрддрд╛ рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:

/* Output lit at dst_pos in dst. */
static inline void lz77_output_lit(uint8_t *dst, size_t dst_pos, uint8_t lit)
{
        dst[dst_pos] = lit;
}

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдХреЙрд▓рд░ рдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ dstрдЙрддреНрдкрдиреНрди рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдЬрдЧрд╣ рд╣реИ рдФрд░ рдмрдлрд░ рдХреЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдмреИрдХрд▓рд┐рдВрдХ рд╕реНрдерд┐рддрд┐ рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪрддрд╛ рд╣реИред

рдЕрдирдкреИрдХрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбреЗрдЯрд╛ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░рддреЗ рд╕рдордп рдЗрд╕реЗ рдкрд╣рд▓реЗ рдмрдирд╛рдирд╛ рд╣реИред рдпрд╣ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо zlib рд╕реЗ рд╣реИрд╢ рдЯреЗрдмрд▓ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдХрд┐ RFC 1951 рдореЗрдВ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╣реИред

рд╣рдо рддреАрди-рд╡рд░реНрдг рдЙрдкрд╕рд░реНрдЧреЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реИрд╢ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдкрд╣рд▓реЗ рд▓рд╛рдЗрди рдореЗрдВ рдкрд╛рдП рдЧрдП рдереЗ (рдЫреЛрдЯреЗ рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХреЛрдИ рд▓рд╛рдн рдирд╣реАрдВ рд▓рд╛рддреЗ рд╣реИрдВ)ред Deflate рдкрд┐рдЫрд▓реЗ 32,768 рд╡рд░реНрдгреЛрдВ рдХреЗ рднреАрддрд░ рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ - рдЗрд╕реЗ рд╡рд┐рдВрдбреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╕реНрдЯреНрд░реАрдорд┐рдВрдЧ рд╕рдВрдкреАрдбрд╝рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ: рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЛ рдПрдХ рдмрд╛рд░ рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдмрд╢рд░реНрддреЗ рдХрд┐ рдЕрдВрддрд┐рдо рдмрд╛рдЗрдЯ рдХреЗ рд╕рд╛рде рд╡рд┐рдВрдбреЛ рдореЗрдореЛрд░реА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдорд╛рд░рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдорд╛рдирддрд╛ рд╣реИ рдХрд┐ рд╕рднреА рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ рдФрд░ рд╣рдо рдЗрд╕реЗ рдПрдХ рд╕рдордп рдореЗрдВ рдкреВрд░рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдЖрдкрдХреЛ рд▓реЗрдЦрд╛рдВрдХрди рдХреЗ рдмрдЬрд╛рдп рд╕рдВрдкреАрдбрд╝рди рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рд╕реНрдЯреНрд░реАрдо рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИред

рд╣рдо рджреЛ рд╕рд░рдгрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ: headрдЗрдирдкреБрдЯ рдореЗрдВ рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рддреАрди-рд╡рд░реНрдг рдЙрдкрд╕рд░реНрдЧ рдХрд╛ рд╣реИрд╢ рдорд╛рди рд╢рд╛рдорд┐рд▓ рд╣реИ, рдФрд░ prevрдЗрд╕ рд╣реИрд╢ рдорд╛рди рдХреЗ рд╕рд╛рде рдкрд┐рдЫрд▓реА рд╕реНрдерд┐рддрд┐ рдХреА рд╕реНрдерд┐рддрд┐ рд╢рд╛рдорд┐рд▓ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, head[h]рдпрд╣ рдПрдХ рд╣реИрд╢ рдХреЗ рд╕рд╛рде рдЙрдкрд╕рд░реНрдЧ рдкрджреЛрдВ рдХреА рдПрдХ рд▓рд┐рдВрдХ рдХреА рдЧрдИ рд╕реВрдЪреА рдХрд╛ рд╢реАрд░реНрд╖рдХ рд╣реИ h, рдФрд░ рд╕реВрдЪреА рд╕реЗ prev[x]рдкрд╣рд▓реЗ xрдХреЗ рддрддреНрд╡ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ ред

#define LZ_WND_SIZE 32768
#define LZ_MAX_LEN  258

#define HASH_SIZE 15
#define NO_POS    SIZE_MAX

/* Perform LZ77 compression on the len bytes in src. Returns false as soon as
   either of the callback functions returns false, otherwise returns true when
   all bytes have been processed. */
bool lz77_compress(const uint8_t *src, size_t len,
                   bool (*lit_callback)(uint8_t lit, void *aux),
                   bool (*backref_callback)(size_t dist, size_t len, void *aux),
                   void *aux)
{
        size_t head[1U << HASH_SIZE];
        size_t prev[LZ_WND_SIZE];

        uint16_t h;
        size_t i, j, dist;
        size_t match_len, match_pos;
        size_t prev_match_len, prev_match_pos;

        /* Initialize the hash table. */
        for (i = 0; i < sizeof(head) / sizeof(head[0]); i++) {
                head[i] = NO_POS;
        }

рд╣реИрд╢ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдПрдХ рдирдИ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдерд┐рддрд┐ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП prev, рдЗрд╕реЗ рдкрд┐рдЫрд▓реЗ рдПрдХ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ head, рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ head:

static void insert_hash(uint16_t hash, size_t pos, size_t *head, size_t *prev)
{
        prev[pos % LZ_WND_SIZE] = head[hash];
        head[hash] = pos;
}

рдЬрдм рдЕрдиреБрдХреНрд░рдордг рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдореЛрдбреБрд▓реЛ рдСрдкрд░реЗрд╢рди рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ prev: рд╣рдо рдХреЗрд╡рд▓ рдЙрди рдкрджреЛрдВ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рдЬреЛ рд╡рд░реНрддрдорд╛рди рд╡рд┐рдВрдбреЛ рдореЗрдВ рдЖрддреЗ рд╣реИрдВред

рдЦрд░реЛрдВрдЪ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рддреАрди-рд╡рд░реНрдг рдЙрдкрд╕рд░реНрдЧ рдХреЗ рд▓рд┐рдП рд╣реИрд╢ рдорд╛рди рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдПрдХ рд░рд┐рдВрдЧ рд╣реИрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рдХреЗрд╡рд▓ рдЕрдВрддрд┐рдо рддреАрди рдЕрдХреНрд╖рд░ рдЗрд╕рдХреЗ рдореВрд▓реНрдп рдореЗрдВ рдкрд░рд┐рд▓рдХреНрд╖рд┐рдд рд╣реЛрдВ:

static uint16_t update_hash(uint16_t hash, uint8_t c)
{
        hash <<= 5;                     /* Shift out old bits. */
        hash ^= c;                      /* Include new bits. */
        hash &= (1U << HASH_SIZE) - 1;  /* Mask off excess bits. */

        return hash;
}

рд╣реИрд╢ рдореИрдк рдХреЛ рддрдм рдПрдХ рдХреНрд░рдо рдХреЗ рд╕рд╛рде рдкрд┐рдЫрд▓реЗ рдореИрдЪреЛрдВ рдХреЗ рд▓рд┐рдП рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдЦреЛрдЬрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдореИрдЪреЛрдВ рдХреА рдЦреЛрдЬ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрд╕рд╛рдзрди-рдЧрд╣рди рд╕рдВрдкреАрдбрд╝рди рдСрдкрд░реЗрд╢рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╕реВрдЪреА рдореЗрдВ рдЦреЛрдЬ рдХреА рдЧрд╣рд░рд╛рдИ рдХреЛ рд╕реАрдорд┐рдд рдХрд░реЗрдВрдЧреЗред

рд╡рд┐рднрд┐рдиреНрди рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдмрджрд▓рдирд╛, рдЬреИрд╕реЗ рдЙрдкрд╕рд░реНрдЧреЛрдВ рдХреА рд╕реВрдЪреА рдкрд░ рдЦреЛрдЬ рдХреА рдЧрд╣рд░рд╛рдИ рдФрд░ рдиреАрдЪреЗ рд╡рд░реНрдгрд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдЖрд▓рд╕реА рддреБрд▓рдирд╛ рдХрд░рдирд╛, рд╕рдВрдкреАрдбрд╝рди рдХреА рдбрд┐рдЧреНрд░реА рдХреЛ рдХрдо рдХрд░рдХреЗ рдЧрддрд┐ рдмрдврд╝рд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдХреЛрдб рдореЗрдВ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ zlib рдореЗрдВ рдЕрдзрд┐рдХрддрдо рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЪреБрдирд╛ рдЧрдпрд╛ рд╣реИред

/* Find the longest most recent string which matches the string starting
 * at src[pos]. The match must be strictly longer than prev_match_len and
 * shorter or equal to max_match_len. Returns the length of the match if found
 * and stores the match position in *match_pos, otherwise returns zero. */
static size_t find_match(const uint8_t *src, size_t pos, uint16_t hash,
                         size_t prev_match_len, size_t max_match_len,
                         const size_t *head, const size_t *prev,
                         size_t *match_pos)
{
        size_t max_match_steps = 4096;
        size_t i, l;
        bool found;

        if (prev_match_len == 0) {
                /* We want backrefs of length 3 or longer. */
                prev_match_len = 2;
        }

        if (prev_match_len >= max_match_len) {
                /* A longer match would be too long. */
                return 0;
        }

        if (prev_match_len >= 32) {
                /* Do not try too hard if there is already a good match. */
                max_match_steps /= 4;
        }

        found = false;
        i = head[hash];

        while (max_match_steps != 0) {
                if (i == NO_POS) {
                        /* No match. */
                        break;
                }

                assert(i < pos && "Matches should precede pos.");
                if (pos - i > LZ_WND_SIZE) {
                        /* The match is outside the window. */
                        break;
                }

                l = cmp(src, i, pos, prev_match_len, max_match_len);

                if (l != 0) {
                        assert(l > prev_match_len);
                        assert(l <= max_match_len);

                        found = true;
                        *match_pos = i;
                        prev_match_len = l;

                        if (l == max_match_len) {
                                /* A longer match is not possible. */
                                return l;
                        }
                }

                /* Look further back in the prefix list. */
                i = prev[i % LZ_WND_SIZE];
                max_match_steps--;
        }

        if (!found) {
                return 0;
        }

        return prev_match_len;
}

/* Compare the substrings starting at src[i] and src[j], and return the length
 * of the common prefix. The match must be strictly longer than prev_match_len
 * and shorter or equal to max_match_len. */
static size_t cmp(const uint8_t *src, size_t i, size_t j,
                  size_t prev_match_len, size_t max_match_len)
{
        size_t l;

        assert(prev_match_len < max_match_len);

        /* Check whether the first prev_match_len + 1 characters match. Do this
         * backwards for a higher chance of finding a mismatch quickly. */
        for (l = 0; l < prev_match_len + 1; l++) {
                if (src[i + prev_match_len - l] !=
                    src[j + prev_match_len - l]) {
                        return 0;
                }
        }

        assert(l == prev_match_len + 1);

        /* Now check how long the full match is. */
        for (; l < max_match_len; l++) {
                if (src[i + l] != src[j + l]) {
                        break;
                }
        }

        assert(l > prev_match_len);
        assert(l <= max_match_len);
        assert(memcmp(&src[i], &src[j], l) == 0);

        return l;
}

рдЖрдк lz77_compressрдкрд┐рдЫрд▓реЗ рдореИрдЪреЛрдВ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХреЛрдб рдХреЗ рд╕рд╛рде рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ :

       /* h is the hash of the three-byte prefix starting at position i. */
        h = 0;
        if (len >= 2) {
                h = update_hash(h, src[0]);
                h = update_hash(h, src[1]);
        }

        prev_match_len = 0;
        prev_match_pos = 0;

        for (i = 0; i + 2 < len; i++) {
                h = update_hash(h, src[i + 2]);

                /* Search for a match using the hash table. */
                match_len = find_match(src, i, h, prev_match_len,
                                       min(LZ_MAX_LEN, len - i), head, prev,
                                       &match_pos);

                /* Insert the current hash for future searches. */
                insert_hash(h, i, head, prev);

                /* If the previous match is at least as good as the current. */
                if (prev_match_len != 0 && prev_match_len >= match_len) {
                        /* Output the previous match. */
                        dist = (i - 1) - prev_match_pos;
                        if (!backref_callback(dist, prev_match_len, aux)) {
                                return false;
                        }
                        /* Move past the match. */
                        for (j = i + 1; j < min((i - 1) + prev_match_len,
                                                len - 2); j++) {
                                h = update_hash(h, src[j + 2]);
                                insert_hash(h, j, head, prev);
                        }
                        i = (i - 1) + prev_match_len - 1;
                        prev_match_len = 0;
                        continue;
                }

                /* If no match (and no previous match), output literal. */
                if (match_len == 0) {
                        assert(prev_match_len == 0);
                        if (!lit_callback(src[i], aux)) {
                                return false;
                        }
                        continue;
                }

                /* Otherwise the current match is better than the previous. */

                if (prev_match_len != 0) {
                        /* Output a literal instead of the previous match. */
                        if (!lit_callback(src[i - 1], aux)) {
                                return false;
                        }
                }

                /* Defer this match and see if the next is even better. */
                prev_match_len = match_len;
                prev_match_pos = match_pos;
        }

        /* Output any previous match. */
        if (prev_match_len != 0) {
                dist = (i - 1) - prev_match_pos;
                if (!backref_callback(dist, prev_match_len, aux)) {
                        return false;
                }
                i = (i - 1) + prev_match_len;
        }

        /* Output any remaining literals. */
        for (; i < len; i++) {
                if (!lit_callback(src[i], aux)) {
                        return false;
                }
        }

        return true;
}

рдпрд╣ рдХреЛрдб рд╕рдмрд╕реЗ рд▓рдВрдмреЗ рдмреИрдХрд▓рд┐рдВрдХ рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЙрддреНрдкрдиреНрди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдЬрд╛рд░реА рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдХрд╛рд░реНрдпрдХреНрд░рдо рдпрд╣ рддрдп рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЕрдЧрд▓реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдПрдХ рдЕрдзрд┐рдХ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдорд┐рд▓рд╛рди рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред рдЬрд╝рд╛рд▓рд┐рдм рдореЗрдВ, рдЗрд╕реЗ рдЖрд▓рд╕реА рддреБрд▓рдирд╛рддреНрдордХ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдпрд╣ рдЕрднреА рднреА рдПрдХ рд▓рд╛рд▓рдЪреА рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣реИ: рдпрд╣ рд╕рдмрд╕реЗ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдореИрдЪ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рд╡рд░реНрддрдорд╛рди рдЫреЛрдЯрд╛ рд╡рд╛рд▓рд╛ рдЖрдкрдХреЛ рдмрд╛рдж рдореЗрдВ рдПрдХ рдореИрдЪ рднреА рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдордЬрдмреВрдд рд╕рдВрдкреАрдбрд╝рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рд▓реЗрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡ рд╕рдВрдкреАрдбрд╝рди рддреЗрдЬреА рдФрд░ рдзреАрдореА рдЧрддрд┐ рд╕реЗ рджреЛрдиреЛрдВ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред ZopfliрдЕрддрд┐рд░рд┐рдХреНрдд рд╕рдВрдкреАрдбрд╝рди рдкреНрд░рддрд┐рд╢рдд рдХреЛ рдирд┐рдЪреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╖реНрдЯрддрдо рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдмрд╣реБрдд рд╕рдордп рдмрд┐рддрд╛рдпрд╛ред рдпрд╣ рдЙрди рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИ рдЬреЛ рдПрдХ рдмрд╛рд░ рд╕рдВрдХреБрдЪрд┐рдд рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдкреБрди: рдЙрдкрдпреЛрдЧ рд╣реЛрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡реЗрдм рд╕рд░реНрд╡рд░ рдкрд░ рд╕реНрдерд┐рд░ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдПред рдкреИрдорд╛рдиреЗ рдХреЗ рджреВрд╕рд░реА рдУрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рд░реВрдк рдХрдореНрдкреНрд░реЗрд╕рд░ рд╣реИрдВ рддреЗрдЬрд╝ рдФрд░ LZ4 , рдЬреЛ рдкрд┐рдЫрд▓реЗ 4 рдмрд╛рдЗрдЯ рдЙрдкрд╕рд░реНрдЧ рдХреЗ рд╕рд╛рде рд╣реА рддреБрд▓рдирд╛ рдореЗрдВ рдФрд░ рдмрд╣реБрдд рддреЗрдЬреА рд╕реЗ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдХрдореНрдкреНрд░реЗрд╢рди рдбреЗрдЯрд╛рдмреЗрд╕ рдФрд░ RPC рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХрд┐рд╕реА рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдпрд╛ рдбрд┐рд╕реНрдХ рдкрд░ рдбреЗрдЯрд╛ рднреЗрдЬрддреЗ рд╕рдордп рдХрдореНрдкреНрд░реЗрд╢рди рдкрд░ рдЦрд░реНрдЪ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рдордп рдХреА рдмрдЪрдд рд╣реЛрддреА рд╣реИред

рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдХреЛ рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдмрд╣реБрдд рд╣реА рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдПрдХ рд╕реНрдерд┐рд░ рд╢рдмреНрджрдХреЛрд╢ рд╕реЗ рднреА рд▓рд╛рдн рдЙрдард╛ рд╕рдХрддреЗ рд╣реИрдВред рдмреНрд░реЗрдЯрд▓реА рдПрдХ LZ77 рдЖрдзрд╛рд░рд┐рдд рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдмрдбрд╝реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рднреА рдХрд░рддрд╛ рд╣реИрд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рд╕реНрдерд┐рд░ рд╢рдмреНрджрдХреЛрд╢ , рдЬреЛ рдЕрдХреНрд╕рд░ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдкрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВред

LZ77 рдХреЛрдб рдХреЛ lz77.h рдФрд░ lz77.c рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред

рд╣рдлрдореИрди рдХреЛрдб


рджреВрд╕рд░рд╛ рдЬрд╝рд┐рдк рд╕рдВрдкреАрдбрд╝рди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣рдлрд╝рдореИрди рдХреЛрдб рд╣реИред рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ

рд╢рдмреНрдж рдХреЛрдб рдХрд┐рд╕реА рдЕрдиреНрдп рд░реВрдк рдореЗрдВ рдбреЗрдЯрд╛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рдгрд╛рд▓реА рдХрд╛ рд╕рдВрджрд░реНрдн рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо рдЙрд╕ рдХреЛрдб рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдХрд┐ рд▓реЗрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рд╢рд╛рдмреНрджрд┐рдХ рдФрд░ рдмреИрдХрд▓рд┐рдВрдХ рдХрд╛ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдкрд╛рд░рдВрдкрд░рд┐рдХ рд░реВрдк рд╕реЗ, рдЕрдВрдЧреНрд░реЗрдЬреА рдкрд╛рда рдХреЛ рдЕрдореЗрд░рд┐рдХрди рд╕реНрдЯреИрдВрдбрд░реНрдб рдХреЛрдб рдлреЙрд░ рдЗрдВрдлреЙрд░реНрдореЗрд╢рди рдЗрдВрдЯрд░рдЪреЗрдВрдЬ (ASCII) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдпрд╣ рдкреНрд░рдгрд╛рд▓реА рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдг рдХреЛ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ, рдЬрд┐рд╕реЗ рдЖрдорддреМрд░ рдкрд░ 8-рдмрд┐рдЯ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдЕрдВрдЧреНрд░реЗрдЬреА рд╡рд░реНрдгрдорд╛рд▓рд╛ рдХреЗ рдмрдбрд╝реЗ рдЕрдХреНрд╖рд░реЛрдВ рдХреЗ рд▓рд┐рдП ASCII рдХреЛрдб рд╣реИрдВ:

рдП01000001N01001110
B01000010O01001111
C01000011P01010000
D01000100Q01010001
E01000101R01010010
F01000110S01010011
G01000111T01010100
H01001000U01010101
I01001001V01010110
J01001010W01010111
K01001011X01011000
L01001100Y01011001
M01001101Z01011010

рдПрдХ рдмрд╛рдЗрдЯ рдкреНрд░рддрд┐ рд╡рд░реНрдг рдкрд╛рда рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдкрд╛рда рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдпрд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╣рдореЗрд╢рд╛ рд╕реНрдкрд╖реНрдЯ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдПрди рд╡рд░реНрдгреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рддрдиреЗ рдмрд╛рдЗрдЯреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдпрд╛ рдПрди рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рдХрд┐рддрдиреЗ рд╡рд░реНрдг рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдХрдмреНрдЬреЗ рд╡рд╛рд▓реА рдЬрдЧрд╣ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдпрд╣ рд╕рдмрд╕реЗ рдкреНрд░рднрд╛рд╡реА рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдВрдЧреНрд░реЗрдЬреА рдореЗрдВ, E рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ Z рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рдмрд╕реЗ рдХрдо рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╡реЙрд▓реНрдпреВрдо рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдг рдХреЛ рд╕рдорд╛рди рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдмрд┐рдЯреНрд╕ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдИ рдХреЗ рд▓рд┐рдП рдХрдо рдмрд┐рдЯ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдФрд░ рдЬреЗрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рд╣реИред

рдПрдХ рдХреЛрдб рдЬреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд▓рдВрдмрд╛рдИ рдХреЗ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕реНрд░реЛрдд рд╡рд░реНрдгреЛрдВ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ, рдЙрд╕реЗ рдПрдХ рдЪрд░-рд▓рдВрдмрд╛рдИ рдХреЛрдб рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ред рд╕рдмрд╕реЗ рдкреНрд░рд╕рд┐рджреНрдз рдЙрджрд╛рд╣рд░рдг рдореЛрд░реНрд╕ рдХреЛрдб рд╣реИред, рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЪрд░рд┐рддреНрд░ рдХреЛ рдбреЙрдЯреНрд╕ рдФрд░ рдбреИрд╢ рдХреЗ рд╕рд╛рде рдПрдиреНрдХреЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдореВрд▓ рд░реВрдк рд╕реЗ рдЫреЛрдЯреА рдФрд░ рд▓рдВрдмреА рджрд╛рд▓реЛрдВ рдХреЗ рд╕рд╛рде рдЯреЗрд▓реАрдЧреНрд░рд╛рдл рджреНрд╡рд╛рд░рд╛ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

рдПтАв -рдПрди- тАв тАв
рдмреА- тАв тАв тАв тАврд╣реЗ- - -
рд╕реА- тАв - тАврдкреАтАв тАв - тАв
рдбреА- тАв тАврдХреНрдпреВ- - тАв -
рдЗтАврдЖрд░тАв тАв тАв
рдПрдлтАв тАв - тАврдПрд╕тАв тАв тАв
рдЬреА- - тАврдЯреА-
рдПрдЪтАв тАв тАв тАв тАврдпреВтАв тАв -
рдореИрдВтАв тАврд╡реАтАв тАв тАв -
рдЬреЗтАв - - -рдбрдмреНрд▓реНрдпреВтАв - -
рдХ- тАв -рдПрдХреНрд╕- тАв тАв -
рдПрд▓тАв тАв тАв тАвY- тАв - -
рдо- -рдЬреЗрдб- - тАв тАв

рдореЛрд░реНрд╕ рдХреЛрдб рдХреА рдХрдорд┐рдпреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рд╣реИ рдХрд┐ рдПрдХ рдХреЛрдбрд╡рд░реНрдб рджреВрд╕рд░реЗ рдХрд╛ рдЙрдкрд╕рд░реНрдЧ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, тАв тАв - тАв рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдбрд┐рдХреЛрдбрд┐рдВрдЧ рдирд╣реАрдВ рд╣реИ: рдпрд╣ рдПрдл рдпрд╛ рдИрдЖрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рд╕рдВрдЪрд░рдг рдХреЗ рджреМрд░рд╛рди рдкрддреНрд░реЛрдВ рдХреЗ рдмреАрдЪ рдард╣рд░рд╛рд╡ (рд▓рдВрдмрд╛рдИ рдореЗрдВ рддреАрди рдбреЙрдЯреНрд╕) рджреНрд╡рд╛рд░рд╛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛ рдпрджрд┐ рдХреЛрдбрд╡рд░реНрдб рдЕрдиреНрдп рд╢рдмреНрджреЛрдВ рдХреЗ рдЙрдкрд╕рд░реНрдЧ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдХреЛрдб рдХреЛ рдЕрдирд░рд┐рдлрд╛рдЗрдВрдб рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд▓рдВрдмрд╛рдИ рдХрд╛ ASCII рдХреЛрдб рдЕрдкреНрд░рдпреБрдХреНрдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдбрд╡рд░реНрдб рд╣рдореЗрд╢рд╛ рдПрдХ рд╣реА рд▓рдВрдмрд╛рдИ рдХреЗ рд╣реЛрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд▓рдВрдмрд╛рдИ рдХреЛрдб рднреА рдЕрдкреНрд░рдХрд╛рд╢рд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдлрд╝реЛрди рдирдВрдмрд░ рдЕрдХреНрд╕рд░ рдЕрдкреНрд░рдпреБрдХреНрдд рд╣реЛрддреЗ рд╣реИрдВред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╕реНрд╡реАрдбрди рдореЗрдВ рдЖрдкрд╛рддрдХрд╛рд▓реАрди рдЯреЗрд▓реАрдлреЛрди рдирдВрдмрд░ 112 рдкреЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛, 112 рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдирдВрдмрд░реЛрдВ рдХреЛ рдмрджрд▓рдирд╛ рдкрдбрд╝рд╛ред рдФрд░ рдпреВрдПрд╕рдП рдореЗрдВ 911 рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рднреА рдЯреЗрд▓реАрдлреЛрди рдирдВрдмрд░ рдирд╣реАрдВ рд╣реИред

рдПрдиреНрдХреЛрдб рдХрд┐рдП рдЧрдП рд╕рдВрджреЗрд╢ рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЕрдХреНрд╕рд░ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╡рд░реНрдгреЛрдВ рдореЗрдВ рдЫреЛрдЯреЗ рдХреЛрдбрд╡рд░реНрдб рд╣реЛрддреЗ рд╣реИрдВред рдЗрд╖реНрдЯрддрдо рдХреЛрдб рд╡рд╣ рд╣реЛрдЧрд╛ рдЬреЛ рд╕рдмрд╕реЗ рдХрдо рд╕рдВрднрд╡ рдкрд░рд┐рдгрд╛рдо рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ - рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреА рд▓рдВрдмрд╛рдИ рдХрд╛ рдпреЛрдЧ, рдЙрдирдХреА рдШрдЯрдирд╛ рдХреА рдЖрд╡реГрддреНрддрд┐ рд╕реЗ рдЧреБрдгрд╛, рдиреНрдпреВрдирддрдо рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреБрд╢рд▓ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдЖрд╡рд┐рд╖реНрдХрд╛рд░рдХ рдХреЗ рд╕рдореНрдорд╛рди рдореЗрдВ , рдЗрд╕реЗ рдиреНрдпреВрдирддрдо рдЕрддрд┐рд░реЗрдХ рдпрд╛ рд╣рдлрд╝рдореИрди рдХреЛрдб рдХреЗ рд╕рд╛рде рдПрдХ рдЧреИрд░-рдЙрдкрд╕рд░реНрдЧ рдХреЛрдб рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ред

рд╣рдлрд╝рдореИрди рдПрд▓реНрдЧреЛрд░рд┐рджрдо


рдПрдордЖрдИрдЯреА рдореЗрдВ рдЗрд▓реЗрдХреНрдЯреНрд░реЙрдирд┐рдХ рдЗрдВрдЬреАрдирд┐рдпрд░рд┐рдВрдЧ рдкрд░ рдЕрдкрдиреЗ рдбреЙрдХреНрдЯрд░реЗрдЯ рд╢реЛрдз рдкреНрд░рдмрдВрдз рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рддреЗ рд╕рдордп, рдбреЗрд╡рд┐рдб рд╣рдлрдореИрди рдиреЗ рд░реЙрдмрд░реНрдЯ рдиреИрдиреЛ рджреНрд╡рд╛рд░рд╛ рд╕рд┐рдЦрд╛рдпрд╛ рд╕реВрдЪрдирд╛ рд╕рд┐рджреНрдзрд╛рдВрдд рдкрд░ рдПрдХ рдкрд╛рдареНрдпрдХреНрд░рдо рдореЗрдВ рднрд╛рдЧ рд▓рд┐рдпрд╛ред рдХрд┐рдВрд╡рджрдВрддреА рдХреЗ рдЕрдиреБрд╕рд╛рд░ , рдлрд╝рд╛рдиреЛ рдиреЗ рдЕрдкрдиреЗ рдЫрд╛рддреНрд░реЛрдВ рдХреЛ рдЪреБрдирдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреА: рдЕрдВрддрд┐рдо рдкрд░реАрдХреНрд╖рд╛ рдпрд╛ рдкрд╛рдареНрдпрдХреНрд░рдо рд▓рд┐рдЦреЗрдВред рд╣рдлрд╝рдореИрди рдиреЗ рдмрд╛рдж рдХреЛ рдЪреБрдирд╛, рдФрд░ рдЙрдиреНрд╣реЗрдВ рдиреНрдпреВрдирддрдо рдЕрддрд┐рд░реЗрдХ рдХреЗ рд╕рд╛рде рдЙрдкрд╕рд░реНрдЧ рд░рд╣рд┐рдд рдХреЛрдб рдЦреЛрдЬрдиреЗ рдХрд╛ рд╡рд┐рд╖рдп рджрд┐рдпрд╛ рдЧрдпрд╛ред рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╡рд╣ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рдерд╛ рдХрд┐ рдЙрд╕ рд╕рдордп рдлрд╛рдиреЛ рд╕реНрд╡рдпрдВ рдЗрд╕ рдХрд╛рд░реНрдп рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рдерд╛ (рдЙрди рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рд╢реИрдирди-рдлрд╝рд╛рдиреЛ рдПрд▓реНрдЧреЛрд░рд┐рдердо рд╕рдмрд╕реЗ рдкреНрд░рд╕рд┐рджреНрдз рд╡рд┐рдзрд┐ рдереА )ред рд╣рдлрд╝рдореИрди рдХрд╛ рдХрд╛рдо 1952 рдореЗрдВ рдП-рдореЗрдердб рдлреЙрд░ рдж рдХрдВрд╕реНрдЯреНрд░рдХреНрд╢рди рдСрдлрд╝ рдорд┐рдирд┐рдордо-рд░рд┐рдбрдВрдбреЗрдВрд╕реА рдХреЛрдбреНрд╕ рдХреЗ рддрд╣рдд 1952 рдореЗрдВ рдкреНрд░рдХрд╛рд╢рд┐рдд рд╣реБрдЖ рдерд╛ ред рддрдм рд╕реЗ рдЗрд╕рдХреЗ рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХрд╛ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд▓рдЧрд╛ред


рдбреЗрд╡рд┐рдб рд╣рдлрд╝рдореИрди рдиреЗ рдпреВрд╕реА рд╕рд╛рдВрддрд╛ рдХреНрд░реВрдЬрд╝ рдХреЛ рд░рд┐рд▓реАрдЬрд╝ рдХрд┐рдпрд╛ ред

рд╣рдлрдореИрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдЪрд░рд┐рддреНрд░ рд╕реЗрдЯ рдФрд░ рдЙрдирдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░реЗрдХ рдХреЛрдб рдХреЗ рд╕рд╛рде рдЕрд╡рд┐рднрд╛рдЬрд┐рдд рдХреЛрдб рдмрдирд╛рддрд╛ рд╣реИред рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдмрд╛рд░-рдмрд╛рд░ рджреЛ рд╡рд░реНрдгреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдореЗрдВ рдкрд╛рдП рдЬрд╛рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ - рдХрд╣рддреЗ рд╣реИрдВ, рдПрдХреНрд╕ рдФрд░ рд╡рд╛рдИ - рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рдордЧреНрд░ рдЪрд░рд┐рддреНрд░ рдЕрд░реНрде "рдПрдХреНрд╕ рдпрд╛ рд╡рд╛рдИ" рд╕реЗ рдмрджрд▓ рджреЗрддрд╛ рд╣реИред рдПрдХ рдорд┐рд╢реНрд░рд┐рдд рдкреНрд░рддреАрдХ рдХреА рдШрдЯрдирд╛ рдХреА рдЖрд╡реГрддреНрддрд┐ рджреЛ рд╕реНрд░реЛрдд рдкреНрд░рддреАрдХреЛрдВ рдХреА рдЖрд╡реГрддреНрддрд┐рдпреЛрдВ рдХрд╛ рдпреЛрдЧ рд╣реИред X рдФрд░ Y рдХреЗ рдХреЛрдбрд╡рд░реНрдб рдХрд┐рд╕реА рднреА рдРрд╕реЗ рдХреЛрдбрд╡рд░реНрдб рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдореВрд▓ рд╡рд░реНрдгреЛрдВ рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 0 рдпрд╛ 1 рдХреЗ рдмрд╛рдж рдпреМрдЧрд┐рдХ рд╡рд░реНрдг "X рдпрд╛ Y" рдХреЛ рджрд┐рдП рдЧрдП рд╣реЛрдВред рдЬрдм рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдПрдХ рд╡рд░реНрдг рдореЗрдВ рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛рдо рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИ ( рд╡реАрдбрд┐рдпреЛ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг )ред

рдпрд╣рд╛рдБ рдПрдХ рдЫреЛрдЯреЗ рд╡рд░реНрдг рд╕реЗрдЯ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

рдкреНрд░рддреАрдХрдЖрд╡реГрддреНрддрд┐
рдП6
рдмреА4
рд╕реА2
рдбреА3

рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдкрд╣рд▓рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐:


C рдФрд░ D, рджреЛ рджреБрд░реНрд▓рдн рдЪрд┐рд╣реНрдиреЛрдВ рдХреЛ рд╕реЗрдЯ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╕рдордЧреНрд░ рдкреНрд░рддреАрдХ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдХреА рдЖрд╡реГрддреНрддрд┐ рдЖрд╡реГрддреНрддрд┐рдпреЛрдВ C рдФрд░ D рдХрд╛ рдпреЛрдЧ рд╣реИ:


рдЕрдм рд╕рдмрд╕реЗ рджреБрд░реНрд▓рдн рдкреНрд░рддреАрдХ B рдФрд░ 5 рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдВрдпреБрдХреНрдд рдкреНрд░рддреАрдХ рд╣реИред рдЙрдиреНрд╣реЗрдВ рд╕реЗрдЯ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ 9 рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдордЧреНрд░ рдкреНрд░рддреАрдХ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


рдЕрдВрдд рдореЗрдВ, 9 рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд╕рд╛рде A рдФрд░ рдПрдХ рд╕рдВрдпреБрдХреНрдд рдкреНрд░рддреАрдХ рдХреЛ 15 рдХреЗ рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рдирдП рдкреНрд░рддреАрдХ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ:


рдкреВрд░реЗ рд╕реЗрдЯ рдХреЛ рдПрдХ рд╡рд░реНрдг рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИред

рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдиреЗ рд╣рдлрдореИрди рдкреЗрдбрд╝ рдирд╛рдордХ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдИ ред рдЗрдирдкреБрдЯ рд╡рд░реНрдг рдкрддреНрддрд┐рдпрд╛рдВ рд╣реИрдВ, рдФрд░ рдПрдХ рд╡рд░реНрдг рдХреА рдЖрд╡реГрддреНрддрд┐ рдЬрд┐рддрдиреА рдЕрдзрд┐рдХ рд╣реЛрддреА рд╣реИ, рдЙрддрдирд╛ рд╣реА рдЙрдЪреНрдЪ рд╕реНрдерд┐рдд рд╣реЛрддрд╛ рд╣реИред рдкреЗрдбрд╝ рдХреА рдЬрдбрд╝ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рдХреНрд░рдорд╢рдГ рдмрд╛рдПрдВ рдпрд╛ рджрд╛рдПрдВ рдЪрд▓рддреЗ рд╕рдордп 0 рдпрд╛ 1 рдЬреЛрдбрд╝рдХрд░ рд╡рд░реНрдгреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд╢рдмреНрдж рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдирд┐рдХрд▓рд╛:

рдкреНрд░рддреАрдХрдХреЛрдбрд╡рд░реНрдб
рдП0
рдмреА10
рд╕реА110
рдбреА111

рдХреЛрдИ рднреА рдХреЛрдбрд╡рд░реНрдб рдХрд┐рд╕реА рдЕрдиреНрдп рдХреЗ рд▓рд┐рдП рдЙрдкрд╕рд░реНрдЧ рдирд╣реАрдВ рд╣реИред рдЬрд┐рддрдиреА рдмрд╛рд░ рдПрдХ рдкреНрд░рддреАрдХ рд╣реЛрддрд╛ рд╣реИ, рдЙрд╕рдХрд╛ рдХреЛрдб рд╢рдмреНрдж рдЙрддрдирд╛ рд╣реА рдЫреЛрдЯрд╛ рд╣реЛрддрд╛ рд╣реИред

рдкреЗрдбрд╝ рдХреЛ рдбрд┐рдХреЛрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рднреА рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рд╣рдо рдЬрдбрд╝ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЪрд░рд┐рддреНрд░ рдХреЗ рд╕рд╛рдордиреЗ 0 рдпрд╛ 1 рдХреЗ рд╕рд╛рде рдореВрд▓реНрдп рдХреЗ рд▓рд┐рдП рджрд╛рдПрдВ рдпрд╛ рдмрд╛рдПрдВ рдЬрд╛рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдмреАрдмреАрдП рдореЗрдВ рд▓рд╛рдЗрди 010100 рдХреЛ рдбрд┐рдХреЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рд╕рдВрдмрдВрдзрд┐рдд рдЯреНрд░реА рдиреЛрдб рдХреА рдЧрд╣рд░рд╛рдИ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ рджреЗрдЦреЗрдВрдЧреЗ, рд╣рдореЗрдВ рдХреЛрдбрд╡рд░реНрдб рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреЗрдбрд╝ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд╕реНрд╡рдпрдВ рд╢рдмреНрджреЛрдВ рдХреА рд▓рдВрдмрд╛рдИ рдЬрд╛рдирдирд╛ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдлрдореИрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреА рд▓рдВрдмрд╛рдИ рд╣реЛрдЧреАред

рдЪрд░рд┐рддреНрд░ рд╕реЗрдЯ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдФрд░ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рд╕рдмрд╕реЗ рдХрдо рдЖрд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдмрд╛рдЗрдирд░реА рд╣реАрдк рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ ред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рд╣рдо рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВрдиреНрдпреВрдирддрдо- рдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рдиреНрдпреВрдирддрдо рдорд╛рди рд╢реАрд░реНрд╖ рдкрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

/* Swap the 32-bit values pointed to by a and b. */
static void swap32(uint32_t *a, uint32_t *b)
{
        uint32_t tmp;

        tmp = *a;
        *a = *b;
        *b = tmp;
}

/* Move element i in the n-element heap down to restore the minheap property. */
static void minheap_down(uint32_t *heap, size_t n, size_t i)
{
        size_t left, right, min;

        assert(i >= 1 && i <= n && "i must be inside the heap");

        /* While the ith element has at least one child. */
        while (i * 2 <= n) {
                left = i * 2;
                right = i * 2 + 1;

                /* Find the child with lowest value. */
                min = left;
                if (right <= n && heap[right] < heap[left]) {
                        min = right;
                }

                /* Move i down if it is larger. */
                if (heap[min] < heap[i]) {
                        swap32(&heap[min], &heap[i]);
                        i = min;
                } else {
                        break;
                }
        }
}

/* Establish minheap property for heap[1..n]. */
static void minheap_heapify(uint32_t *heap, size_t n)
{
        size_t i;

        /* Floyd's algorithm. */
        for (i = n / 2; i >= 1; i--) {
                minheap_down(heap, n, i);
        }
}

nрд╡рд░реНрдгреЛрдВ рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП , рд╣рдо nрддрддреНрд╡реЛрдВ рдХреЗ рдПрдХ рд╕рдореВрд╣ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рд░ рдмрд╛рд░ рдПрдХ рд╕рдордЧреНрд░ рдкреНрд░рддреАрдХ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рдо рджреЛрдиреЛрдВ рд╕реНрд░реЛрдд рдкреНрд░рддреАрдХреЛрдВ рдХреЛ "рд▓рд┐рдВрдХ" рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рддреАрдХ рдореЗрдВ рдПрдХ "рд╕рдВрдЪрд╛рд░ рддрддреНрд╡" рд╣реЛрдЧрд╛ред -Element рдвреЗрд░ рдФрд░ рд╕рдВрдЪрд╛рд░ рддрддреНрд╡реЛрдВ

рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП , рд╣рдо рддрддреНрд╡реЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ ред рдЬрдм рдвреЗрд░ рдкрд░ рджреЛ рдкрд╛рддреНрд░реЛрдВ рдХреЛ рдПрдХ рд╕реЗ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдирдП рдЪрд░рд┐рддреНрд░ рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░реЗ рддрддреНрд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкреНрд░рдмрдВрдз рдЧреАрдЧрд╛рдмрд╛рдЗрдЯреНрд╕ рдСрдлрд╝ рд╡рд┐рдЯреЗрди, рдореЛрдлрд╝рдд рдФрд░ рдмреЗрд▓ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ редnnn * 2 + 1

рдвреЗрд░ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб рдореЗрдВ, рд╣рдо рдкреНрд░рддреАрдХ рдЖрд╡реГрддреНрддрд┐ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 16 рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдкреНрд░рддреАрдХ рд╕рдВрдЪрд╛рд░ рддрддреНрд╡ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 16 рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯреНрд╕ред рдЙрдЪреНрдЪ рдмрд┐рдЯреНрд╕ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдХрд╛рд░рдг, рдвреЗрд░ рдХреЗ рджреЛ рддрддреНрд╡реЛрдВ рдХреЗ рдмреАрдЪ 32-рдмрд┐рдЯ рдХреА рддреБрд▓рдирд╛ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдЖрд╡реГрддреНрддрд┐ рдЕрдВрддрд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдЗрд╕ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреЗ рдХрд╛рд░рдг, рд╣рдореЗрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдкрд╛рддреНрд░реЛрдВ рдХреА рдЖрд╡реГрддреНрддрд┐ рд╣рдореЗрд╢рд╛ 16 рдмрд┐рдЯреНрд╕ рдореЗрдВ рдлрд┐рдЯ рд╣реЛрддреА рд╣реИред рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЕрдВрддрд┐рдо рд╕рдВрдпреБрдХреНрдд рдкреНрд░рддреАрдХ рдореЗрдВ рд╕рднреА рд╕рдВрдпреБрдХреНрдд рдкреНрд░рддреАрдХреЛрдВ рдХреА рдЖрд╡реГрддреНрддрд┐ рд╣реЛрдЧреА, рдЕрд░реНрдерд╛рдд, рдЗрд╕ рд░рд╛рд╢рд┐ рдХреЛ 16 рдмрд┐рдЯреНрд╕ рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдорд╛рд░рд╛ рдбрд┐рдлрд╛рд▓реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди 64,535 рд╡рд░реНрдгреЛрдВ рдХреЛ рдПрдХ рд╕рд╛рде рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдХреЗ рдЗрд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдЧрд╛ред

рд╢реВрдиреНрдп рдЖрд╡реГрддреНрддрд┐ рд╡рд╛рд▓реЗ рдкреНрд░рддреАрдХреЛрдВ рдХреЛ рд╢реВрдиреНрдп рд▓рдВрдмрд╛рдИ рдХреЗ рдХреЛрдб рд╢рдмреНрдж рдкреНрд░рд╛рдкреНрдд рд╣реЛрдВрдЧреЗ рдФрд░ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдХреЗ рд╕рдВрдХрд▓рди рдореЗрдВ рднрд╛рдЧ рдирд╣реАрдВ рд▓реЗрдВрдЧреЗред

рдпрджрд┐ рдХреЛрдб рд╢рдмреНрдж рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЕрдзрд┐рдХрддрдо рдЧрд╣рд░рд╛рдИ рддрдХ рдкрд╣реБрдВрдЪрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЖрд╡реГрддреНрддрд┐ рд╕реАрдорд╛ рд▓рд╛рдЧреВ рдХрд░рдХреЗ рдЖрд╡реГрддреНрддрд┐ рд╡рд┐рддрд░рдг рдХреЛ "рд╕реБрдЪрд╛рд░реВ" рдХрд░реЗрдВрдЧреЗ рдФрд░ рдлрд┐рд░ рд╕реЗ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗ (рд╣рд╛рдБ, рдорджрдж рдХреЗ рд╕рд╛рде goto)ред рдЧрд╣рд░рд╛рдИ рддрдХ рд╕реАрдорд┐рдд рд╣рдлрд╝рдореИрди рдХреЛрдбрд┐рдВрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдкрд░рд┐рд╖реНрдХреГрдд рддрд░реАрдХреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд░рд▓ рдФрд░ рдХреБрд╢рд▓ рд╣реИред

#define MAX_HUFFMAN_SYMBOLS 288      /* Deflate uses max 288 symbols. */

/* Construct a Huffman code for n symbols with the frequencies in freq, and
 * codeword length limited to max_len. The sum of the frequencies must be <=
 * UINT16_MAX. max_len must be large enough that a code is always possible,
 * i.e. 2 ** max_len >= n. Symbols with zero frequency are not part of the code
 * and get length zero. Outputs the codeword lengths in lengths[0..n-1]. */
static void compute_huffman_lengths(const uint16_t *freqs, size_t n,
                                    uint8_t max_len, uint8_t *lengths)
{
        uint32_t nodes[MAX_HUFFMAN_SYMBOLS * 2 + 1], p, q;
        uint16_t freq;
        size_t i, h, l;
        uint16_t freq_cap = UINT16_MAX;

#ifndef NDEBUG
        uint32_t freq_sum = 0;
        for (i = 0; i < n; i++) {
                freq_sum += freqs[i];
        }
        assert(freq_sum <= UINT16_MAX && "Frequency sum too large!");
#endif

        assert(n <= MAX_HUFFMAN_SYMBOLS);
        assert((1U << max_len) >= n && "max_len must be large enough");

try_again:
        /* Initialize the heap. h is the heap size. */
        h = 0;
        for (i = 0; i < n; i++) {
                freq = freqs[i];

                if (freq == 0) {
                        continue; /* Ignore zero-frequency symbols. */
                }
                if (freq > freq_cap) {
                        freq = freq_cap; /* Enforce the frequency cap. */
                }

                /* High 16 bits: Symbol frequency.
                   Low 16 bits:  Symbol link element index. */
                h++;
                nodes[h] = ((uint32_t)freq << 16) | (uint32_t)(n + h);
        }
        minheap_heapify(nodes, h);

        /* Special case for less than two non-zero symbols. */
        if (h < 2) {
                for (i = 0; i < n; i++) {
                        lengths[i] = (freqs[i] == 0) ? 0 : 1;
                }
                return;
        }

        /* Build the Huffman tree. */
        while (h > 1) {
                /* Remove the lowest frequency node p from the heap. */
                p = nodes[1];
                nodes[1] = nodes[h--];
                minheap_down(nodes, h, 1);

                /* Get q, the next lowest frequency node. */
                q = nodes[1];

                /* Replace q with a new symbol with the combined frequencies of
                   p and q, and with the no longer used h+1'th node as the
                   link element. */
                nodes[1] = ((p & 0xffff0000) + (q & 0xffff0000))
                           | (uint32_t)(h + 1);

                /* Set the links of p and q to point to the link element of
                   the new node. */
                nodes[p & 0xffff] = nodes[q & 0xffff] = (uint32_t)(h + 1);

                /* Move the new symbol down to restore heap property. */
                minheap_down(nodes, h, 1);
        }

        /* Compute the codeword length for each symbol. */
        h = 0;
        for (i = 0; i < n; i++) {
                if (freqs[i] == 0) {
                        lengths[i] = 0;
                        continue;
                }
                h++;

                /* Link element for the i'th symbol. */
                p = nodes[n + h];

                /* Follow the links until we hit the root (link index 2). */
                l = 1;
                while (p != 2) {
                        l++;
                        p = nodes[p];
                }

                if (l > max_len) {
                        /* Lower freq_cap to flatten the distribution. */
                        assert(freq_cap != 1 && "Cannot lower freq_cap!");
                        freq_cap /= 2;
                        goto try_again;
                }

                assert(l <= UINT8_MAX);
                lengths[i] = (uint8_t)l;
        }
}

рдмрд╛рдЗрдирд░реА рд╣реАрдк рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдПрдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╡рд┐рдХрд▓реНрдк рджреЛ рдХрддрд╛рд░реЛрдВ рдореЗрдВ рдкрд╛рддреНрд░реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рд╣реИред рдкрд╣рд▓реЗ рдореЗрдВ рд╕реНрд░реЛрдд рд╡рд░реНрдг рд╣реЛрддреЗ рд╣реИрдВ, рдЖрд╡реГрддреНрддрд┐ рджреНрд╡рд╛рд░рд╛ рдХреНрд░рдордмрджреНрдзред рдЬрдм рдПрдХ рдпреМрдЧрд┐рдХ рдкреНрд░рддреАрдХ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╕рдмрд╕реЗ рдХрдо рдЖрд╡реГрддреНрддрд┐ рд╡рд╛рд▓рд╛ рдкреНрд░рддреАрдХ рд╣рдореЗрд╢рд╛ рдХрддрд╛рд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреА рдкрд╣рд▓реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реЛрдЧрд╛ред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рд╡рд░реНрдгрди рдЬрди рд╡реИрди рд▓реАрдЙрд╡реЗрди рдиреЗ рдСрди рдж рдХрдВрд╕реНрдЯреНрд░рдХреНрд╢рди рдСрдл рд╣рдлрд╝рдореИрди рдЯреНрд░реАрдЬрд╝ (1976) рдореЗрдВ рдХрд┐рдпрд╛ рд╣реИред

рд╣рдлрд╝рдореИрди рдХреЛрдбрд┐рдВрдЧ рдЧреИрд░-рдЙрдкрд╕рд░реНрдЧ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЗрд╖реНрдЯрддрдо рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдиреНрдп рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рддрд░реАрдХреЗ рд╣реИрдВ: рдЕрдВрдХрдЧрдгрд┐рдд рдХреЛрдбрд┐рдВрдЧ рдФрд░ рдЕрд╕рдордорд┐рдд рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рдгрд╛рд▓реА ред

рд╣рдлрдореИрди рдХреЗ рд╡рд┐рд╣рд┐рдд рдХреЛрдб


рдКрдкрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдордиреЗ рдПрдХ рд╣рдлрдореИрди рдкреЗрдбрд╝ рдмрдирд╛рдпрд╛:


рдпрджрд┐ рд╣рдо рд░реВрдЯ рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдмрд╛рдИрдВ рд╢рд╛рдЦрд╛ рдХреЗ рд▓рд┐рдП 0 рдФрд░ рджрд╛рдИрдВ рдУрд░ 1 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдорд┐рд▓рддреЗ рд╣реИрдВ:

рдкреНрд░рддреАрдХрдХреЛрдбрд╡рд░реНрдб
рдП0
рдмреА10
рд╕реА110
рдбреА111

рдмрд╛рдИрдВ рд╢рд╛рдЦрд╛ рдХреЗ рд▓рд┐рдП 0 рдФрд░ рджрд╛рдИрдВ рдУрд░ 1 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рдордирдорд╛рдирд╛ рд▓рдЧрддрд╛ рд╣реИред рдпрджрд┐ рд╣рдо рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдпрд╣ рдорд┐рд▓рддрд╛ рд╣реИ:

рдкреНрд░рддреАрдХрдХреЛрдбрд╡рд░реНрдб
рдП1
рдмреА01
рд╕реА001
рдбреА000

рд╣рдо рд╢реВрдиреНрдп рдФрд░ рдПрдХ рдХреЗ рд╕рд╛рде рдиреЛрдб рд╕реЗ рдирд┐рдХрд▓рдиреЗ рд╡рд╛рд▓реА рджреЛ рд╢рд╛рдЦрд╛рдУрдВ рдХреЛ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рд▓реЗрдмрд▓ рдЕрд▓рдЧ рд╣реИрдВ), рдФрд░ рдЕрднреА рднреА рдмрд░рд╛рдмрд░ рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:


рдкреНрд░рддреАрдХрдХреЛрдбрд╡рд░реНрдб
рдП0
рдмреАрдЧреНрдпрд╛рд░рд╣
рд╕реА100
рдбреА101

рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╣рдлрд╝рдореИрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдиреНрдпреВрдирддрдо рдЕрддрд┐рд░реЗрдХ рдХреЗ рд╕рд╛рде рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рд╡реНрдпрдХреНрддрд┐рдЧрдд рдХреЛрдбрд╡рд░реНрдб рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВред

рд╣рдлрд╝рдореИрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рджреНрд╡рд╛рд░рд╛ рдЧрдгрдирд╛ рдХреА рдЧрдИ рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рд╡рд┐рд╣рд┐рдд рд╣рдлрд╝рдореИрди рдХреЛрдб рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рддрд░реАрдХреЗ рд╕реЗ рд╡рд░реНрдгреЛрдВ рдХреЛ рдХреЛрдбрд╡рд░реНрдб рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрдкрдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рдХреЛ рд╕реНрдЯреЛрд░ рдФрд░ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ: рдбрд┐рдХреЛрдбрд░ рдЕрдкрдиреА рд▓рдВрдмрд╛рдИ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреЛрдбрд╡рд░реНрдб рдХреЛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛ред рдмреЗрд╢рдХ, рдЖрдк рдкреНрд░рддреАрдХ рдЖрд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдФрд░ рд╕рдВрдЪрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдбрд┐рдХреЛрдбрд░ рдореЗрдВ рд╣рдлрдореИрди рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рдбрд┐рдХреЛрдбрд░ рд╕реЗ рдЕрдзрд┐рдХ рдХрд╛рдо рдФрд░ рдЕрдзрд┐рдХ рднрдВрдбрд╛рд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдПрдХ рдФрд░ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рдВрдкрддреНрддрд┐ рдпрд╣ рд╣реИ рдХрд┐ рд╡рд┐рд╣рд┐рдд рдХреЛрдб рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреБрд╢рд▓ рдбрд┐рдХреЛрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред

рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рд╕реЗ рдХрдо, рд╡рд░реНрдгреЛрдВ рдХреЛ рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреЛ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИред рдкрд╣рд▓рд╛ рдХреЛрдб рд╢рдмреНрдж рд╣реИ 0. рдЕрдЧрд▓рд╛ рд╢рдмреНрдж рдкрд┐рдЫрд▓реЗ рд╢рдмреНрдж рдХреА рд▓рдВрдмрд╛рдИ рдХреЗ рд╕рд╛рде рдПрдХ рд╢рдмреНрдж рд╣реЛрдЧрд╛ред 1. рдПрди рдХреА рд▓рдВрдмрд╛рдИ рд╡рд╛рд▓рд╛ рдкрд╣рд▓рд╛ рд╢рдмреНрдж рдПрди -1 рдХреА рд▓рдВрдмрд╛рдИ рдХреЗ рдЕрдВрддрд┐рдо рд╢рдмреНрдж рд╕реЗ рдмрдирд╛ рд╣реИ, рдПрдХ рдХреЛ рдЬреЛрдбрд╝рдирд╛ (рдПрдХ рдирдпрд╛ рдХреЛрдб рд╢рдмреНрдж рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП) рдФрд░ рдмрд╛рдИрдВ рдУрд░ рдПрдХ рдХрджрдо рд╢рд┐рдлреНрдЯ рдХрд░рдирд╛ (рд▓рдВрдмрд╛рдИ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП)ред

рд╣реЙрдлрдореИрди рдкреЗрдбрд╝ рдХреА рд╢рдмреНрджрд╛рд╡рд▓реА рдореЗрдВ, рдХреЛрдб рд╢рдмреНрдж рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдмрд╛рдПрдВ рд╕реЗ рджрд╛рдПрдВ, рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рд╕реНрддрд░ рдкрд░ рдкрддреНрддрд┐рдпреЛрдВ рдХреЛ рд╕реМрдВрдкрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдЧрд▓реЗ рд╕реНрддрд░ рдкрд░ рдЬрд╛рдиреЗ рдкрд░ рдмрд╛рдИрдВ рдУрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рд╣реЛрддрд╛ рд╣реИред

рд╣рдорд╛рд░реЗ ABCD рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдлрдореИрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдиреЗ 1, 2, 3, рдФрд░ 3 рдХреА рд▓рдВрдмрд╛рдИ рдХреЗ рд╕рд╛рде рдХреЛрдб рд╢рдмреНрдж рджрд┐рдП рд╣реИрдВред рдкрд╣рд▓рд╛ рд╢рдмреНрдж 0. рд╣реИред рдпрд╣ рд▓рдВрдмрд╛рдИ рдХрд╛ рдЕрдВрддрд┐рдо рд╢рдмреНрдж рднреА рд╣реИред рд▓рдВрдмрд╛рдИ 2 рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрдЧрд▓рд╛ рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 0 рд▓рдЧрддрд╛ рд╣реИ рдФрд░ 1 рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЬреЛ рджреЛ-рдмрд┐рдЯ рдХреЛрдб рдХрд╛ рдЙрдкрд╕рд░реНрдЧ рдмрди рдЬрд╛рдПрдЧрд╛ред , рдмрд╛рдИрдВ рдУрд░ рдЬрд╛рдПрдВ рдФрд░ 10. рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред рдпрд╣ рдЕрдм рд▓рдВрдмрд╛рдИ рдХрд╛ рдЕрдВрддрд┐рдо рд╢рдмреНрдж рд╣реИред рд▓рдВрдмрд╛рдИ 3 рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо 1 рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдФрд░ рд╢рд┐рдлреНрдЯ рдХрд░рддреЗ рд╣реИрдВ: 110ред рд▓рдВрдмрд╛рдИ 3 рдХреЗ рдЕрдЧрд▓реЗ рд╢рдмреНрдж рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо 1: 111 рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред

рдкреНрд░рддреАрдХрдХреЛрдбрд╡рд░реНрдб
рдП0
рдмреА10
рд╕реА110
рдбреА111

рд╡рд┐рд╣рд┐рдд рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ Deflate рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо LSB- рдкреНрд░рдердо рд╕рд┐рджреНрдзрд╛рдВрдд (рдкрд╣рд▓реЗ, рд╕рдмрд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреЛрдбрд╡рд░реНрдб рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред рдпрд╣реА рд╣реИ, рдХреЛрдбрд╡рд░реНрдб рдХрд╛ рдкрд╣рд▓рд╛ рдмрд┐рдЯ рдХрдо рд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдмрд┐рдЯреНрд╕ рдХреЗ рдХреНрд░рдо рдХреЛ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд▓реБрдХрдЕрдк рдЯреЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред

#define MAX_HUFFMAN_BITS 15          /* Deflate uses max 15-bit codewords. */

static void compute_canonical_code(uint16_t *codewords, const uint8_t *lengths,
                                   size_t n)
{
        size_t i;
        uint16_t count[MAX_HUFFMAN_BITS + 1] = {0};
        uint16_t code[MAX_HUFFMAN_BITS + 1];
        int l;

        /* Count the number of codewords of each length. */
        for (i = 0; i < n; i++) {
                count[lengths[i]]++;
        }
        count[0] = 0; /* Ignore zero-length codes. */

        /* Compute the first codeword for each length. */
        code[0] = 0;
        for (l = 1; l <= MAX_HUFFMAN_BITS; l++) {
                code[l] = (uint16_t)((code[l - 1] + count[l - 1]) << 1);
        }

        /* Assign a codeword for each symbol. */
        for (i = 0; i < n; i++) {
                l = lengths[i];
                if (l == 0) {
                        continue;
                }

                codewords[i] = reverse16(code[l]++, l); /* Make it LSB-first. */
        }
}

/* Reverse the n least significant bits of x.
   The (16 - n) most significant bits of the result will be zero. */
static inline uint16_t reverse16(uint16_t x, int n)
{
        uint16_t lo, hi;
        uint16_t reversed;

        assert(n > 0);
        assert(n <= 16);

        lo = x & 0xff;
        hi = x >> 8;

        reversed = (uint16_t)((reverse8_tbl[lo] << 8) | reverse8_tbl[hi]);

        return reversed >> (16 - n);
}

рдЕрдм рдЗрд╕реЗ рд╕рдм рдПрдХ рд╕рд╛рде рд░рдЦреЗрдВ рдФрд░ рдПрдирдХреЛрдбрд░ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЛрдб рд▓рд┐рдЦреЗрдВ:

typedef struct huffman_encoder_t huffman_encoder_t;
struct huffman_encoder_t {
        uint16_t codewords[MAX_HUFFMAN_SYMBOLS]; /* LSB-first codewords. */
        uint8_t lengths[MAX_HUFFMAN_SYMBOLS];    /* Codeword lengths. */
};

/* Initialize a Huffman encoder based on the n symbol frequencies. */
void huffman_encoder_init(huffman_encoder_t *e, const uint16_t *freqs, size_t n,
                          uint8_t max_codeword_len)
{
        assert(n <= MAX_HUFFMAN_SYMBOLS);
        assert(max_codeword_len <= MAX_HUFFMAN_BITS);

        compute_huffman_lengths(freqs, n, max_codeword_len, e->lengths);
        compute_canonical_code(e->codewords, e->lengths, n);
}

рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рдЧрдгрдирд╛ рдХреА рдЧрдИ рдХреЛрдб рд▓рдВрдмрд╛рдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдирдХреЛрдбрд░ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рддреЗ рд╣реИрдВ:

/* Initialize a Huffman encoder based on the n codeword lengths. */
void huffman_encoder_init2(huffman_encoder_t *e, const uint8_t *lengths,
                           size_t n)
{
        size_t i;

        for (i = 0; i < n; i++) {
                e->lengths[i] = lengths[i];
        }
        compute_canonical_code(e->codewords, e->lengths, n);
}

рдХреБрд╢рд▓ рд╣рдлрдореИрди рдбрд┐рдХреЛрдбрд┐рдВрдЧ


рд╣рдлрд╝рдореИрди рдХреЛ рдбрд┐рдХреЛрдб рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рдкреЗрдбрд╝ рдХреЛ рдЬрдбрд╝ рд╕реЗ рд╢реБрд░реВ рдХрд░рдирд╛ рд╣реИ, рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рд╕рд╛ рдЗрдирдкреБрдЯ рдкрдврд╝рдирд╛ рдФрд░ рдпрд╣ рддрдп рдХрд░рдирд╛ рдХрд┐ рдХреМрди рд╕реА рд╢рд╛рдЦрд╛ рдХреЛ рдЕрдЧрд▓реЗ, рдмрд╛рдПрдБ рдпрд╛ рджрд╛рдПрдБ рд▓реЗрдирд╛ рд╣реИред рдЬрдм рдПрдХ рдкрддреНрддрд╛ рдиреЛрдб рддрдХ рдкрд╣реБрдБрдЪ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдПрдХ рдбреАрдХреЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╡рд░реНрдг рд╣реЛрддрд╛ рд╣реИред

рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рдЕрдХреНрд╕рд░ рд╡рд┐рд╢реНрд╡рд╡рд┐рджреНрдпрд╛рд▓рдпреЛрдВ рдФрд░ рдкреБрд╕реНрддрдХреЛрдВ рдореЗрдВ рдкрдврд╝рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╕рд░рд▓ рдФрд░ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рдмрд┐рдЯ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдмрд╣реБрдд рдзреАрдорд╛ рд╣реИред рд▓реБрдХрдЕрдк рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбрд┐рдХреЛрдб рдХрд░рдирд╛ рдЕрдзрд┐рдХ рддреЗрдЬрд╝ рд╣реИред рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрд┐рд╕рдореЗрдВ рдЕрдзрд┐рдХрддрдо рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рддреАрди рдмрд┐рдЯреНрд╕ рд╣реИ, рдЖрдк рдирд┐рдореНрди рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

рдмрд┐рдЯреНрд╕рдкреНрд░рддреАрдХрдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИ
0 00рдП1
0 01рдП1
0 10рдП1
0 11рдП1
резреж режрдмреА2
резреж резрдмреА2
110рд╕реА3
111рдбреА3

рд╣рд╛рд▓рд╛рдВрдХрд┐ рдХреЗрд╡рд▓ рдЪрд╛рд░ рд╡рд░реНрдг рд╣реИрдВ, рд╣рдореЗрдВ рддреАрди рд╕рдВрднрд╡ рд╕рдВрдпреЛрдЬрди рдХреЛ рдХрд╡рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрда рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рддреАрди рдмрд┐рдЯреНрд╕ рд╕реЗ рдЫреЛрдЯреЗ рдХреЛрдбрд╡рд░реНрдб рд╡рд╛рд▓реЗ рдкреНрд░рддреАрдХреЛрдВ рдореЗрдВ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдХрдИ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдВ рд╣реЛрддреА рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 10 рд╢рдмреНрдж "рдкреВрд░рдХ" 10 10 рдФрд░ 10 1 рдХреЗ рд╕рд╛рде рдерд╛ред 10. рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рддреАрди-рдмрд┐рдЯ рд╕рдВрдпреЛрдЬрдиреЛрдВ рдХреЛ рдХрд╡рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред

рдЗрд╕ рддрд░рд╣ рд╕реЗ рдбреАрдХреЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддреАрди рдЗрдирдкреБрдЯ рдмрд┐рдЯреНрд╕ рдХреЗ рд╕рд╛рде рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рддреБрд░рдВрдд рд╕рдВрдмрдВрдзрд┐рдд рд╡рд░реНрдг рдФрд░ рдЙрд╕рдХреЗ рдХреЛрдб рд╢рдмреНрдж рдХреА рд▓рдВрдмрд╛рдИ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рд╣реЛрдЧрд╛ред рд▓рдВрдмрд╛рдИ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЕрдЧрд▓реЗ рддреАрди рдмрд┐рдЯреНрд╕ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рд╣рдореЗрдВ рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рдХреЗ рд╕рдорд╛рди рдЗрдирдкреБрдЯ рдмрд┐рдЯреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдЦреЛрдЬ рддрд╛рд▓рд┐рдХрд╛-рдЖрдзрд╛рд░рд┐рдд рд╡рд┐рдзрд┐ рдмрд╣реБрдд рддреЗрдЬрд╝реА рд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдПрдХ рдЦрд╛рдореА рд╣реИ: рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯ рдХреЗ рд╕рд╛рде рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЖрдХрд╛рд░ рджреЛрдЧреБрдирд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣реА рд╣реИ, рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рддреЗрдЬреА рд╕реЗ рдзреАрдорд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЕрдЧрд░ рдпрд╣ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреИрд╢ рдореЗрдВ рдлрд┐рдЯ рд╣реЛрдирд╛ рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╡рд┐рдзрд┐ рдзреАрд░реЗ-рдзреАрд░реЗ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддреА рд╣реИред

рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ, рд▓реБрдХрдЕрдк рдЯреЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдорддреМрд░ рдкрд░ рдХреЗрд╡рд▓ рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд▓рдВрдмрд╛рдИ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдФрд░ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рд╢рдмреНрдж рдПрдХ рдЕрд▓рдЧ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд▓реЗрддреЗ рд╣реИрдВред рдЬрд┐рд╕ рддрд░рд╣ рд╣рдлрдореИрди рдХреЛрдбрд┐рдВрдЧ рдХрдо рдХреЛрдбрд╡рд░реНрдб рдХреЛ рдЕрдзрд┐рдХ рдмрд╛рд░ рд╡рд░реНрдгреЛрдВ рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░рддрд╛ рд╣реИ, рд╡реИрд╕реЗ рд╣реА рд╢реЙрд░реНрдЯ рдХреЛрдбрд╡рд░реНрдб рдХреЗ рд▓рд┐рдП рд▓реБрдХрдЕрдк рдЯреЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдИ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рдЕрдиреБрдХреВрд▓рди рд╣реИред

рдЬрд╝рд╛рд▓рд┐рдм рдореЗрдВрдЦреЛрдЬ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЗ рдХрдИ рд╕реНрддрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдкрд╣рд▓реА рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд▓рд┐рдП рдХреЛрдбрд╡рд░реНрдб рдмрд╣реБрдд рд▓рдВрдмрд╛ рд╣реИ, рддреЛ рдЦреЛрдЬ рд╢реЗрд╖ рдмрд┐рдЯреНрд╕ рдХреЛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреНрд╡рд┐рддреАрдпрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдЬрд╛рдПрдЧреАред

рд▓реЗрдХрд┐рди рдПрдХ рдФрд░, рдмрд╣реБрдд рд╣реА рд╕реБрдВрджрд░ рд╡рд┐рдзрд┐ рд╣реИ, рдЬреЛ рдХреИрдиреЛрдирд┐рдХрд▓ рд╣рдлрдореИрди рдХреЛрдб рдХреЗ рдЧреБрдгреЛрдВ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред рдпрд╣ рдиреНрдпреВрдирддрдо рдЕрддрд┐рд░реЗрдХ рдЙрдкрд╕рд░реНрдЧ рд╕рдВрд╣рд┐рддрд╛рдУрдВ (рдореЛрдлрд╝рдд рдФрд░ рдЯрд░реНрдкрд┐рди, 1997) рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рд╡рд░реНрдгрд┐рдд рд╣реИ , рдФрд░ рдЗрд╕реЗ рдЪрд╛рд░реНрд▓реНрд╕ рдмреНрд▓реВрдо рдХреЗ рдж рд▓реЙрд╕реНрдЯ рд╣рдлрд╝рдореИрди рдкреЗрдкрд░ рдореЗрдВ рднреА рд╕рдордЭрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ ред

рдЖрдЗрдП рд╡рд┐рд╣рд┐рдд рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рдХреЛрдб рд╢рдмреНрдж рд▓реЗрддреЗ рд╣реИрдВ: 0, 10, 110, 111ред рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рд▓рдВрдмрд╛рдИ рдХреЗ рдкрд╣рд▓реЗ рдХреЛрдб рд╢рдмреНрджреЛрдВ рдФрд░ рд╕рд╛рде рд╣реА рд╕рд╛рдорд╛рдиреНрдп рдЕрдиреБрдХреНрд░рдо рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХреЛрдб рд╢рдмреНрдж рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЯреНрд░реИрдХ рдХрд░реЗрдВрдЧреЗ - "рдкреНрд░рддреАрдХ рд╕реВрдЪрдХрд╛рдВрдХ"ред

рдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИрдкрд╣рд▓рд╛ рдХреЛрдбрд╡рд░реНрдбрдкрд╣рд▓рд╛ рдЪрд░рд┐рддреНрд░ рд╕реВрдЪрдХрд╛рдВрдХ
101 (рдП)
2102 (рдмреА)
31103 (рд╕реА)

рдЪреВрдВрдХрд┐ рдХреЛрдб рд╢рдмреНрдж рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдЕрд╕рд╛рдЗрди рдХрд┐рдП рдЧрдП рд╣реИрдВ, рдЕрдЧрд░ рд╣рдореЗрдВ рдмрд┐рдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЙрдкрд░реЛрдХреНрдд рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпреЗ рдмрд┐рдЯреНрд╕ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рддреАрди-рдмрд┐рдЯ 111 рдХреЗ рд▓рд┐рдП рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдЗрд╕ рд▓рдВрдмрд╛рдИ (110) рдХреЗ рдкрд╣рд▓реЗ рдХреЛрдбрд╡рд░реНрдб рд╕реЗ рдПрдХ рдСрдлрд╕реЗрдЯ рд╣реИред рдЗрд╕ рд▓рдВрдмрд╛рдИ рдХрд╛ рдкрд╣рд▓рд╛ рд╡рд░реНрдг рд╕реВрдЪрдХрд╛рдВрдХ 3 рд╣реИ, рдФрд░ рдПрдХ рдХреА рдПрдХ рдСрдлрд╕реЗрдЯ рд╣рдореЗрдВ 4 рдХрд╛ рд╕реВрдЪрдХрд╛рдВрдХ рджреЗрддрд╛ рд╣реИред рдПрдХ рдЕрдиреНрдп рддрд╛рд▓рд┐рдХрд╛ рдЪрд░рд┐рддреНрд░ рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рддреБрд▓рдирд╛ рдЪрд░рд┐рддреНрд░ рдХреЗ рд╕рд╛рде рдХрд░рддреА рд╣реИ:

sym_idx = d->first_symbol[len] + (bits - d->first_code[len]);
sym = d->syms[sym_idx];

рдереЛрдбрд╝рд╛ рдЕрдиреБрдХреВрд▓рди: рдкрд╣рд▓реЗ рд╡рд░реНрдг рд╕реВрдЪрдХрд╛рдВрдХ рдФрд░ рдкрд╣рд▓реЗ рдХреЛрдб рд╢рдмреНрдж рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдкрд╣рд▓реЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдкрд╣рд▓реЗ рдХреЛрдб рд╢рдмреНрдж рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

sym_idx = d->offset_first_sym_idx[len] + bits;
sym = d->syms[sym_idx];

рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХрд┐рддрдиреЗ рдмрд┐рдЯреНрд╕ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд╣рдо рдлрд┐рд░ рд╕реЗ рдХреЛрдб рдЕрдиреБрдХреНрд░рдо рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╕рднреА рдорд╛рдиреНрдп рдПрдХ-рдмрд┐рдЯ рдХреЛрдбрд╡рд░реНрдб рдХрдбрд╝рд╛рдИ рд╕реЗ 1 рд╕реЗ рдХрдо рд╣реИрдВ, рджреЛ-рдмрд┐рдЯ - рд╕рдЦреНрддреА рд╕реЗ 11 рд╕реЗ рдХрдо, рддреАрди-рдмрд┐рдЯ - 1000 рд╕реЗ рдХрдо (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рднреА рддреАрди-рдмрд┐рдЯ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣реА)ред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдорд╛рдиреНрдп рдПрди-рдмрд┐рдЯ рдХреЛрдбрд╡рд░реНрдб рдкрд╣рд▓реЗ рдПрди-рдмрд┐рдЯ рдХреЛрдбрд╡рд░реНрдб рдФрд░ рдПрди-рдмрд┐рдЯ рдХреЛрдбрд╡рд░реНрдб рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдХрдбрд╝рд╛рдИ рд╕реЗ рдХрдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдЗрди рд╕реАрдорд╛рдУрдВ рдХреЛ рдмрд╛рдИрдВ рдУрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╡реЗ рд╕рднреА рддреАрди-рдмрд┐рдЯ рдЪреМрдбрд╝реЗ рд╣реЛрдВред рдЪрд▓реЛ рдЗрд╕реЗ рдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИ рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрдВрдзрд╛рддреНрдордХ рдмрд┐рдЯреНрд╕ рдХрд╣рддреЗ рд╣реИрдВ :

рдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИрдмрд┐рдЯреНрд╕ рд╕реАрдорд┐рдд рдХрд░реЗрдВ
1100
2110
31000

рд▓рдВрдмрд╛рдИ 3 рдХреЗ рд▓рд┐рдП рд╕реАрдордХ 4 рдмрд┐рдЯреНрд╕ рдкрд░ рдмрд╣ рдирд┐рдХрд▓рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдорддрд▓рдм рдХреЗрд╡рд▓ рдпрд╣реА рд╣реИ рдХрд┐ рдХреЛрдИ рднреА рддреАрди-рдмрд┐рдЯ рд╢рдмреНрдж рдХрд░реЗрдЧрд╛ред

рд╣рдо рддреАрди-рдмрд┐рдЯ рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЗ рдмреАрдЪ рдЦреЛрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддрд┐рдмрдВрдзрд╛рддреНрдордХ рдмрд┐рдЯреНрд╕ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рдХреЗ рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░рд╛ рдХреЛрдб рд╢рдмреНрдж рдХрд┐рддрдирд╛ рд▓рдВрдмрд╛ рд╣реИред рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЗрдирдкреБрдЯ рдмрд┐рдЯреНрд╕ рдХреЛ рд╢рд┐рдлреНрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдХреЗрд╡рд▓ рдЙрдирдХреА рд╕рд╣реА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╡рд░реНрдг рд╕реВрдЪрдХрд╛рдВрдХ рдкрд╛рддреЗ рд╣реИрдВ:

for (len = 1; len <= 3; len++) {
        if (bits < d->sentinel_bits[len]) {
                bits >>= 3 - len;  /* Get the len most significant bits. */
                sym_idx = d->offset_first_sym_idx[len] + bits;
        }
}

рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рд╕рдордп рдЬрдЯрд┐рд▓рддрд╛ рдХреЛрдб рд╢рдмреНрджреЛрдВ рдореЗрдВ рдмрд┐рдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рд░реИрдЦрд┐рдХ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдЧрд╣ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдЦрд░реНрдЪ рдХреА рдЬрд╛рддреА рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдЪрд░рдг рдкрд░ рдХреЗрд╡рд▓ рд▓реЛрдбрд┐рдВрдЧ рдФрд░ рддреБрд▓рдирд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЪреВрдВрдХрд┐ рдХрдо рдХреЛрдб рд╢рдмреНрдж рдЕрдзрд┐рдХ рд╕рд╛рдорд╛рдиреНрдп рд╣реЛрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╡рд┐рдзрд┐ рдХрдИ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рд╕рдВрдкреАрдбрд╝рди рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред

рдкреВрд░реНрдг рдбрд┐рдХреЛрдбрд░ рдХреЛрдб:

#define HUFFMAN_LOOKUP_TABLE_BITS 8  /* Seems a good trade-off. */

typedef struct huffman_decoder_t huffman_decoder_t;
struct huffman_decoder_t {
        /* Lookup table for fast decoding of short codewords. */
        struct {
                uint16_t sym : 9;  /* Wide enough to fit the max symbol nbr. */
                uint16_t len : 7;  /* 0 means no symbol. */
        } table[1U << HUFFMAN_LOOKUP_TABLE_BITS];

        /* "Sentinel bits" value for each codeword length. */
        uint16_t sentinel_bits[MAX_HUFFMAN_BITS + 1];

        /* First symbol index minus first codeword mod 2**16 for each length. */
        uint16_t offset_first_sym_idx[MAX_HUFFMAN_BITS + 1];

        /* Map from symbol index to symbol. */
        uint16_t syms[MAX_HUFFMAN_SYMBOLS];
#ifndef NDEBUG
        size_t num_syms;
#endif
};

/* Get the n least significant bits of x. */
static inline uint64_t lsb(uint64_t x, int n)
{
        assert(n >= 0 && n <= 63);
        return x & (((uint64_t)1 << n) - 1);
}

/* Use the decoder d to decode a symbol from the LSB-first zero-padded bits.
 * Returns the decoded symbol number or -1 if no symbol could be decoded.
 * *num_used_bits will be set to the number of bits used to decode the symbol,
 * or zero if no symbol could be decoded. */
static inline int huffman_decode(const huffman_decoder_t *d, uint16_t bits,
                                 size_t *num_used_bits)
{
        uint64_t lookup_bits;
        size_t l;
        size_t sym_idx;

        /* First try the lookup table. */
        lookup_bits = lsb(bits, HUFFMAN_LOOKUP_TABLE_BITS);
        assert(lookup_bits < sizeof(d->table) / sizeof(d->table[0]));
        if (d->table[lookup_bits].len != 0) {
                assert(d->table[lookup_bits].len <= HUFFMAN_LOOKUP_TABLE_BITS);
                assert(d->table[lookup_bits].sym < d->num_syms);

                *num_used_bits = d->table[lookup_bits].len;
                return d->table[lookup_bits].sym;
        }

        /* Then do canonical decoding with the bits in MSB-first order. */
        bits = reverse16(bits, MAX_HUFFMAN_BITS);
        for (l = HUFFMAN_LOOKUP_TABLE_BITS + 1; l <= MAX_HUFFMAN_BITS; l++) {
                if (bits < d->sentinel_bits[l]) {
                        bits >>= MAX_HUFFMAN_BITS - l;

                        sym_idx = (uint16_t)(d->offset_first_sym_idx[l] + bits);
                        assert(sym_idx < d->num_syms);

                        *num_used_bits = l;
                        return d->syms[sym_idx];
                }
        }

        *num_used_bits = 0;
        return -1;
}

рдбрд┐рдХреЛрдбрд░ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╡рд┐рд╣рд┐рдд рдХреЛрдбреЛрдВ рдХреА рдкреВрд░реНрд╡ рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ huffman_encoder_init рдХреЗ рд▓рд┐рдП , рдФрд░ рд╡рд┐рднрд┐рдиреНрди рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЛ рднрд░реЗрдВ:

/* Initialize huffman decoder d for a code defined by the n codeword lengths.
   Returns false if the codeword lengths do not correspond to a valid prefix
   code. */
bool huffman_decoder_init(huffman_decoder_t *d, const uint8_t *lengths,
                          size_t n)
{
        size_t i;
        uint16_t count[MAX_HUFFMAN_BITS + 1] = {0};
        uint16_t code[MAX_HUFFMAN_BITS + 1];
        uint32_t s;
        uint16_t sym_idx[MAX_HUFFMAN_BITS + 1];
        int l;

#ifndef NDEBUG
        assert(n <= MAX_HUFFMAN_SYMBOLS);
        d->num_syms = n;
#endif

        /* Zero-initialize the lookup table. */
        for (i = 0; i < sizeof(d->table) / sizeof(d->table[0]); i++) {
                d->table[i].len = 0;
        }

        /* Count the number of codewords of each length. */
        for (i = 0; i < n; i++) {
                assert(lengths[i] <= MAX_HUFFMAN_BITS);
                count[lengths[i]]++;
        }
        count[0] = 0;  /* Ignore zero-length codewords. */

        /* Compute sentinel_bits and offset_first_sym_idx for each length. */
        code[0] = 0;
        sym_idx[0] = 0;
        for (l = 1; l <= MAX_HUFFMAN_BITS; l++) {
                /* First canonical codeword of this length. */
                code[l] = (uint16_t)((code[l - 1] + count[l - 1]) << 1);

                if (count[l] != 0 && code[l] + count[l] - 1 > (1U << l) - 1) {
                        /* The last codeword is longer than l bits. */
                        return false;
                }

                s = (uint32_t)((code[l] + count[l]) << (MAX_HUFFMAN_BITS - l));
                d->sentinel_bits[l] = (uint16_t)s;
                assert(d->sentinel_bits[l] == s && "No overflow.");

                sym_idx[l] = sym_idx[l - 1] + count[l - 1];
                d->offset_first_sym_idx[l] = sym_idx[l] - code[l];
        }

        /* Build mapping from index to symbol and populate the lookup table. */
        for (i = 0; i < n; i++) {
                l = lengths[i];
                if (l == 0) {
                        continue;
                }

                d->syms[sym_idx[l]] = (uint16_t)i;
                sym_idx[l]++;

                if (l <= HUFFMAN_LOOKUP_TABLE_BITS) {
                        table_insert(d, i, l, code[l]);
                        code[l]++;
                }
        }

        return true;
}

static void table_insert(huffman_decoder_t *d, size_t sym, int len,
                         uint16_t codeword)
{
        int pad_len;
        uint16_t padding, index;

        assert(len <= HUFFMAN_LOOKUP_TABLE_BITS);

        codeword = reverse16(codeword, len); /* Make it LSB-first. */
        pad_len = HUFFMAN_LOOKUP_TABLE_BITS - len;

        /* Pad the pad_len upper bits with all bit combinations. */
        for (padding = 0; padding < (1U << pad_len); padding++) {
                index = (uint16_t)(codeword | (padding << len));
                d->table[index].sym = (uint16_t)sym;
                d->table[index].len = (uint16_t)len;

                assert(d->table[index].sym == sym && "Fits in bitfield.");
                assert(d->table[index].len == len && "Fits in bitfield.");
        }
}

рд╣рд╡рд╛ рдирд┐рдХрд╛рд▓рдирд╛


Deflate рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо, 1993 рдореЗрдВ PKZip 2.04c рдореЗрдВ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЧрдпрд╛, рдЖрдзреБрдирд┐рдХ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдПрдХ рдорд╛рдирдХ рд╕рдВрдкреАрдбрд╝рди рд╡рд┐рдзрд┐ рд╣реИред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ gzip, PNG рдФрд░ рдХрдИ рдЕрдиреНрдп рдкреНрд░рд╛рд░реВрдкреЛрдВ рдореЗрдВ рднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ LZ77 рд╕рдВрдкреАрдбрд╝рди рдФрд░ рд╣рдлрд╝рдореИрди рдХреЛрдбрд┐рдВрдЧ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдЗрд╕ рдЦрдВрдб рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХрд░реЗрдВрдЧреЗ рдФрд░ рд▓рд╛рдЧреВ рдХрд░реЗрдВрдЧреЗред

Deflate рд╕реЗ рдкрд╣рд▓реЗ, PKZip рдиреЗ Shrink, Reduce, рдФрд░ Implode рд╕рдВрдкреАрдбрд╝рди рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред рдЖрдЬ рд╡реЗ рджреБрд░реНрд▓рдн рд╣реИрдВ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рдбреЗрдлрд▓реЗрдЯ рдХреЗ рдмрд╛рдж рднреА рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдореЗрдВ рдереЗ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдХрдо рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рддреЗ рдереЗред рд▓реЗрдХрд┐рди рд╣рдо рдЙрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред

рдмрд┐рдЯ рд╕реНрдЯреНрд░реАрдо


рдПрд▓рдПрд╕рдмреА-рдкреНрд░рдердо рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╣рдлрд╝рдореИрди рдХреЛрдбрд╡рд░реНрдб рдХреЛ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рдореЗрдВ рд╕реНрдЯреЛрд░ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рд╕реНрдЯреНрд░реАрдо рдХрд╛ рдкрд╣рд▓рд╛ рдмрд┐рдЯ рдкрд╣рд▓реЗ рдмрд╛рдЗрдЯ рдХреЗ рдХрдо рд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИред

рдПрдХ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ (рдмрд╛рдПрдВ рд╕реЗ рджрд╛рдПрдВ рдкрдврд╝реЗрдВ) 1-0-0-1-1ред рдЬрдм рдЗрд╕реЗ рдПрд▓рдПрд╕рдмреА-рдкрд╣рд▓реЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдмрд╛рдЗрдЯ рдорд╛рди 0b00011001 (рдмрд╛рдЗрдирд░реА) рдпрд╛ 0x19 (рд╣реЗрдХреНрд╕рд╛рдбреЗрд╕рд┐рдорд▓) рдмрди рдЬрд╛рддрд╛ рд╣реИред рдРрд╕рд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдзрд╛рд░рд╛ рдХреЛ рдХреЗрд╡рд▓ рдкреАрдЫреЗ рдХреА рдУрд░ (рдПрдХ рдЕрд░реНрде рдореЗрдВ, рдпрд╣ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ) рд╣реИ, рд▓реЗрдХрд┐рди рдлрд╛рдпрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдХрдВрдкреНрдпреВрдЯрд░ рд╢рдмреНрдж рд╕реЗ рдкрд╣рд▓рд╛ рдПрди рдмрд┐рдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЖрд╕рд╛рди рд╣реИ: рд╣рдо рдмрд╕ рдПрди рдХрдо рд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯреНрд╕ рдХреЛ рдЫрд┐рдкрд╛рддреЗ рд╣реИрдВред

рдпреЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рд╕реЗ рд▓реА рдЧрдИ рд╣реИрдВ :

/* Input bitstream. */
typedef struct istream_t istream_t;
struct istream_t {
        const uint8_t *src;  /* Source bytes. */
        const uint8_t *end;  /* Past-the-end byte of src. */
        size_t bitpos;       /* Position of the next bit to read. */
        size_t bitpos_end;   /* Position of past-the-end bit. */
};

/* Initialize an input stream to present the n bytes from src as an LSB-first
 * bitstream. */
static inline void istream_init(istream_t *is, const uint8_t *src, size_t n)
{
        is->src = src;
        is->end = src + n;
        is->bitpos = 0;
        is->bitpos_end = n * 8;
}

рд╣рдорд╛рд░реЗ рд╣рдлрд╝рдореИрди рдбрд┐рдХреЛрдбрд░ рдХреЛ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдмрд┐рдЯреНрд╕ рджреЗрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рд╕рдВрднрд╡ рд╕рдмрд╕реЗ рд▓рдВрдмреЗ рдХреЛрдбрд╡рд░реНрдб рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдмрд┐рдЯреНрд╕), рдФрд░ рдлрд┐рд░ рдбрд┐рдХреЛрдб рдХрд┐рдП рдЧрдП рдкреНрд░рддреАрдХ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдмрд┐рдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рджреНрд╡рд╛рд░рд╛ рд╕реНрдЯреНрд░реАрдо рдЬрд╛рд░реА рд░рдЦреЗрдВ:

#define ISTREAM_MIN_BITS (64 - 7)

/* Get the next bits from the input stream. The number of bits returned is
 * between ISTREAM_MIN_BITS and 64, depending on the position in the stream, or
 * fewer if the end of stream is reached. The upper bits are zero-padded. */
static inline uint64_t istream_bits(const istream_t *is)
{
        const uint8_t *next;
        uint64_t bits;
        int i;

        next = is->src + (is->bitpos / 8);

        assert(next <= is->end && "Cannot read past end of stream.");

        if (is->end - next >= 8) {
                /* Common case: read 8 bytes in one go. */
                bits = read64le(next);
        } else {
                /* Read the available bytes and zero-pad. */
                bits = 0;
                for (i = 0; i < is->end - next; i++) {
                        bits |= (uint64_t)next[i] << (i * 8);
                }
        }

        return bits >> (is->bitpos % 8);
}

/* Advance n bits in the bitstream if possible. Returns false if that many bits
 * are not available in the stream. */
static inline bool istream_advance(istream_t *is, size_t n) {
        if (is->bitpos + n > is->bitpos_end) {
                return false;
        }

        is->bitpos += n;
        return true;
}

рд▓рдмреНрдмреЛрд▓реБрдЖрдм рдпрд╣ рд╣реИ рдХрд┐ 64-рдмрд┐рдЯ рдорд╢реАрдиреЛрдВ рдкрд░ istream_bitsрдЖрдк рдЖрдорддреМрд░ рдкрд░ рдПрдХрд▓-рдмреВрдЯ рдирд┐рд░реНрджреЗрд╢ рдФрд░ рдХреБрдЫ рдЕрдВрдХрдЧрдгрд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рддрддреНрд╡ istream_tрд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рд╣реИрдВред read64le рдмрд┐рдЯреНрд╕ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред (рдЖрдзреБрдирд┐рдХ рд╕рдВрдХрд▓рдХ рдЗрд╕реЗ рдЫреЛрдЯреЗ-рдПрдВрдбрд┐рдпрди рд╕рд┐рджреНрдзрд╛рдВрдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ 64-рдмрд┐рдЯ рдбрд╛рдЙрдирд▓реЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ):

/* Read a 64-bit value from p in little-endian byte order. */
static inline uint64_t read64le(const uint8_t *p)
{
        /* The one true way, see
         * https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html */
        return ((uint64_t)p[0] << 0)  |
               ((uint64_t)p[1] << 8)  |
               ((uint64_t)p[2] << 16) |
               ((uint64_t)p[3] << 24) |
               ((uint64_t)p[4] << 32) |
               ((uint64_t)p[5] << 40) |
               ((uint64_t)p[6] << 48) |
               ((uint64_t)p[7] << 56);
}

рд╣рдореЗрдВ рдЕрдЧрд▓реЗ рдмрд╛рдЗрдЯ рдХреА рд╕реАрдорд╛ рддрдХ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

/* Round x up to the next multiple of m, which must be a power of 2. */
static inline size_t round_up(size_t x, size_t m)
{
        assert((m & (m - 1)) == 0 && "m must be a power of two");
        return (x + m - 1) & (size_t)(-m); /* Hacker's Delight (2nd), 3-1. */
}

/* Align the input stream to the next 8-bit boundary and return a pointer to
 * that byte, which may be the past-the-end-of-stream byte. */
static inline const uint8_t *istream_byte_align(istream_t *is)
{
        const uint8_t *byte;

        assert(is->bitpos <= is->bitpos_end && "Not past end of stream.");

        is->bitpos = round_up(is->bitpos, 8);
        byte = is->src + is->bitpos / 8;
        assert(byte <= is->end);

        return byte;
}

рдПрдХ рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рдХреЗ рд▓рд┐рдП, рд╣рдо рд░реАрдб-рдореЙрдбрд┐рдлрд╛рдИ-рд░рд╛рдЗрдЯ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрд┐рдЯреНрд╕ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рддреНрд╡рд░рд┐рдд рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЖрдк 64-рдмрд┐рдЯ рд░реАрдб, рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд┐рдЯ рдСрдкрд░реЗрд╢рди рдФрд░ 64-рдмрд┐рдЯ рд▓реЗрдЦрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдереЛрдбрд╝рд╛ рд▓рд┐рдЦ тАЛтАЛрд╕рдХрддреЗ рд╣реИрдВред

/* Output bitstream. */
typedef struct ostream_t ostream_t;
struct ostream_t {
        uint8_t *dst;
        uint8_t *end;
        size_t bitpos;
        size_t bitpos_end;
};

/* Initialize an output stream to write LSB-first bits into dst[0..n-1]. */
static inline void ostream_init(ostream_t *os, uint8_t *dst, size_t n)
{
        os->dst = dst;
        os->end = dst + n;
        os->bitpos = 0;
        os->bitpos_end = n * 8;
}

/* Get the current bit position in the stream. */
static inline size_t ostream_bit_pos(const ostream_t *os)
{
        return os->bitpos;
}

/* Return the number of bytes written to the output buffer. */
static inline size_t ostream_bytes_written(ostream_t *os)
{
        return round_up(os->bitpos, 8) / 8;
}

/* Write n bits to the output stream. Returns false if there is not enough room
 * at the destination. */
static inline bool ostream_write(ostream_t *os, uint64_t bits, size_t n)
{
        uint8_t *p;
        uint64_t x;
        int shift, i;

        assert(n <= 57);
        assert(bits <= ((uint64_t)1 << n) - 1 && "Must fit in n bits.");

        if (os->bitpos_end - os->bitpos < n) {
                /* Not enough room. */
                return false;
        }

        p = &os->dst[os->bitpos / 8];
        shift = os->bitpos % 8;

        if (os->end - p >= 8) {
                /* Common case: read and write 8 bytes in one go. */
                x = read64le(p);
                x = lsb(x, shift);
                x |= bits << shift;
                write64le(p, x);
        } else {
                /* Slow case: read/write as many bytes as are available. */
                x = 0;
                for (i = 0; i < os->end - p; i++) {
                        x |= (uint64_t)p[i] << (i * 8);
                }
                x = lsb(x, shift);
                x |= bits << shift;
                for (i = 0; i < os->end - p; i++) {
                        p[i] = (uint8_t)(x >> (i * 8));
                }
        }

        os->bitpos += n;

        return true;
}

/* Write a 64-bit value x to dst in little-endian byte order. */
static inline void write64le(uint8_t *dst, uint64_t x)
{
        dst[0] = (uint8_t)(x >> 0);
        dst[1] = (uint8_t)(x >> 8);
        dst[2] = (uint8_t)(x >> 16);
        dst[3] = (uint8_t)(x >> 24);
        dst[4] = (uint8_t)(x >> 32);
        dst[5] = (uint8_t)(x >> 40);
        dst[6] = (uint8_t)(x >> 48);
        dst[7] = (uint8_t)(x >> 56);
}

рд╣рдореЗрдВ рд╕реНрдЯреНрд░реАрдо рдХреЛ рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рдХреБрд╢рд▓рддрд╛рдкреВрд░реНрд╡рдХ рд▓рд┐рдЦрдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдмреЗрд╢рдХ, рдЖрдк рдмрд╛рд░-рдмрд╛рд░ 8-рдмрд┐рдЯ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмрд╣реБрдд рддреЗрдЬрд╝ рд╣реЛрдЧрд╛ memcpy:

/* Align the bitstream to the next byte boundary, then write the n bytes from
   src to it. Returns false if there is not enough room in the stream. */
static inline bool ostream_write_bytes_aligned(ostream_t *os,
                                               const uint8_t *src,
                                               size_t n)
{
        if (os->bitpos_end - round_up(os->bitpos, 8) < n * 8) {
                return false;
        }

        os->bitpos = round_up(os->bitpos, 8);
        memcpy(&os->dst[os->bitpos / 8], src, n);
        os->bitpos += n * 8;

        return true;
}

рдЕрдирдкреИрдХрд┐рдВрдЧ (рдореБрджреНрд░рд╛рд╕реНрдлреАрддрд┐)


рдЪреВрдВрдХрд┐ рд╕рдВрдкреАрдбрд╝рди рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рдбрд┐рдлреНрд▓реИрдЯ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ - рдЙрдбрд╝рд╛рдирд╛ , рдХрд┐рд╕реА рдЪреАрдЬ рд╕реЗ рд╣рд╡рд╛ рдирд┐рдХрд╛рд▓рдирд╛ - рдЕрдирдкреИрдХрд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХрднреА-рдХрднреА рдореБрджреНрд░рд╛рд╕реНрдлреАрддрд┐ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдпрджрд┐ рдЖрдк рдкрд╣рд▓реА рдмрд╛рд░ рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╕рдордЭреЗрдВрдЧреЗ рдХрд┐ рдкреНрд░рд╛рд░реВрдк рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЖрдк рдХреЛрдб рдХреЛ deflate.h рдФрд░ deflate.c , bit.h , tables.h рдФрд░ tables.c рдХреЗ рдкрд╣рд▓реЗ рднрд╛рдЧ рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ ( Generate_tables.c рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрддреНрдкрдиреНрди )ред

Deflate рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдкреАрдбрд╝рд┐рдд рдбреЗрдЯрд╛ рдХреЛ рдмреНрд▓реЙрдХ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ редред рдкреНрд░рддреНрдпреЗрдХ рдмреНрд▓реЙрдХ 3-рдмрд┐рдЯ рд╣реЗрдбрд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкрд╣рд▓рд╛ (рд╕рдмрд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг) рдмрд┐рдЯ рд╕реЗрдЯ рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рдпрд╣ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рдЕрдВрддрд┐рдо рдмреНрд▓реЙрдХ рд╣реИ, рдФрд░ рдЕрдиреНрдп рджреЛ рдмрд┐рдЯреНрд╕ рдЗрд╕рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВред


рддреАрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдмреНрд▓реЙрдХ рд╣реИрдВ: рдЕрд╕рдореНрдкреАрдбрд┐рдд (0), рдирд┐рд╢реНрдЪрд┐рдд рд╣рдлрд╝рдореИрди рдХреЛрдб (1) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдФрд░ "рдбрд╛рдпрдиреЗрдорд┐рдХ" рд╣рдлрд╝рдореИрди рдХреЛрдб (2) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдкреАрдбрд╝рд┐рддред

рдпрд╣ рдХреЛрдб рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдмреНрд▓реЙрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдирдкреИрдХрд┐рдВрдЧ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдмрд╛рдж рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░реЗрдВрдЧреЗ:

typedef enum {
        HWINF_OK,   /* Inflation was successful. */
        HWINF_FULL, /* Not enough room in the output buffer. */
        HWINF_ERR   /* Error in the input data. */
} inf_stat_t;

/* Decompress (inflate) the Deflate stream in src. The number of input bytes
   used, at most src_len, is stored in *src_used on success. Output is written
   to dst. The number of bytes written, at most dst_cap, is stored in *dst_used
   on success. src[0..src_len-1] and dst[0..dst_cap-1] must not overlap.
   Returns a status value as defined above. */
inf_stat_t hwinflate(const uint8_t *src, size_t src_len, size_t *src_used,
                     uint8_t *dst, size_t dst_cap, size_t *dst_used)
{
        istream_t is;
        size_t dst_pos;
        uint64_t bits;
        bool bfinal;
        inf_stat_t s;

        istream_init(&is, src, src_len);
        dst_pos = 0;

        do {
                /* Read the 3-bit block header. */
                bits = istream_bits(&is);
                if (!istream_advance(&is, 3)) {
                        return HWINF_ERR;
                }
                bfinal = bits & 1;
                bits >>= 1;

                switch (lsb(bits, 2)) {
                case 0: /* 00: No compression. */
                        s = inf_noncomp_block(&is, dst, dst_cap, &dst_pos);
                        break;
                case 1: /* 01: Compressed with fixed Huffman codes. */
                        s = inf_fixed_block(&is, dst, dst_cap, &dst_pos);
                        break;
                case 2: /* 10: Compressed with "dynamic" Huffman codes. */
                        s = inf_dyn_block(&is, dst, dst_cap, &dst_pos);
                        break;
                default: /* Invalid block type. */
                        return HWINF_ERR;
                }

                if (s != HWINF_OK) {
                        return s;
                }
        } while (!bfinal);

        *src_used = (size_t)(istream_byte_align(&is) - src);

        assert(dst_pos <= dst_cap);
        *dst_used = dst_pos;

        return HWINF_OK;
}

рдЕрд╕рдореНрдмрджреНрдз рдЦрдВрдб рдЦрдВрдб


рдпреЗ "рд╕рдВрдЧреНрд░рд╣рд┐рдд" рдмреНрд▓реЙрдХ рд╣реИрдВ, рд╕рдмрд╕реЗ рд╕рд░рд▓ рдкреНрд░рдХрд╛рд░ред рдпрд╣ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рдХреА рдЕрдЧрд▓реА 8-рдмрд┐рдЯ рд╕реАрдорд╛ рдХреЗ рд╕рд╛рде 16-рдмрд┐рдЯ рд╢рдмреНрдж (рд▓реЗрди) рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдмреНрд▓реЙрдХ рдХреА рд▓рдВрдмрд╛рдИ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдкреАрдЫреЗ рдПрдХ рдФрд░ 16-рдмрд┐рдЯ рд╢рдмреНрдж (рдПрдирдПрд▓рдПрди) рд╣реИ, рдЬреЛ рдЬреЗрди рд╢рдмреНрдж рдХрд╛ рд╕рдВрдХрд▓рди (рдмрд┐рдЯреНрд╕ рдХрд╛ рдХреНрд░рдо рдЙрд▓реНрдЯрд╛) рд╣реИред рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдПрдирдПрд▓рдПрди рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд▓реЗрди рдЪреЗрдХрд╕рдо рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ: рдпрджрд┐ рдлрд╝рд╛рдЗрд▓ рдХреНрд╖рддрд┐рдЧреНрд░рд╕реНрдд рд╣реИ, рддреЛ рдорд╛рди рд╢рд╛рдпрдж рдкреВрд░рдХ рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдПрдХ рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛ред


рд▓реЗрди рдФрд░ nlen рдХреЗ рдмрд╛рдж рдбреЗрдЯрд╛ рдЕрд╕рдореНрдкреАрдбрд┐рдд рд╣реИрдВред рдЪреВрдВрдХрд┐ рдмреНрд▓реЙрдХ рдХреА рд▓рдВрдмрд╛рдИ 16-рдмрд┐рдЯ рдорд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдбреЗрдЯрд╛ рдХрд╛ рдЖрдХрд╛рд░ 65,535 рдмрд╛рдЗрдЯреНрд╕ рддрдХ рд╕реАрдорд┐рдд рд╣реИред

static inf_stat_t inf_noncomp_block(istream_t *is, uint8_t *dst,
                                    size_t dst_cap, size_t *dst_pos)
{
        const uint8_t *p;
        uint16_t len, nlen;

        p = istream_byte_align(is);

        /* Read len and nlen (2 x 16 bits). */
        if (!istream_advance(is, 32)) {
                return HWINF_ERR; /* Not enough input. */
        }
        len  = read16le(p);
        nlen = read16le(p + 2);
        p += 4;

        if (nlen != (uint16_t)~len) {
                return HWINF_ERR;
        }

        if (!istream_advance(is, len * 8)) {
                return HWINF_ERR; /* Not enough input. */
        }

        if (dst_cap - *dst_pos < len) {
                return HWINF_FULL; /* Not enough room to output. */
        }

        memcpy(&dst[*dst_pos], p, len);
        *dst_pos += len;

        return HWINF_OK;
}

рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣рдлрд╝рдореИрди рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЦрдВрдбреЛрдВ рдХреЛ рдЦрдВрдбрд┐рдд рдХрд░реЗрдВ


рд╕рдВрдХреБрдЪрд┐рдд рдЦрдВрдбрди рдЦрдВрдб HZman рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ LZ77 рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВред рдмреНрд▓реЙрдХ рдПрдВрдб рдорд╛рд░реНрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХреЛ рддреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╢рд╛рдмреНрджрд┐рдХ, рдмреИрдХрд▓рд┐рдВрдХ рд▓рдВрдмрд╛рдИ рдФрд░ рдорд╛рд░реНрдХрд░ рдХреЗ рд▓рд┐рдП, рд▓рд┐рдЯрд▓рди рд╣рдлрд╝рдореИрди рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдФрд░ рдмреИрдХрд▓рд┐рдВрдХ рджреВрд░реА рдХреЗ рд▓рд┐рдП, рдбрд┐рд╕реНрдЯ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред


рд▓рд┐рдЯрд▓реЗрди 0-285 рдХреА рд╕реАрдорд╛ рдореЗрдВ рдорд╛рдиреЛрдВ рдХреЛ рдПрдирдХреЛрдб рдХрд░рддрд╛ рд╣реИред рдорд╛рди 0-255 рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, 256 рдЕрдВрдд-рдСрдл-рдмреНрд▓реЙрдХ рдорд╛рд░реНрдХрд░ рд╣реИ, рдФрд░ 257-285 рдмреИрдХрд▓рд┐рдВрдХ рд▓рдВрдмрд╛рдИ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдмреИрдХрд▓рд┐рдВрдХреНрд╕ 3-258 рдмрд╛рдЗрдЯреНрд╕ рд▓рдВрдмреЗ рд╣реЛрддреЗ рд╣реИрдВред рд▓рд┐рдЯрд▓реЗрди рдореВрд▓реНрдп рдЖрдзрд╛рд░ рдХреА рд▓рдВрдмрд╛рдИ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдиреАрдЪреЗ рдХреА рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреВрд░реНрдг рд▓рдВрдмрд╛рдИ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрд╛рд░рд╛ рд╕реЗ рд╢реВрдиреНрдп рдпрд╛ рдЕрдзрд┐рдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯреНрд╕ рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 269 рдХреЗ рдПрдХ рд▓рд┐рдЯрд▓рди рдорд╛рди рдХрд╛ рдЕрд░реНрде рд╣реИ рдЖрдзрд╛рд░ рдХреА рд▓рдВрдмрд╛рдИ 19 рдФрд░ рджреЛ рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯреНрд╕ред рдзрд╛рд░рд╛ рд╕реЗ рджреЛ рдмрд┐рдЯреНрд╕ рдХрд╛ рдЬреЛрдбрд╝ 19 рд╕реЗ 22 рддрдХ рдЕрдВрддрд┐рдо рд▓рдВрдмрд╛рдИ рджреЗрддрд╛ рд╣реИред

LitlenрдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯреНрд╕рд▓рдВрдмрд╛рдИ
25703
25804
25905
26006
26107
26208
26309
264010
265111-12
266113-14
267115-16
268117-18
269219-22
270223-26
271227-30
272231-34
273335-42
274343-50
275351-58
276359-66
277467-82
278483-98
279499-114
2804115-130
2815131-162
2825163-194
2835195-226
2845227-257
2850258

рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ 284 рдкреНрд▓рд╕ 5 рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯреНрд╕ рдХрд╛ рдПрдХ рд▓рд┐рдЯрд▓рди рдорд╛рди 227 рд╕реЗ 258 рддрдХ рдХреА рд▓рдВрдмрд╛рдИ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рд▓рдВрдмрд╛рдИ 258 - рдмреИрдХрд▓рд┐рдВрдХ рдХреА рдЕрдзрд┐рдХрддрдо рд▓рдВрдмрд╛рдИ - рдПрдХ рдЕрд▓рдЧ рд▓рд┐рдЯреНрд▓рд┐рди рдореВрд▓реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджрд░реНрд╢рд╛рдИ рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЙрди рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдХреЛрдбрд┐рдВрдЧ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдЕрдзрд┐рдХрддрдо рд▓рдВрдмрд╛рдИ рдЕрдХреНрд╕рд░ рд╕рд╛рдордирд╛ рд╣реЛрддреА рд╣реИред

рдбреАрдХрдВрдкреНрд░реЗрд╕рд░ рд▓рд┐рдЯрд▓рди рдорд╛рди (рдмреЗрд╕ 257) рд╕реЗ рдмреЗрд╕ рдХреА рд▓рдВрдмрд╛рдИ рдФрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:

/* Table of litlen symbol values minus 257 with corresponding base length
   and number of extra bits. */
struct litlen_tbl_t {
        uint16_t base_len : 9;
        uint16_t ebits : 7;
};
const struct litlen_tbl_t litlen_tbl[29] = {
/* 257 */ { 3, 0 },
/* 258 */ { 4, 0 },

...

/* 284 */ { 227, 5 },
/* 285 */ { 258, 0 }
};

рд╣рдлрд╝рдореИрди рдХрд╛ рдирд┐рд╢реНрдЪрд┐рдд рд▓рд┐рдЯрд▓рди рдХреЛрдб рдХреИрдиреЛрдирд┐рдХрд▓ рд╣реИ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ (286-287 рдорд╛рдиреНрдп рд▓рд┐рдЯрд▓рди рдорд╛рди рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡реЗ рдХреЛрдб рдкреАрдврд╝реА рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ):

рд▓рд┐рдЯрд▓рди рдорд╛рдирдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИ
0-1438
144-2559
256-2797
280-2878

рдбреАрдХрдВрдкреНрд░реЗрд╕рд░ рдЗрди рд▓рдВрдмрд╛рдИ рдХреЛ рд╕рдВрдЪрд░рдг рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ huffman_decoder_init:

const uint8_t fixed_litlen_lengths[288] = {
/*   0 */ 8,
/*   1 */ 8,

...

/* 287 */ 8,
};

рдмреИрдХрд▓рд┐рдВрдХ рдХреА рджреВрд░реА 1 рд╕реЗ 32,768 рддрдХ рд╣реЛрддреА рд╣реИред рд╡реЗ рдПрдХ рдРрд╕реА рдпреЛрдЬрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдиреНрдХреЛрдбреЗрдб рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рд▓рдВрдмрд╛рдИ рдХреЛрдбрд┐рдВрдЧ рдпреЛрдЬрдирд╛ рдХреЗ рд╕рдорд╛рди рд╣реИред рд╣рдлрд╝рдореИрди рдХреЛрдб рдбрд┐рд╕реНрдЯреНрд░реЗрд╕ рдорд╛рдиреЛрдВ рдХреЛ 0 рд╕реЗ 29 рддрдХ рдПрдиреНрдХреЛрдб рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдЖрдзрд╛рд░ рдХреА рд▓рдВрдмрд╛рдИ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЕрдВрддрд┐рдо рджреВрд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯреНрд╕ рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВ:

рдЬрд┐рд▓рд╛рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд┐рдЯреНрд╕рджреВрд░рд┐рдпрд╛рдВ
001
102
203
304
415-6
517-8
629-12
7213-16
8317-24
9325-32
10433-48
рдЧреНрдпрд╛рд░рд╣449-64
12565-96
рддреЗрд░рд╣597-128
146129-192
рдкрдВрджреНрд░рд╣6193-256
рд╕реЛрд▓рд╣7257-384
177385-512
рдЕрдард╛рд░рд╣8513-768
рдЙрдиреНрдиреАрд╕8769-1024
рдмреАрд╕91025-1536
2191537-2048
22102049-3072
23103073-4096
24рдЧреНрдпрд╛рд░рд╣4097-6144
25рдЧреНрдпрд╛рд░рд╣6145-8192
26128,193-12,288
271212,289-16,384
28рддреЗрд░рд╣16,385-24,576
29 рд╡реЗрдВрддреЗрд░рд╣24,577-32,768

рд╣рдлрдореИрди рдХрд╛ рдирд┐рд╢реНрдЪрд┐рдд рдХреЛрдб рдбрд┐рд╕реНрдЯреЗрдВрд╕рд┐рдХ рд╣реИред рд╕рднреА рдХреЛрдбрд╡рд░реНрдб 5 рдмрд┐рдЯ рд▓рдВрдмреЗ рд╣реЛрддреЗ рд╣реИрдВред рдпрд╣ рд╕рд░рд▓ рд╣реИ, рдбреАрдХрдВрдкреНрд░реЗрд╕рд░ рдХреЛрдб рдХреЛ рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ huffman_decoder_init(рдбрд┐рд╕реНрдЯ рдорд╛рди 30-31 рд╕рд╣реА рдирд╣реАрдВ рд╣реИрдВред рдпрд╣ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рд╣рдлрд╝рдореИрди рдХреЛрдб рдХреА рдкреАрдврд╝реА рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕рдХрд╛ рдХреЛрдИ рдкреНрд░рднрд╛рд╡ рдирд╣реАрдВ рд╣реИ):

const uint8_t fixed_dist_lengths[32] = {
/*  0 */ 5,
/*  1 */ 5,

...

/* 31 */ 5,
};

рдЕрдкрдШрдЯрди рдпрд╛ рдЕрдирдкреИрдХрд┐рдВрдЧ рдХреЛрдб - рдирд┐рд╢реНрдЪрд┐рдд рд╣рдлрдореИрди рдХреЛрдбреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЦрдВрдб рдХреЛ рдЦрдВрдбрд┐рдд рдХрд░реЗрдВ:

static inf_stat_t inf_fixed_block(istream_t *is, uint8_t *dst,
                                  size_t dst_cap, size_t *dst_pos)
{
        huffman_decoder_t litlen_dec, dist_dec;

        huffman_decoder_init(&litlen_dec, fixed_litlen_lengths,
                             sizeof(fixed_litlen_lengths) /
                             sizeof(fixed_litlen_lengths[0]));
        huffman_decoder_init(&dist_dec, fixed_dist_lengths,
                             sizeof(fixed_dist_lengths) /
                             sizeof(fixed_dist_lengths[0]));

        return inf_block(is, dst, dst_cap, dst_pos, &litlen_dec, &dist_dec);
}

#define LITLEN_EOB 256
#define LITLEN_MAX 285
#define LITLEN_TBL_OFFSET 257
#define MIN_LEN 3
#define MAX_LEN 258

#define DISTSYM_MAX 29
#define MIN_DISTANCE 1
#define MAX_DISTANCE 32768

static inf_stat_t inf_block(istream_t *is, uint8_t *dst, size_t dst_cap,
                            size_t *dst_pos,
                            const huffman_decoder_t *litlen_dec,
                            const huffman_decoder_t *dist_dec)
{
        uint64_t bits;
        size_t used, used_tot, dist, len;
        int litlen, distsym;
        uint16_t ebits;

        while (true) {
                /* Read a litlen symbol. */
                bits = istream_bits(is);
                litlen = huffman_decode(litlen_dec, (uint16_t)bits, &used);
                bits >>= used;
                used_tot = used;

                if (litlen < 0 || litlen > LITLEN_MAX) {
                        /* Failed to decode, or invalid symbol. */
                        return HWINF_ERR;
                } else if (litlen <= UINT8_MAX) {
                        /* Literal. */
                        if (!istream_advance(is, used_tot)) {
                                return HWINF_ERR;
                        }
                        if (*dst_pos == dst_cap) {
                                return HWINF_FULL;
                        }
                        lz77_output_lit(dst, (*dst_pos)++, (uint8_t)litlen);
                        continue;
                } else if (litlen == LITLEN_EOB) {
                        /* End of block. */
                        if (!istream_advance(is, used_tot)) {
                                return HWINF_ERR;
                        }
                        return HWINF_OK;
                }

                /* It is a back reference. Figure out the length. */
                assert(litlen >= LITLEN_TBL_OFFSET && litlen <= LITLEN_MAX);
                len   = litlen_tbl[litlen - LITLEN_TBL_OFFSET].base_len;
                ebits = litlen_tbl[litlen - LITLEN_TBL_OFFSET].ebits;
                if (ebits != 0) {
                        len += lsb(bits, ebits);
                        bits >>= ebits;
                        used_tot += ebits;
                }
                assert(len >= MIN_LEN && len <= MAX_LEN);

                /* Get the distance. */
                distsym = huffman_decode(dist_dec, (uint16_t)bits, &used);
                bits >>= used;
                used_tot += used;

                if (distsym < 0 || distsym > DISTSYM_MAX) {
                        /* Failed to decode, or invalid symbol. */
                        return HWINF_ERR;
                }
                dist  = dist_tbl[distsym].base_dist;
                ebits = dist_tbl[distsym].ebits;
                if (ebits != 0) {
                        dist += lsb(bits, ebits);
                        bits >>= ebits;
                        used_tot += ebits;
                }
                assert(dist >= MIN_DISTANCE && dist <= MAX_DISTANCE);

                assert(used_tot <= ISTREAM_MIN_BITS);
                if (!istream_advance(is, used_tot)) {
                        return HWINF_ERR;
                }

                /* Bounds check and output the backref. */
                if (dist > *dst_pos) {
                        return HWINF_ERR;
                }
                if (round_up(len, 8) <= dst_cap - *dst_pos) {
                        output_backref64(dst, *dst_pos, dist, len);
                } else if (len <= dst_cap - *dst_pos) {
                        lz77_output_backref(dst, *dst_pos, dist, len);
                } else {
                        return HWINF_FULL;
                }
                (*dst_pos) += len;
        }
}

рдЗрд╕ рдЕрдиреБрдХреВрд▓рди рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ: рдЬрдм рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдмрдлрд░ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рдЬрдЧрд╣ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдЬрд╛рд░реА рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рдмрд╛рд░ рдореЗрдВ 64 рдмрд┐рдЯреНрд╕ рдХреЛ рдХреЙрдкреА рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЗрд╕ рдЕрд░реНрде рдореЗрдВ "рдЧрдбрд╝рдмрдбрд╝" рд╣реИ рдХрд┐ рдпрд╣ рдЕрдХреНрд╕рд░ рдХреБрдЫ рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд╛рдЗрдЯреНрд╕ (8 рдХреЗ рдЕрдЧрд▓реЗ рдХрдИ рддрдХ) рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рддреЗрдЬреА рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ lz77_output_backref, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрдо рдЪрдХреНрд░реАрдп рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдФрд░ рдореЗрдореЛрд░реА рдПрдХреНрд╕реЗрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЕрдм рдЫреЛрдЯреЗ рдмреИрдХрд▓рд┐рдВрдХреНрд╕ рдХреЛ рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдмреНрд░рд╛рдВрдЪрд┐рдВрдЧ рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред

/* Output the (dist,len) backref at dst_pos in dst using 64-bit wide writes.
   There must be enough room for len bytes rounded to the next multiple of 8. */
static void output_backref64(uint8_t *dst, size_t dst_pos, size_t dist,
                             size_t len)
{
        size_t i;
        uint64_t tmp;

        assert(len > 0);
        assert(dist <= dst_pos && "cannot reference before beginning of dst");

        if (len > dist) {
                /* Self-overlapping backref; fall back to byte-by-byte copy. */
                lz77_output_backref(dst, dst_pos, dist, len);
                return;
        }

        i = 0;
        do {
                memcpy(&tmp, &dst[dst_pos - dist + i], 8);
                memcpy(&dst[dst_pos + i], &tmp, 8);
                i += 8;
        } while (i < len);
}

рдбрд╛рдпрдиреЗрдорд┐рдХ рд╣рдлрд╝рдореИрди рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЦрдВрдбреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ


рдбрд╛рдпрдирд╛рдорд┐рдХ рд╣рдлрд╝рдореИрди рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЦрдВрдбреЛрдВ рдХреЛ рдЦрдВрдбрд┐рдд рдХрд░рдирд╛ рдЙрд╕реА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╣реИред рд▓реЗрдХрд┐рди litlen рдФрд░ dist рдХреЗ рд▓рд┐рдП рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреЛрдб рдХреЗ рдмрдЬрд╛рдп, рд╡реЗ рдмреНрд▓реЙрдХ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рд╣реА Deflate рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдирд╛рдо рд╢рд╛рдпрдж рдЕрд╕рдлрд▓ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЧрддрд┐рд╢реАрд▓ рд╣рдлрд╝рдореИрди рдХреЛрдб рдХреЛ рдХреЛрдбрд┐рдВрдЧ рднреА рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдХреЛрдбрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдмрджрд▓ рдЬрд╛рддреЗ рд╣реИрдВ - рдпрд╣ рдЕрдиреБрдХреВрд▓реА рд╣рдлрд╝рдореИрди рдХреЛрдбрд┐рдВрдЧ рд╣реИ ред рдпрд╣рд╛рдБ рд╡рд░реНрдгрд┐рдд рдХреЛрдб рдХрд╛ рдЙрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реЗ рдХреЛрдИ рд▓реЗрдирд╛-рджреЗрдирд╛ рдирд╣реАрдВ рд╣реИред рд╡реЗ рдХреЗрд╡рд▓ рдЗрд╕ рдЕрд░реНрде рдореЗрдВ рдЧрддрд┐рд╢реАрд▓ рд╣реИрдВ рдХрд┐ рд╡рд┐рднрд┐рдиреНрди рдмреНрд▓реЙрдХ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдбрд╛рдпрдиреЗрдорд┐рдХ рд▓рд┐рдЯреНрд▓рди рдФрд░ рдбрд┐рд╕реНрдЯ рдХреЛрдб рдХреЛ рдЬрдирд░реЗрдЯ рдХрд░рдирд╛ рдбрд┐рдлрд▓реЗрдЯ рдкреНрд░рд╛рд░реВрдк рдХрд╛ рд╕рдмрд╕реЗ рдХрдард┐рди рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЬреИрд╕реЗ рд╣реА рдХреЛрдб рдЙрддреНрдкрдиреНрди рд╣реЛрддреЗ рд╣реИрдВ, рд╡рд┐рдШрдЯрди рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреИрд╕реЗ рдкрд┐рдЫрд▓реЗ рднрд╛рдЧ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИ, рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП inf_block:

static inf_stat_t inf_dyn_block(istream_t *is, uint8_t *dst,
                                size_t dst_cap, size_t *dst_pos)
{
        inf_stat_t s;
        huffman_decoder_t litlen_dec, dist_dec;

        s = init_dyn_decoders(is, &litlen_dec, &dist_dec);
        if (s != HWINF_OK) {
                return s;
        }

        return inf_block(is, dst, dst_cap, dst_pos, &litlen_dec, &dist_dec);
}

рдбрд╛рдпрдиреЗрдорд┐рдХ рдбрд┐рд▓реЗрдЯ рдмреНрд▓реЙрдХ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЯрд▓рди рдФрд░ рдбрд┐рд╕реНрдЯ рдХреЛрдб рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рддреАрд╕рд░реЗ рд╣рдлрд╝рдореИрди рдХреЛрдб - рдХреЛрдбреЗрд▓рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рдВрдмрд╛рдИ рд╕реНрд╡рдпрдВ рдПрдиреНрдХреЛрдбреЗрдб рд╣реИ ред рдпрд╣ рдХреЛрдб рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреА рд▓рдВрдмрд╛рдИ ( codelen_lens) рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдмреНрд▓реЙрдХ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИрдВ (рдХреНрдпрд╛ рдореИрдВрдиреЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ)ред


рдбрд╛рдпрдирд╛рдорд┐рдХ рдмреНрд▓реЙрдХ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ 14 рдмрд┐рдЯреНрд╕ рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рд▓рд┐рдЯрд▓реЗрди рдХреА рд╕рдВрдЦреНрдпрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ-, рдбрд┐рд╕реНрдЯ- рдФрд░ рдХреЛрдбреЗрд▓-рд▓реЗрдВрдб рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреА рдЬрд┐рдиреНрд╣реЗрдВ рдмреНрд▓реЙрдХ рд╕реЗ рдкрдврд╝рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ:

#define MIN_CODELEN_LENS 4
#define MAX_CODELEN_LENS 19

#define MIN_LITLEN_LENS 257
#define MAX_LITLEN_LENS 288

#define MIN_DIST_LENS 1
#define MAX_DIST_LENS 32

#define CODELEN_MAX_LIT 15

#define CODELEN_COPY 16
#define CODELEN_COPY_MIN 3
#define CODELEN_COPY_MAX 6

#define CODELEN_ZEROS 17
#define CODELEN_ZEROS_MIN 3
#define CODELEN_ZEROS_MAX 10

#define CODELEN_ZEROS2 18
#define CODELEN_ZEROS2_MIN 11
#define CODELEN_ZEROS2_MAX 138

/* RFC 1951, 3.2.7 */
static const int codelen_lengths_order[MAX_CODELEN_LENS] =
{ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };

static inf_stat_t init_dyn_decoders(istream_t *is,
                                    huffman_decoder_t *litlen_dec,
                                    huffman_decoder_t *dist_dec)
{
        uint64_t bits;
        size_t num_litlen_lens, num_dist_lens, num_codelen_lens;
        uint8_t codelen_lengths[MAX_CODELEN_LENS];
        uint8_t code_lengths[MAX_LITLEN_LENS + MAX_DIST_LENS];
        size_t i, n, used;
        int sym;
        huffman_decoder_t codelen_dec;

        bits = istream_bits(is);

        /* Number of litlen codeword lengths (5 bits + 257). */
        num_litlen_lens = lsb(bits, 5) + MIN_LITLEN_LENS;
        bits >>= 5;
        assert(num_litlen_lens <= MAX_LITLEN_LENS);

        /* Number of dist codeword lengths (5 bits + 1). */
        num_dist_lens = lsb(bits, 5) + MIN_DIST_LENS;
        bits >>= 5;
        assert(num_dist_lens <= MAX_DIST_LENS);

        /* Number of code length lengths (4 bits + 4). */
        num_codelen_lens = lsb(bits, 4) + MIN_CODELEN_LENS;
        bits >>= 4;
        assert(num_codelen_lens <= MAX_CODELEN_LENS);

        if (!istream_advance(is, 5 + 5 + 4)) {
                return HWINF_ERR;
        }

рдлрд┐рд░ рдХреЛрдбреЗрд▓ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рдЖрддреА рд╣реИред рдпреЗ рд▓рдВрдмрд╛рдИ рд╕рд╛рдорд╛рдиреНрдп рддреАрди-рдмрд┐рдЯ рдорд╛рди рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╡рд┐рд╢реЗрд╖ рдХреНрд░рдо рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ codelen_lengths_orderред рдЪреВрдВрдХрд┐ 19 рд▓рдВрдмрд╛рдИ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдХреЗрд╡рд▓ рдзрд╛рд░рд╛ рд╕реЗ рдкрдврд╝рд╛ рдЬрд╛рдПрдЧрд╛ num_codelen_lens; рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрд╢рдХреНрдд рд╣реИред рд▓рдВрдмрд╛рдИ рдХреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдХреНрд░рдо рдореЗрдВ рд╕реВрдЪреАрдмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╢реВрдиреНрдп рд▓рдВрдмрд╛рдИ рд╕реВрдЪреА рдХреЗ рдЕрдВрдд рдореЗрдВ рдЧрд┐рд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реЛ рдФрд░ рдмреНрд▓реЙрдХ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рди рд╣реЛред

       /* Read the codelen codeword lengths (3 bits each)
           and initialize the codelen decoder. */
        for (i = 0; i < num_codelen_lens; i++) {
                bits = istream_bits(is);
                codelen_lengths[codelen_lengths_order[i]] =
                        (uint8_t)lsb(bits, 3);
                if (!istream_advance(is, 3)) {
                        return HWINF_ERR;
                }
        }
        for (; i < MAX_CODELEN_LENS; i++) {
                codelen_lengths[codelen_lengths_order[i]] = 0;
        }
        if (!huffman_decoder_init(&codelen_dec, codelen_lengths,
                                  MAX_CODELEN_LENS)) {
                return HWINF_ERR;
        }

рдХреЛрдбреЗрд▓рди рдбрд┐рдХреЛрдбрд░ рдХреЛ рд╕реЗрдЯ рдХрд░рдХреЗ, рд╣рдо рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреА рд▓рдВрдмрд╛рдИ рдХреЛ рд▓рд┐рдЯреНрд▓рди рдФрд░ рдзрд╛рд░рд╛ рд╕реЗ рджреВрд░ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред

       /* Read the litlen and dist codeword lengths. */
        i = 0;
        while (i < num_litlen_lens + num_dist_lens) {
                bits = istream_bits(is);
                sym = huffman_decode(&codelen_dec, (uint16_t)bits, &used);
                bits >>= used;
                if (!istream_advance(is, used)) {
                        return HWINF_ERR;
                }

                if (sym >= 0 && sym <= CODELEN_MAX_LIT) {
                        /* A literal codeword length. */
                        code_lengths[i++] = (uint8_t)sym;
                }

16, 17 рдФрд░ 18 рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд▓рдВрдмрд╛рдИ рдирд╣реАрдВ рд╣реИрдВ, рд╡реЗ рд╕рдВрдХреЗрддрдХ рд╣реИрдВ рдХрд┐ рдкрд┐рдЫрд▓реА рд▓рдВрдмрд╛рдИ рдХреЛ рдХрдИ рдмрд╛рд░ рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдпрд╛ рдЖрдкрдХреЛ рд╢реВрдиреНрдп рд▓рдВрдмрд╛рдИ рдХреЛ рджреЛрд╣рд░рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

               else if (sym == CODELEN_COPY) {
                        /* Copy the previous codeword length 3--6 times. */
                        if (i < 1) {
                                return HWINF_ERR; /* No previous length. */
                        }
                        n = lsb(bits, 2) + CODELEN_COPY_MIN; /* 2 bits + 3 */
                        if (!istream_advance(is, 2)) {
                                return HWINF_ERR;
                        }
                        assert(n >= CODELEN_COPY_MIN && n <= CODELEN_COPY_MAX);
                        if (i + n > num_litlen_lens + num_dist_lens) {
                                return HWINF_ERR;
                        }
                        while (n--) {
                                code_lengths[i] = code_lengths[i - 1];
                                i++;
                        }
                } else if (sym == CODELEN_ZEROS) {
                        /* 3--10 zeros. */
                        n = lsb(bits, 3) + CODELEN_ZEROS_MIN; /* 3 bits + 3 */
                        if (!istream_advance(is, 3)) {
                                return HWINF_ERR;
                        }
                        assert(n >= CODELEN_ZEROS_MIN &&
                               n <= CODELEN_ZEROS_MAX);
                        if (i + n > num_litlen_lens + num_dist_lens) {
                                return HWINF_ERR;
                        }
                        while (n--) {
                                code_lengths[i++] = 0;
                        }
                } else if (sym == CODELEN_ZEROS2) {
                        /* 11--138 zeros. */
                        n = lsb(bits, 7) + CODELEN_ZEROS2_MIN; /* 7 bits +138 */
                        if (!istream_advance(is, 7)) {
                                return HWINF_ERR;
                        }
                        assert(n >= CODELEN_ZEROS2_MIN &&
                               n <= CODELEN_ZEROS2_MAX);
                        if (i + n > num_litlen_lens + num_dist_lens) {
                                return HWINF_ERR;
                        }
                        while (n--) {
                                code_lengths[i++] = 0;
                        }
                } else {
                        /* Invalid symbol. */
                        return HWINF_ERR;
                }
        }

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд▓рд┐рдЯрд▓реЗрди рдФрд░ рдбрд┐рд╕реНрдЯ рд▓рдореНрдмрд╛рдИ рдХреЛ рдПрдХ-рдПрдХ рдХрд░рдХреЗ рд╕рд░рдгреА рдореЗрдВ рдкрдврд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ code_lengthsред рдЙрдиреНрд╣реЗрдВ рдЕрд▓рдЧ рд╕реЗ рдирд╣реАрдВ рдкрдврд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдб рдХреА рд▓рдВрдмрд╛рдИ рдХреЛ рдЕрдВрддрд┐рдо рд▓рд┐рдЯрд▓реЗрди рдХреА рд▓рдВрдмрд╛рдИ рд╕реЗ рдкрд╣рд▓реЗ рджреВрд░ рдХреА рд▓рдВрдмрд╛рдИ рддрдХ рд▓реЗ рдЬрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рд╣рдлрд╝рдореИрди рдбрд┐рдХреЛрдбрд░реНрд╕ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдбрд┐рдХреЛрдбрд┐рдВрдЧ рдХреЗ рдХрд╛рд░реНрдп рдкрд░ рд╡рд╛рдкрд╕ рд▓реМрдЯ рд╕рдХрддреЗ рд╣реИрдВ:

       if (!huffman_decoder_init(litlen_dec, &code_lengths[0],
                                  num_litlen_lens)) {
                return HWINF_ERR;
        }
        if (!huffman_decoder_init(dist_dec, &code_lengths[num_litlen_lens],
                                  num_dist_lens)) {
                return HWINF_ERR;
        }

        return HWINF_OK;
}

рд╕рдВрдкреАрдбрд╝рди (рдЕрдкрд╕реНрдлреАрддрд┐)


рдкрд┐рдЫрд▓реЗ рднрд╛рдЧреЛрдВ рдореЗрдВ, рд╣рдордиреЗ рдбреАрдлрд╝рд▓реНрдЯ рд╕рдВрдкреАрдбрд╝рди рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рднреА рдЙрдкрдХрд░рдг рдмрдирд╛рдП: рд▓реИрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡, рд╣рдлрд╝рдореИрди рдХреЛрдбрд┐рдВрдЧ, рдмрд┐рдЯ рд╕реНрдЯреНрд░реАрдо рдФрд░ рддреАрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреАрдлрд╝реНрд▓реИрдЯ рдмреНрд▓реЙрдХреЛрдВ рдХрд╛ рд╡рд┐рд╡рд░рдгред рдФрд░ рдЗрд╕ рднрд╛рдЧ рдореЗрдВ рд╣рдо рд╕рднреА рдХреЛ рдПрдХ рд╕рд╛рде рдорд┐рд▓рдХрд░ Deflate Compression рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗред

рд╕рдВрдкреАрдбрд╝рди рд▓реЗрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡ рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдХреЛ рдмреИрдХрд▓рд┐рдВрдХ рдФрд░ рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдореЗрдВ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдХреНрд░рдо рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдкрд┐рдЫрд▓реЗ рднрд╛рдЧ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ, рдбрд┐рдХреНрд▓реЗрдЯ рдмреНрд▓реЙрдХ рдореЗрдВ рдПрдиреНрдХреЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡рд┐рднрд╛рдЬрди рд╡рд┐рдзрд┐ рдХрд╛ рдЪрдпрди рдЕрдХреНрд╕рд░ рдЕрд╡рд░реБрджреНрдз рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ редред рдПрдХ рддрд░рдл, рдкреНрд░рддреНрдпреЗрдХ рдирдП рдмреНрд▓реЙрдХ рдХрд╛ рдорддрд▓рдм рдХрд┐рд╕реА рддрд░рд╣ рдХрд╛ рдУрд╡рд░рд╣реЗрдб рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреА рдорд╛рддреНрд░рд╛ рдмреНрд▓реЙрдХ рдФрд░ рдЙрд╕рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЗ рдкреНрд░рдХрд╛рд░ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИред рдХрдо рдмреНрд▓реЙрдХ - рдХрдо рдУрд╡рд░рд╣реЗрдбред рджреВрд╕рд░реА рдУрд░, рдПрдХ рдирдпрд╛ рдмреНрд▓реЙрдХ рдмрдирд╛рдиреЗ рдХреА рдпреЗ рд▓рд╛рдЧрдд рдЪреБрдХрд╛рдиреА рдкрдбрд╝ рд╕рдХрддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдбреЗрдЯрд╛ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рдЖрдкрдХреЛ рд╣рдлрд╝рдореИрди рдХреЛрдбрд┐рдВрдЧ рдХреЛ рдЕрдзрд┐рдХ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИрдВ рдФрд░ рдЙрддреНрдкрдиреНрди рдбреЗрдЯрд╛ рдХреА рдХреБрд▓ рдорд╛рддреНрд░рд╛ рдХреЛ рдХрдо рдХрд░рддреА рд╣реИрдВред

рдмреНрд▓реЙрдХ рдХрд░рдирд╛ рдПрдХ рдХрдард┐рди рдЕрдиреБрдХреВрд▓рди рдХрд╛рд░реНрдп рд╣реИред рдХреБрдЫ рдХрдВрдкреНрд░реЗрд╢рд░реНрд╕ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрд╝реЛрдлрд╝рд▓реА ) рджреВрд╕рд░реЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмреЗрд╣рддрд░ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬреНрдпрд╛рджрд╛рддрд░ рдмрд╕ рдПрдХ рд▓рд╛рд▓рдЪреА рджреГрд╖реНрдЯрд┐рдХреЛрдг рд▓реЗрддреЗ рд╣реИрдВ: рд╡реЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЖрдХрд╛рд░ рддрдХ рдкрд╣реБрдВрдЪрддреЗ рд╣реА рдмреНрд▓реЙрдХ рдЬрд╛рд░реА рдХрд░рддреЗ рд╣реИрдВред

рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдмреНрд▓реЙрдХреЛрдВ рдХреЗ рдЕрдкрдиреЗ рдЖрдХрд╛рд░ рдкреНрд░рддрд┐рдмрдВрдз рд╣реИрдВ:

  • рдЕрд╕рдореНрдмрджреНрдз рдмреНрд▓реЙрдХ рдореЗрдВ 65,535 рд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рдЗрдЯреНрд╕ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред
  • рд╣рдлрд╝рдореИрди рдирд┐рд╢реНрдЪрд┐рдд рдХреЛрдб рдХрд╛ рдЕрдзрд┐рдХрддрдо рдЖрдХрд╛рд░ рдирд╣реАрдВ рд╣реИред
  • рдбрд╛рдпрдиреЗрдорд┐рдХ рд╣рдлрд╝рдореИрди рдХреЛрдб рдореЗрдВ рдЖрдорддреМрд░ рдкрд░ рдЕрдзрд┐рдХрддрдо рдЖрдХрд╛рд░ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдлрд╝рдореИрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ 16-рдмрд┐рдЯ рд╡рд░реНрдг рдХреНрд░рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реЛрддрд╛ рд╣реИ, рд╣рдо 65,535 рд╡рд░реНрдгреЛрдВ рддрдХ рд╕реАрдорд┐рдд рд╣реИрдВред

рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдмреНрд▓реЙрдХ рдХрд╛ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдирдХреЗ рдЖрдХрд╛рд░ рдХреЛ 65,534 рдмрд╛рдЗрдЯреНрд╕ рддрдХ рд╕реАрдорд┐рдд рдХрд░реЗрдВ:

/* The largest number of bytes that will fit in any kind of block is 65,534.
   It will fit in an uncompressed block (max 65,535 bytes) and a Huffman
   block with only literals (65,535 symbols including end-of-block marker). */
#define MAX_BLOCK_LEN_BYTES 65534

рд╕рдВрдкреАрдбрд╝рди рдХреЗ рджреМрд░рд╛рди рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рдФрд░ рд╡рд░реНрддрдорд╛рди рдмреНрд▓реЙрдХ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:

typedef struct deflate_state_t deflate_state_t;
struct deflate_state_t {
        ostream_t os;

        const uint8_t *block_src; /* First src byte in the block. */

        size_t block_len;       /* Number of symbols in the current block. */
        size_t block_len_bytes; /* Number of src bytes in the block. */

        /* Symbol frequencies for the current block. */
        uint16_t litlen_freqs[LITLEN_MAX + 1];
        uint16_t dist_freqs[DISTSYM_MAX + 1];

        struct {
                uint16_t distance;    /* Backref distance. */
                union {
                        uint16_t lit; /* Literal byte or end-of-block. */
                        uint16_t len; /* Backref length (distance != 0). */
                } u;
        } block[MAX_BLOCK_LEN_BYTES + 1];
};

static void reset_block(deflate_state_t *s)
{
        s->block_len = 0;
        s->block_len_bytes = 0;
        memset(s->litlen_freqs, 0, sizeof(s->litlen_freqs));
        memset(s->dist_freqs, 0, sizeof(s->dist_freqs));
}

рдХрд╛рд░реНрдп рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдмреНрд▓реЙрдХ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, lz77_compressрд╣рдо рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЕрдзрд┐рдХрддрдо рдЖрдХрд╛рд░ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдкрд░, рд╣рдо рдмреНрд▓реЙрдХ рдХреЛ рдмрд┐рдЯрд╕реНрдЯреНрд░реАрдо рдкрд░ рд▓рд┐рдЦреЗрдВрдЧреЗ:

static bool lit_callback(uint8_t lit, void *aux)
{
        deflate_state_t *s = aux;

        if (s->block_len_bytes + 1 > MAX_BLOCK_LEN_BYTES) {
                if (!write_block(s, false)) {
                        return false;
                }
                s->block_src += s->block_len_bytes;
                reset_block(s);
        }

        assert(s->block_len < sizeof(s->block) / sizeof(s->block[0]));
        s->block[s->block_len  ].distance = 0;
        s->block[s->block_len++].u.lit = lit;
        s->block_len_bytes++;

        s->litlen_freqs[lit]++;

        return true;
}

static bool backref_callback(size_t dist, size_t len, void *aux)
{
        deflate_state_t *s = aux;

        if (s->block_len_bytes + len > MAX_BLOCK_LEN_BYTES) {
                if (!write_block(s, false)) {
                        return false;
                }
                s->block_src += s->block_len_bytes;
                reset_block(s);
        }

        assert(s->block_len < sizeof(s->block) / sizeof(s->block[0]));
        s->block[s->block_len  ].distance = (uint16_t)dist;
        s->block[s->block_len++].u.len = (uint16_t)len;
        s->block_len_bytes += len;

        assert(len >= MIN_LEN && len <= MAX_LEN);
        assert(dist >= MIN_DISTANCE && dist <= MAX_DISTANCE);
        s->litlen_freqs[len2litlen[len]]++;
        s->dist_freqs[distance2dist[dist]]++;

        return true;
}

рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдмреНрд▓реЙрдХреЛрдВ рдХреА рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рд╣реИред рдпрджрд┐ рдмреНрд▓реЙрдХ рд╕рдВрдХреБрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ, рддреЛ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ:

static bool write_uncomp_block(deflate_state_t *s, bool final)
{
        uint8_t len_nlen[4];

        /* Write the block header. */
        if (!ostream_write(&s->os, (0x0 << 1) | final, 3)) {
                return false;
        }

        len_nlen[0] = (uint8_t)(s->block_len_bytes >> 0);
        len_nlen[1] = (uint8_t)(s->block_len_bytes >> 8);
        len_nlen[2] = ~len_nlen[0];
        len_nlen[3] = ~len_nlen[1];

        if (!ostream_write_bytes_aligned(&s->os, len_nlen, sizeof(len_nlen))) {
                return false;
        }

        if (!ostream_write_bytes_aligned(&s->os, s->block_src,
                                         s->block_len_bytes)) {
                return false;
        }

        return true;
}

рдПрдХ рд╕реНрдерд┐рд░ рд╣рдлрд╝рдореИрди рдмреНрд▓реЙрдХ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд╣рд▓реЗ рд▓рд┐рдЯрд▓рди рдФрд░ рдбрд┐рд╕реНрдЯ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рд╣рд┐рдд рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВред рдлрд┐рд░ рд╣рдо рдЗрди рдХреЛрдбреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╡рд░реНрдгреЛрдВ рдХреЛ рд▓рд┐рдЦрддреЗ рд╣реБрдП рдмреНрд▓реЙрдХ рдХреЛ рдкреБрди: рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╣реИрдВ:

static bool write_static_block(deflate_state_t *s, bool final)
{
        huffman_encoder_t litlen_enc, dist_enc;

        /* Write the block header. */
        if (!ostream_write(&s->os, (0x1 << 1) | final, 3)) {
                return false;
        }

        huffman_encoder_init2(&litlen_enc, fixed_litlen_lengths,
                              sizeof(fixed_litlen_lengths) /
                              sizeof(fixed_litlen_lengths[0]));
        huffman_encoder_init2(&dist_enc, fixed_dist_lengths,
                              sizeof(fixed_dist_lengths) /
                              sizeof(fixed_dist_lengths[0]));

        return write_huffman_block(s, &litlen_enc, &dist_enc);
}

static bool write_huffman_block(deflate_state_t *s,
                                const huffman_encoder_t *litlen_enc,
                                const huffman_encoder_t *dist_enc)
{
        size_t i, nbits;
        uint64_t distance, dist, len, litlen, bits, ebits;

        for (i = 0; i < s->block_len; i++) {
                if (s->block[i].distance == 0) {
                        /* Literal or EOB. */
                        litlen = s->block[i].u.lit;
                        assert(litlen <= LITLEN_EOB);
                        if (!ostream_write(&s->os,
                                           litlen_enc->codewords[litlen],
                                           litlen_enc->lengths[litlen])) {
                                return false;
                        }
                        continue;
                }

                /* Back reference length. */
                len = s->block[i].u.len;
                litlen = len2litlen[len];

                /* litlen bits */
                bits = litlen_enc->codewords[litlen];
                nbits = litlen_enc->lengths[litlen];

                /* ebits */
                ebits = len - litlen_tbl[litlen - LITLEN_TBL_OFFSET].base_len;
                bits |= ebits << nbits;
                nbits += litlen_tbl[litlen - LITLEN_TBL_OFFSET].ebits;

                /* Back reference distance. */
                distance = s->block[i].distance;
                dist = distance2dist[distance];

                /* dist bits */
                bits |= (uint64_t)dist_enc->codewords[dist] << nbits;
                nbits += dist_enc->lengths[dist];

                /* ebits */
                ebits = distance - dist_tbl[dist].base_dist;
                bits |= ebits << nbits;
                nbits += dist_tbl[dist].ebits;

                if (!ostream_write(&s->os, bits, nbits)) {
                        return false;
                }
        }

        return true;
}

рдмреЗрд╢рдХ, рд╣рдлрд╝рдореИрди рдбрд╛рдпрдиреЗрдорд┐рдХ рдмреНрд▓реЙрдХ рд▓рд┐рдЦрдирд╛ рдХрдард┐рди рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрдирдореЗрдВ рд▓рд┐рдЯреНрд▓реАрди рдФрд░ рдбрд┐рд╕реНрдЯ рдХреЛрдб рдХреЗ рдЯреНрд░рд┐рдХреА рдХреЛрдбрд┐рдВрдЧ рд╣реЛрддреЗ рд╣реИрдВред рдЗрд╕ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:

typedef struct codelen_sym_t codelen_sym_t;
struct codelen_sym_t {
        uint8_t sym;
        uint8_t count; /* For symbols 16, 17, 18. */
};

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд▓рд┐рдЯрд▓реЗрди рдФрд░ рдбрд┐рд╕реНрдЯрд░реНрдб рдХреЛрдбрд╡рд░реНрдб рдХреА рдЙрдирдХреА рд╢реВрдиреНрдп рд▓рдВрдмрд╛рдИ рдХреА рдкреВрдВрдЫ рдХреЛ рд╣рдЯрд╛ рджреЗрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдмрд╛рдж рдХреЗ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рдпрдорд┐рдд рд╕рд░рдгреА рдореЗрдВ рдХреЙрдкреА рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рд╕рднреА рд╢реВрдиреНрдп рдХреЛ рдирд╣реАрдВ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ: рдпрджрд┐ рдПрдХ рднреА рдбрд┐рд╕реНрдЯ рдХреЛрдб рдирд╣реАрдВ рд╣реИ рддреЛ рдбрд┐рдлрд▓реЗрдЯ рдмреНрд▓реЙрдХ рдХреЛ рдПрдирдХреЛрдб рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИред 257 рд╕реЗ рдХрдо рд▓рд┐рдЯрд▓реЗрди рдХреЛрдб рд╣реЛрдирд╛ рднреА рдЕрд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдореЗрд╢рд╛ рдмрд╛рдЗрдЯ рдПрдВрдбрд┐рдВрдЧ рдорд╛рд░реНрдХрд░ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП 256 рдХреЗ рд╡рд░реНрдг рдХреЗ рд▓рд┐рдП рд╣рдореЗрд╢рд╛ рдПрдХ рдЧреИрд░-рд╢реВрдиреНрдп рдХреЛрдб рд▓рдВрдмрд╛рдИ рд╣реЛрдЧреАред

/* Encode litlen_lens and dist_lens into encoded. *num_litlen_lens and
   *num_dist_lens will be set to the number of encoded litlen and dist lens,
   respectively. Returns the number of elements in encoded. */
static size_t encode_dist_litlen_lens(const uint8_t *litlen_lens,
                                      const uint8_t *dist_lens,
                                      codelen_sym_t *encoded,
                                      size_t *num_litlen_lens,
                                      size_t *num_dist_lens)
{
        size_t i, n;
        uint8_t lens[LITLEN_MAX + 1 + DISTSYM_MAX + 1];

        *num_litlen_lens = LITLEN_MAX + 1;
        *num_dist_lens = DISTSYM_MAX + 1;

        /* Drop trailing zero litlen lengths. */
        assert(litlen_lens[LITLEN_EOB] != 0 && "EOB len should be non-zero.");
        while (litlen_lens[*num_litlen_lens - 1] == 0) {
                (*num_litlen_lens)--;
        }
        assert(*num_litlen_lens >= MIN_LITLEN_LENS);

        /* Drop trailing zero dist lengths, keeping at least one. */
        while (dist_lens[*num_dist_lens - 1] == 0 && *num_dist_lens > 1) {
                (*num_dist_lens)--;
        }
        assert(*num_dist_lens >= MIN_DIST_LENS);

        /* Copy the lengths into a unified array. */
        n = 0;
        for (i = 0; i < *num_litlen_lens; i++) {
                lens[n++] = litlen_lens[i];
        }
        for (i = 0; i < *num_dist_lens; i++) {
                lens[n++] = dist_lens[i];
        }

        return encode_lens(lens, n, encoded);
}

рдПрдХ рд╕рд░рдгреА рдореЗрдВ рдХреЛрдб рд▓рдВрдмрд╛рдИ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рд╕рдорд╛рди рдХреЛрдб рд▓рдВрдмрд╛рдИ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд╡рд░реНрдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЛрдбрд┐рдВрдЧ рдХрд░рддреЗ рд╣реИрдВред

/* Encode the n code lengths in lens into encoded, returning the number of
   elements in encoded. */
static size_t encode_lens(const uint8_t *lens, size_t n, codelen_sym_t *encoded)
{
        size_t i, j, num_encoded;
        uint8_t count;

        i = 0;
        num_encoded = 0;
        while (i < n) {
                if (lens[i] == 0) {
                        /* Scan past the end of this zero run (max 138). */
                        for (j = i; j < min(n, i + CODELEN_ZEROS2_MAX) &&
                                    lens[j] == 0; j++);
                        count = (uint8_t)(j - i);

                        if (count < CODELEN_ZEROS_MIN) {
                                /* Output a single zero. */
                                encoded[num_encoded++].sym = 0;
                                i++;
                                continue;
                        }

                        /* Output a repeated zero. */
                        if (count <= CODELEN_ZEROS_MAX) {
                                /* Repeated zero 3--10 times. */
                                assert(count >= CODELEN_ZEROS_MIN &&
                                       count <= CODELEN_ZEROS_MAX);
                                encoded[num_encoded].sym = CODELEN_ZEROS;
                                encoded[num_encoded++].count = count;
                        } else {
                                /* Repeated zero 11--138 times. */
                                assert(count >= CODELEN_ZEROS2_MIN &&
                                       count <= CODELEN_ZEROS2_MAX);
                                encoded[num_encoded].sym = CODELEN_ZEROS2;
                                encoded[num_encoded++].count = count;
                        }
                        i = j;
                        continue;
                }

                /* Output len. */
                encoded[num_encoded++].sym = lens[i++];

                /* Scan past the end of the run of this len (max 6). */
                for (j = i; j < min(n, i + CODELEN_COPY_MAX) &&
                            lens[j] == lens[i - 1]; j++);
                count = (uint8_t)(j - i);

                if (count >= CODELEN_COPY_MIN) {
                        /* Repeat last len 3--6 times. */
                        assert(count >= CODELEN_COPY_MIN &&
                               count <= CODELEN_COPY_MAX);
                        encoded[num_encoded].sym = CODELEN_COPY;
                        encoded[num_encoded++].count = count;
                        i = j;
                        continue;
                }
        }

        return num_encoded;
}

рдХреЛрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╡рд░реНрдгреЛрдВ рдХреЛ рд╣рдлрд╝рдореИрди рдХреЛрдб - рдХреЛрдбрд▓реЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдХреЛрдбреЗрд▓рди рдХреЛрдб рд╕реЗ рдХреЛрдбрд╡рд░реНрдб рдХреА рд▓рдВрдмрд╛рдИ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреНрд░рдо рдореЗрдВ рдмреНрд▓реЙрдХ рдХреЛ рд▓рд┐рдЦреА рдЬрд╛рддреА рд╣реИ рддрд╛рдХрд┐ рд╢реВрдиреНрдп рд▓рдВрдмрд╛рдИ рдЕрдВрдд рдореЗрдВ рд╕рдорд╛рдкреНрдд рд╣реЛрдиреЗ рдХреА рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реЛред рдпрд╣рд╛рдБ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рддрдиреА рд▓рдВрдмрд╛рдИ рд▓рд┐рдЦреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП:

static const int codelen_lengths_order[19] =
{ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };

/* Count the number of significant (not trailing zeros) codelen lengths. */
size_t count_codelen_lens(const uint8_t *codelen_lens)
{
        size_t n = MAX_CODELEN_LENS;

        /* Drop trailing zero lengths. */
        while (codelen_lens[codelen_lengths_order[n - 1]] == 0) {
                n--;
        }

        /* The first 4 lengths in the order (16, 17, 18, 0) cannot be used to
           encode any non-zero lengths. Since there will always be at least
           one non-zero codeword length (for EOB), n will be >= 4. */
        assert(n >= MIN_CODELEN_LENS && n <= MAX_CODELEN_LENS);

        return n;
}

рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рд▓рд┐рдЯрд▓рди рдФрд░ рдбрд┐рд╕реНрдЯ рдХреЛрдб рд╕реЗрдЯ рдХрд░ рджрд┐рдП рд╣реИрдВ, рдЙрдирдХреЗ рдХреЛрдб рд╢рдмреНрджреЛрдВ рдХреА рд▓рдВрдмрд╛рдИ рдФрд░ рдЗрди рд▓рдВрдмрд╛рдИ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЛрдб рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рд╕реЗрдЯ рдХрд░реЗрдВред рдЕрдм рд╣рдо рдПрдХ рдЧрддрд┐рд╢реАрд▓ рд╣рдлрд╝рдореИрди рдмреНрд▓реЙрдХ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:

static bool write_dynamic_block(deflate_state_t *s, bool final,
                                size_t num_litlen_lens, size_t num_dist_lens,
                                size_t num_codelen_lens,
                                const huffman_encoder_t *codelen_enc,
                                const codelen_sym_t *encoded_lens,
                                size_t num_encoded_lens,
                                const huffman_encoder_t *litlen_enc,
                                const huffman_encoder_t *dist_enc)
{
        size_t i;
        uint8_t codelen, sym;
        size_t nbits;
        uint64_t bits, hlit, hdist, hclen, count;

        /* Block header. */
        bits = (0x2 << 1) | final;
        nbits = 3;

        /* hlit (5 bits) */
        hlit = num_litlen_lens - MIN_LITLEN_LENS;
        bits |= hlit << nbits;
        nbits += 5;

        /* hdist (5 bits) */
        hdist = num_dist_lens - MIN_DIST_LENS;
        bits |= hdist << nbits;
        nbits += 5;

        /* hclen (4 bits) */
        hclen = num_codelen_lens - MIN_CODELEN_LENS;
        bits |= hclen << nbits;
        nbits += 4;

        if (!ostream_write(&s->os, bits, nbits)) {
                return false;
        }

        /* Codelen lengths. */
        for (i = 0; i < num_codelen_lens; i++) {
                codelen = codelen_enc->lengths[codelen_lengths_order[i]];
                if (!ostream_write(&s->os, codelen, 3)) {
                        return false;
                }
        }

        /* Litlen and dist code lengths. */
        for (i = 0; i < num_encoded_lens; i++) {
                sym = encoded_lens[i].sym;

                bits = codelen_enc->codewords[sym];
                nbits = codelen_enc->lengths[sym];

                count = encoded_lens[i].count;
                if (sym == CODELEN_COPY) { /* 2 ebits */
                        bits |= (count - CODELEN_COPY_MIN) << nbits;
                        nbits += 2;
                } else if (sym == CODELEN_ZEROS) { /* 3 ebits */
                        bits |= (count - CODELEN_ZEROS_MIN) << nbits;
                        nbits += 3;
                } else if (sym == CODELEN_ZEROS2) { /* 7 ebits */
                        bits |= (count - CODELEN_ZEROS2_MIN) << nbits;
                        nbits += 7;
                }

                if (!ostream_write(&s->os, bits, nbits)) {
                        return false;
                }
        }

        return write_huffman_block(s, litlen_enc, dist_enc);
}

рдкреНрд░рддреНрдпреЗрдХ рдмреНрд▓реЙрдХ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдХрдо рд╕реЗ рдХрдо рдмрд┐рдЯреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдПрдХ рдЕрд╕рдореНрдкреАрдбрд┐рдд рдмреНрд▓реЙрдХ рдХреА рд▓рдВрдмрд╛рдИ рдХреА рдЧрдгрдирд╛ рдЬрд▓реНрджреА рд╕реЗ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ:

/* Calculate the number of bits for an uncompressed block, including header. */
static size_t uncomp_block_len(const deflate_state_t *s)
{
        size_t bit_pos, padding;

        /* Bit position after writing the block header. */
        bit_pos = ostream_bit_pos(&s->os) + 3;
        padding = round_up(bit_pos, 8) - bit_pos;

        /* Header + padding + len/nlen + block contents. */
        return 3 + padding + 2 * 16 + s->block_len_bytes * 8;
}

рд╣рдлрд╝рдореИрди рдПрдиреНрдХреЛрдбреЗрдб рдмреНрд▓реЙрдХреНрд╕ рдХреЗ рд▓рд┐рдП, рдЖрдк рд▓рд┐рдЯрд▓реЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╢рд░реАрд░ рдХреА рд▓рдВрдмрд╛рдИ рдХреА рдЧрдгрдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ- рдФрд░ рд╡рд░реНрдг рдФрд░ рдХреЛрдбрд╡рд░реНрдб рд▓рдВрдмрд╛рдИ рдХреА рдлрд╝реНрд░реАрдХреНрд╡реЗрдВрд╕реА:

/* Calculate the number of bits for a Huffman encoded block body. */
static size_t huffman_block_body_len(const deflate_state_t *s,
                                     const uint8_t *litlen_lens,
                                     const uint8_t *dist_lens)
{
        size_t i, freq, len;

        len = 0;

        for (i = 0; i <= LITLEN_MAX; i++) {
                freq = s->litlen_freqs[i];
                len += litlen_lens[i] * freq;

                if (i >= LITLEN_TBL_OFFSET) {
                        len += litlen_tbl[i - LITLEN_TBL_OFFSET].ebits * freq;
                }
        }

        for (i = 0; i <= DISTSYM_MAX; i++) {
                freq = s->dist_freqs[i];
                len += dist_lens[i] * freq;
                len += dist_tbl[i].ebits * freq;
        }

        return len;
}

рд╕реНрдереИрддрд┐рдХ рдмреНрд▓реЙрдХ рдХреА рдХреБрд▓ рд▓рдВрдмрд╛рдИ рд╣реЗрдбрд░ рдХреЗ 3 рдмрд┐рдЯреНрд╕ рдФрд░ рд╢рд░реАрд░ рдХреА рд▓рдВрдмрд╛рдИ рд╣реИред рдбрд╛рдпрдирд╛рдорд┐рдХ рдмреНрд▓реЙрдХ рдХреЗ рд╣реЗрдбрд░ рдЖрдХрд╛рд░ рдХреА рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХрд╛рдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ:

/* Calculate the number of bits for a dynamic Huffman block. */
static size_t dyn_block_len(const deflate_state_t *s, size_t num_codelen_lens,
                            const uint16_t *codelen_freqs,
                            const huffman_encoder_t *codelen_enc,
                            const huffman_encoder_t *litlen_enc,
                            const huffman_encoder_t *dist_enc)
{
        size_t len, i, freq;

        /* Block header. */
        len = 3;

        /* Nbr of litlen, dist, and codelen lengths. */
        len += 5 + 5 + 4;

        /* Codelen lengths. */
        len += 3 * num_codelen_lens;

        /* Codelen encoding. */
        for (i = 0; i < MAX_CODELEN_LENS; i++) {
                freq = codelen_freqs[i];
                len += codelen_enc->lengths[i] * freq;

                /* Extra bits. */
                if (i == CODELEN_COPY) {
                        len += 2 * freq;
                } else if (i == CODELEN_ZEROS) {
                        len += 3 * freq;
                } else if (i == CODELEN_ZEROS2) {
                        len += 7 * freq;
                }
        }

        return len + huffman_block_body_len(s, litlen_enc->lengths,
                                            dist_enc->lengths);
}

рдЕрдм рд╣рдо рд╕рдм рдХреБрдЫ рдПрдХ рд╕рд╛рде рд░рдЦреЗрдВрдЧреЗ рдФрд░ рдмреНрд▓реЙрдХ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдмрдирд╛рдПрдВрдЧреЗ:

/* Write the current deflate block, marking it final if that parameter is true,
   returning false if there is not enough room in the output stream. */
static bool write_block(deflate_state_t *s, bool final)
{
        size_t old_bit_pos, uncomp_len, static_len, dynamic_len;
        huffman_encoder_t dyn_litlen_enc, dyn_dist_enc, codelen_enc;
        size_t num_encoded_lens, num_litlen_lens, num_dist_lens;
        codelen_sym_t encoded_lens[LITLEN_MAX + 1 + DISTSYM_MAX + 1];
        uint16_t codelen_freqs[MAX_CODELEN_LENS] = {0};
        size_t num_codelen_lens;
        size_t i;

        old_bit_pos = ostream_bit_pos(&s->os);

        /* Add the end-of-block marker in case we write a Huffman block. */
        assert(s->block_len < sizeof(s->block) / sizeof(s->block[0]));
        assert(s->litlen_freqs[LITLEN_EOB] == 0);
        s->block[s->block_len  ].distance = 0;
        s->block[s->block_len++].u.lit = LITLEN_EOB;
        s->litlen_freqs[LITLEN_EOB] = 1;

        uncomp_len = uncomp_block_len(s);

        static_len = 3 + huffman_block_body_len(s, fixed_litlen_lengths,
                                                fixed_dist_lengths);

        /* Compute "dynamic" Huffman codes. */
        huffman_encoder_init(&dyn_litlen_enc, s->litlen_freqs,
                             LITLEN_MAX + 1, 15);
        huffman_encoder_init(&dyn_dist_enc, s->dist_freqs, DISTSYM_MAX + 1, 15);

        /* Encode the litlen and dist code lengths. */
        num_encoded_lens = encode_dist_litlen_lens(dyn_litlen_enc.lengths,
                                                   dyn_dist_enc.lengths,
                                                   encoded_lens,
                                                   &num_litlen_lens,
                                                   &num_dist_lens);

        /* Compute the codelen code. */
        for (i = 0; i < num_encoded_lens; i++) {
                codelen_freqs[encoded_lens[i].sym]++;
        }
        huffman_encoder_init(&codelen_enc, codelen_freqs, MAX_CODELEN_LENS, 7);
        num_codelen_lens = count_codelen_lens(codelen_enc.lengths);

        dynamic_len = dyn_block_len(s, num_codelen_lens, codelen_freqs,
                                    &codelen_enc, &dyn_litlen_enc,
                                    &dyn_dist_enc);

        if (uncomp_len <= dynamic_len && uncomp_len <= static_len) {
                if (!write_uncomp_block(s, final)) {
                        return false;
                }
                assert(ostream_bit_pos(&s->os) - old_bit_pos == uncomp_len);
        } else if (static_len <= dynamic_len) {
                if (!write_static_block(s, final)) {
                        return false;
                }
                assert(ostream_bit_pos(&s->os) - old_bit_pos == static_len);
        } else {
                if (!write_dynamic_block(s, final, num_litlen_lens,
                                         num_dist_lens, num_codelen_lens,
                                         &codelen_enc, encoded_lens,
                                         num_encoded_lens, &dyn_litlen_enc,
                                         &dyn_dist_enc)) {
                        return false;
                }
                assert(ostream_bit_pos(&s->os) - old_bit_pos == dynamic_len);
        }

        return true;
}

рдЕрдВрдд рдореЗрдВ, рд╕рдВрдкреВрд░реНрдг рд╕рдВрдкреАрдбрд╝рди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдЖрд░рдВрднрдХрд░реНрддрд╛ рдХреЛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП, рд▓реЗрдореНрдкреЗрд▓-рдЬрд╝рд┐рд╡ рд╕рдВрдкреАрдбрд╝рди рд╢реБрд░реВ рдХрд░реЗрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдореА рдмреНрд▓реЙрдХ рд▓рд┐рдЦреЗрдВ:

/* Compress (deflate) the data in src into dst. The number of bytes output, at
   most dst_cap, is stored in *dst_used. Returns false if there is not enough
   room in dst. src and dst must not overlap. */
bool hwdeflate(const uint8_t *src, size_t src_len, uint8_t *dst,
               size_t dst_cap, size_t *dst_used)
{
        deflate_state_t s;

        ostream_init(&s.os, dst, dst_cap);
        reset_block(&s);
        s.block_src = src;

        if (!lz77_compress(src, src_len, &lit_callback,
                           &backref_callback, &s)) {
                return false;
        }

        if (!write_block(&s, true)) {
                return false;
        }

        /* The end of the final block should match the end of src. */
        assert(s.block_src + s.block_len_bytes == src + src_len);

        *dst_used = ostream_bytes_written(&s.os);

        return true;
}

рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рд╕реНрд╡рд░реВрдк


рдКрдкрд░, рд╣рдордиреЗ рдЬрд╛рдВрдЪ рдХреА рдХрд┐ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдбреАрдлрд╝реНрд▓реИрдЯ рд╕рдВрдкреАрдбрд╝рди рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдХреНрдпрд╛ рдлрд╝рд╛рдЗрд▓ рд╕реНрд╡рд░реВрдк рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реА? рдЗрд╕ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рдЗрд╕рдХреА рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдЬрд╛рдБрдЪ рдХрд░реЗрдВрдЧреЗред рдХреЛрдб zip.h рдФрд░ zip.c рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ ред

рдЕрд╡рд▓реЛрдХрди


рдлрд╝рд╛рдЗрд▓ рдкреНрд░рд╛рд░реВрдк PKZip рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдиреЛрдЯ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИ :

  1. рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рд╛рдЗрд▓, рдпрд╛ рд╕рдВрдЧреНрд░рд╣ рдЖрдЗрдЯрдо, рдЖрдЗрдЯрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдерд╛рдиреАрдп рдлрд╝рд╛рдЗрд▓ рд╣реЗрдбрд░ рд╣реИ ред
  2. . , , , Zip-.
  3. , . , . Zip-.


рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдЧреНрд░рд╣ рдЖрдЗрдЯрдо рдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рднрд▓реЗ рд╣реА рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдмреАрдЪ рдореИрдЪ рд╣реЛрдВ, рдЙрдиреНрд╣реЗрдВ рд╕рдВрдкреАрдбрд╝рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзреНрдпрд╛рди рдирд╣реАрдВ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдЕрдВрдд рдореЗрдВ рдХреЗрдВрджреНрд░реАрдп рдХреИрдЯрд▓реЙрдЧ рдХрд╛ рд╕реНрдерд╛рди рдЖрдкрдХреЛ рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдзреАрд░реЗ-рдзреАрд░реЗ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЬреИрд╕реЗ рд╣реА рдлрд╝рд╛рдЗрд▓ рддрддреНрд╡ рд╕рдВрдкреАрдбрд╝рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕реВрдЪрдХрд╛рдВрдХ рд╕рднреА рд╕рдВрдкреАрдбрд╝рд┐рдд рдЖрдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рдж рджрд░реНрдЬ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ рд╕рднреА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдСрдлрд╕реЗрдЯ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдореМрдЬреВрджрд╛ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдХрд╛рдлреА рдЖрд╕рд╛рди рд╣реИ, рдЗрд╕реЗ рдЕрдВрддрд┐рдо рддрддреНрд╡ рдХреЗ рдмрд╛рдж рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдзреАрд░реЗ-рдзреАрд░реЗ рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ рдмрдирд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХрдИ рдлреНрд▓реЙрдкреА рдбрд┐рд╕реНрдХ рдпрд╛ рд╡реЙрд▓реНрдпреВрдо рдкрд░ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рдкреНрд░рд╕рд╛рд░ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рдереАред рдЬреИрд╕реЗ рд╣реА рдпрд╣ рд╕рдВрдХреБрдЪрд┐рдд рд╣реБрдЖ, PKZip рдиреЗ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирдП рдбрд┐рд╕реНрдХреЗрдЯ рдбрд╛рд▓реЗрдВ, рдФрд░ рдЕрдВрддрд┐рдо (рдЕрдВрддрд┐рдо) рд╡рд╛рд▓реЛрдВ рдХреЛ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд▓рд┐рдЦреЗрдВред рдорд▓реНрдЯреА-рд╡реЙрд▓реНрдпреВрдо рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдЕрдирдЬрд╝рд┐рдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреАрдХреЗрдЬрд╝рд┐рдк рдиреЗ рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдЦрд┐рд░реА рдбрд┐рд╕реНрдХреЗрдЯ рдХреЛ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛, рдФрд░ рдлрд┐рд░ рдмрд╛рдХреА рдбрд┐рд╕реНрдХреЗрдЯ рдХреЛ рдЕрдиреБрд░реЛрдзрд┐рдд рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдерд╛ред

рдпрд╣ рдЖрдкрдХреЛ рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдПрдХ рд╣реА рдирд╛рдо рдХреЗ рд╕рд╛рде рдХрдИ рдлрд╛рдЗрд▓реЗрдВ рд░рдЦрдиреЗ рдкрд░ рдХреЛрдИ рдирд┐рдпрдо рдирд╣реАрдВ рдерд╛ред рдпрд╣ рдЕрдирдкреИрдХ рдХрд░рддреЗ рд╕рдордп рдмрд╣реБрдд рднреНрд░рдо рдкреИрджрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ: рдпрджрд┐ рдПрдХ рд╣реА рдирд╛рдо рд╡рд╛рд▓реА рдХрдИ рдлрд╛рдЗрд▓реЗрдВ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдХреМрди рд╕рд╛ рдЕрдирдкреИрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП? рдмрджрд▓реЗ рдореЗрдВ, рдпрд╣ рд╕реБрд░рдХреНрд╖рд╛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдЬрдиреНрдо рджреЗ рд╕рдХрддрд╛ рд╣реИред Android рдореЗрдВ "рдорд╛рд╕реНрдЯрд░ рдХреБрдВрдЬреА" рдмрдЧ рдХреЗ рдХрд╛рд░рдг (CVE-2013-4787 , рдмреНрд▓реИрдХ рд╣реИрдЯ рдкрд░ рд░рд┐рдкреЛрд░реНрдЯ рд╕реЗ рд╕реНрд▓рд╛рдЗрдб рдФрд░ рд╡реАрдбрд┐рдпреЛ ) рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╕рдордп рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рдЪреЗрдХ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдПрдВрдбреНрд░реЙрдЗрдб рдкреНрд░реЛрдЧреНрд░рд╛рдо рдПрдкреАрдХреЗ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ , рдЬреЛ рдЬрд╝рд┐рдк рдлрд╛рдЗрд▓реЗрдВ рд╣реИрдВред рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛, рдЕрдЧрд░ рдПрдкреАрдХреЗ рдореЗрдВ рдПрдХ рд╣реА рдирд╛рдо рд╡рд╛рд▓реА рдХрдИ рдлрд╛рдЗрд▓реЗрдВ рдереАрдВ, рддреЛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╕рддреНрдпрд╛рдкрди рдХреЛрдб рдиреЗ рдЙрд╕реА рдирд╛рдо рдХреЗ рд╕рд╛рде рдЕрдВрддрд┐рдо рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ , рдФрд░ рдЗрдВрд╕реНрдЯреЙрд▓рд░ рдиреЗ рдкрд╣рд▓реА рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ , рдЕрд░реНрдерд╛рдд, рд╕рддреНрдпрд╛рдкрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рджреЛ рдЬрд╝рд┐рдк рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рдмреАрдЪ рдЗрд╕ рдЫреЛрдЯреЗ рдЕрдВрддрд░ рдиреЗ рдкреВрд░реЗ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рд╕реБрд░рдХреНрд╖рд╛ рдореЙрдбрд▓ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛ рджрд┐рдпрд╛ред

рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдпрд╛ рдЬрд╛рджреВ рдирдВрдмрд░ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рдЗрдВрдЧрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдХрд┐рд╕реА рднреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рддрд░реАрдХреЗ рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдЖрдкрдХреЛ рдРрд╕реА рдлрд╛рдЗрд▓реЗрдВ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ рдЬреЛ рдЬрд╝рд┐рдк рдХреЗ рд░реВрдк рдореЗрдВ рдФрд░ рдПрдХ рдЕрд▓рдЧ рдкреНрд░рд╛рд░реВрдк - рдкреЙрд▓реАрдЧреНрд▓реЙрдЯ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдиреНрдп рд╣реИрдВ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реНрд╡рдпрдВ-рдирд┐рдХрд╛рд▓рдиреЗ рд╡рд╛рд▓реЗ рдЬрд╝рд┐рдк рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, pkz204g.exe ) рдЖрдорддреМрд░ рдкрд░ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдФрд░ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рджреЛрдиреЛрдВ рд╣реИрдВ: рдкрд╣рд▓рд╛ рднрд╛рдЧ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рд╣реИ, рдЗрд╕рдХреЗ рдмрд╛рдж рдПрдХ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ (рдЬреЛ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рднрд╛рдЧ рджреНрд╡рд╛рд░рд╛ рдЕрдирдкреИрдХ рдХреА рдЧрдИ рд╣реИ)ред рдУрдПрд╕ рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрд╝рд┐рдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЗрд╕реЗ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдЦреЛрд▓ рджреЗрдЧрд╛ред рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рдЖрдкрдХреЛ рдлрд╝рд╛рдЗрд▓ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреА рд╣реИред

рд╣рд╛рд▓рд╛рдВрдХрд┐ рдРрд╕реА рдкреЙрд▓реАрдЧреНрд▓реЙрдЯ рдлрд╛рдЗрд▓реЗрдВ рд╕реНрдорд╛рд░реНрдЯ рд╣реЛрддреА рд╣реИрдВ, рд╡реЗ рд╕реБрд░рдХреНрд╖рд╛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдЬрдиреНрдо рджреЗ рд╕рдХрддреА рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдлрд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рдЪрдХрдорд╛ рджреЗ рд╕рдХрддреА рд╣реИрдВ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдерд╛рди рдкрд░ рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг рдХреЛрдб рд╡рд┐рддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдкрдпреЛрдЧ рдХреА рдЧрдИ GIFAR рдлрд╛рдЗрд▓реЗрдВ, рдЬреЛ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ GIF рдЪрд┐рддреНрд░ рдФрд░ рдЬрд╛рд╡рд╛ рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ (JAR, рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЗрдВ) рд╕рд╣реА рд╣реИрдВред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП, рдлрд╝рд╛рдЗрд▓ рдХреЛ рджреБрд░реНрд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддреЗ рд╣реБрдП рдЖрд▓реЗрдЦ рджреЗрдЦреЗрдВ (рдкреГрд╖реНрда 18 рдкрд░ рд╢реБрд░реВ)ред

рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдиреАрдЪреЗ рджреЗрдЦреЗрдВрдЧреЗ, рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЗрдВ 32-рдмрд┐рдЯ рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдСрдлрд╝рд╕реЗрдЯреНрд╕ рдФрд░ рдЖрдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдВрдЧреНрд░рд╣ рдХрд╛ рдЖрдХрд╛рд░ рдФрд░ рдЗрд╕рдХреЗ рддрддреНрд╡реЛрдВ рдХреЛ рдЪрд╛рд░ рдЧреАрдЧрд╛рдмрд╛рдЗрдЯ рддрдХ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреА рд╣реИрдВред рдореЗрдВ рдЖрд╡реЗрджрди рдиреЛрдЯ 4.5PKWare рдиреЗ 64-рдмрд┐рдЯ рдСрдлрд╝рд╕реЗрдЯ рдФрд░ рдЖрдХрд╛рд░реЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реБрдП рдкреНрд░рд╛рд░реВрдк рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдЬреЛрдбрд╝ рджрд┐рдП рд╣реИрдВред рдЗрди рдПрдХреНрд╕рдЯреЗрдВрд╢рдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдлрд╛рдЗрд▓реЗрдВ рдЬрд╝рд┐рдк 64 рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо рдЙрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред

рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ


рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдХрд╛ рдЕрдВрдд


рдПрдХ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ (рдИрдУрд╕реАрдбреАрдЖрд░) рдХрд╛ рдЕрдВрдд рдЖрдорддреМрд░ рдкрд░ рдПрдХ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╢реБрд░реБрдЖрддреА рдмрд┐рдВрджреБ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХрд╛ рд╕реНрдерд╛рди рдФрд░ рдЖрдХрд╛рд░, рд╕рд╛рде рд╣реА рдкреВрд░реЗ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡реИрдХрд▓реНрдкрд┐рдХ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред

рдХрдИ рдбрд┐рд╕реНрдХреЗрдЯ - рдпрд╛ рд╡реЙрд▓реНрдпреВрдо рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ - рдИрдУрд╕реАрдбреАрдЖрд░ рдореЗрдВ рдпрд╣ рднреА рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрддреА рд╣реИ рдХрд┐ рд╣рдо рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХрд┐рд╕ рдбрд┐рд╕реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЬрд┐рд╕ рдбрд┐рд╕реНрдХ рдкрд░ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ, рдЖрджрд┐ред рдЖрдЬ, рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢рд╛рдпрдж рд╣реА рдХрднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдХреЛрдб рдРрд╕реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

EOCDR рд╣рд╕реНрддрд╛рдХреНрд╖рд░ 'P' K 'рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрд╛рдж рдмрд╛рдЗрдЯреНрд╕ 5 рдФрд░ 6. рдЗрд╕рдХреЗ рдмрд╛рдж рдиреАрдЪреЗ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╣реЛрддреА рд╣реИ, рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдЫреЛрдЯреЗ-рдПрдВрдбрд┐рдпрди рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

/* End of Central Directory Record. */
struct eocdr {
        uint16_t disk_nbr;        /* Number of this disk. */
        uint16_t cd_start_disk;   /* Nbr. of disk with start of the CD. */
        uint16_t disk_cd_entries; /* Nbr. of CD entries on this disk. */
        uint16_t cd_entries;      /* Nbr. of Central Directory entries. */
        uint32_t cd_size;         /* Central Directory size in bytes. */
        uint32_t cd_offset;       /* Central Directory file offset. */
        uint16_t comment_len;     /* Archive comment length. */
        const uint8_t *comment;   /* Archive comment. */
};

рдИрдУрд╕реАрдбреАрдЖрд░ рдлрд╛рдЗрд▓ рдХреЗ рдЕрдВрдд рдореЗрдВ рд╕реНрдерд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рдЗрд╕рдХреА рдкреВрдВрдЫ рдореЗрдВ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ 16-рдмрд┐рдЯ рд▓рдВрдмрд╛рдИ рдХреА рдЯрд┐рдкреНрдкрдгреА рд╣реЛ рд╕рдХрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдерд┐рддрд┐ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:

/* Read 16/32 bits little-endian and bump p forward afterwards. */
#define READ16(p) ((p) += 2, read16le((p) - 2))
#define READ32(p) ((p) += 4, read32le((p) - 4))

/* Size of the End of Central Directory Record, not including comment. */
#define EOCDR_BASE_SZ 22
#define EOCDR_SIGNATURE 0x06054b50  /* "PK\5\6" little-endian. */

static bool find_eocdr(struct eocdr *r, const uint8_t *src, size_t src_len)
{
        size_t comment_len;
        const uint8_t *p;
        uint32_t signature;

        for (comment_len = 0; comment_len <= UINT16_MAX; comment_len++) {
                if (src_len < EOCDR_BASE_SZ + comment_len) {
                        break;
                }

                p = &src[src_len - EOCDR_BASE_SZ - comment_len];
                signature = READ32(p);

                if (signature == EOCDR_SIGNATURE) {
                        r->disk_nbr = READ16(p);
                        r->cd_start_disk = READ16(p);
                        r->disk_cd_entries = READ16(p);
                        r->cd_entries = READ16(p);
                        r->cd_size = READ32(p);
                        r->cd_offset = READ32(p);
                        r->comment_len = READ16(p);
                        r->comment = p;
                        assert(p == &src[src_len - comment_len] &&
                               "All fields read.");

                        if (r->comment_len == comment_len) {
                                return true;
                        }
                }
        }

        return false;
}

EOCDR рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдЖрд╕рд╛рди рд╣реИред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрддрд╛ рд╣реИ рдФрд░ рд▓рд┐рдЦреА рдЧрдИ рдмрд╛рдЗрдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ:

/* Write 16/32 bits little-endian and bump p forward afterwards. */
#define WRITE16(p, x) (write16le((p), (x)), (p) += 2)
#define WRITE32(p, x) (write32le((p), (x)), (p) += 4)

static size_t write_eocdr(uint8_t *dst, const struct eocdr *r)
{
        uint8_t *p = dst;

        WRITE32(p, EOCDR_SIGNATURE);
        WRITE16(p, r->disk_nbr);
        WRITE16(p, r->cd_start_disk);
        WRITE16(p, r->disk_cd_entries);
        WRITE16(p, r->cd_entries);
        WRITE32(p, r->cd_size);
        WRITE32(p, r->cd_offset);
        WRITE16(p, r->comment_len);
        assert(p - dst == EOCDR_BASE_SZ);

        if (r->comment_len != 0) {
                memcpy(p, r->comment, r->comment_len);
                p += r->comment_len;
        }

        return (size_t)(p - dst);
}

рд╕реЗрдВрдЯреНрд░рд▓ рдлрд╝рд╛рдЗрд▓ рд╣реИрдбрд░


рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдХреЗрдВрджреНрд░реАрдп рдлрд╝рд╛рдЗрд▓ рд╣реЗрдбрд░ рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдЧреНрд░рд╣ рдЖрдЗрдЯрдо рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ рд▓рд┐рдЦреЗ рдЬрд╛рддреЗ рд╣реИрдВред рдкреНрд░рддреНрдпреЗрдХ рд╢реАрд░реНрд╖рдХ 'P', 'K', 1, 2 рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЗрд╕ рддрд░рд╣ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╣реЛрддреА рд╣реИ:

#define EXT_ATTR_DIR (1U << 4)
#define EXT_ATTR_ARC (1U << 5)

/* Central File Header (Central Directory Entry) */
struct cfh {
        uint16_t made_by_ver;    /* Version made by. */
        uint16_t extract_ver;    /* Version needed to extract. */
        uint16_t gp_flag;        /* General purpose bit flag. */
        uint16_t method;         /* Compression method. */
        uint16_t mod_time;       /* Modification time. */
        uint16_t mod_date;       /* Modification date. */
        uint32_t crc32;          /* CRC-32 checksum. */
        uint32_t comp_size;      /* Compressed size. */
        uint32_t uncomp_size;    /* Uncompressed size. */
        uint16_t name_len;       /* Filename length. */
        uint16_t extra_len;      /* Extra data length. */
        uint16_t comment_len;    /* Comment length. */
        uint16_t disk_nbr_start; /* Disk nbr. where file begins. */
        uint16_t int_attrs;      /* Internal file attributes. */
        uint32_t ext_attrs;      /* External file attributes. */
        uint32_t lfh_offset;     /* Local File Header offset. */
        const uint8_t *name;     /* Filename. */
        const uint8_t *extra;    /* Extra data. */
        const uint8_t *comment;  /* File comment. */
};

made_by_verрдФрд░ extract_verрдЗрд╕ рдЖрдЗрдЯрдо рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рдУрдПрд╕ рдФрд░ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдПрдиреНрдХреЛрдб рдХрд░реЗрдВ, рд╕рд╛рде рд╣реА рдЗрд╕реЗ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕ рд╕рдВрд╕реНрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЖрда рдмрд┐рдЯреНрд╕ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдПрдирдХреЛрдб рдХрд░рддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 0 рдХрд╛ рдЕрд░реНрде рд╣реИ рдбреЙрд╕, 3 рдХрд╛ рдЕрд░реНрде рд╣реИ рдпреВрдирд┐рдХреНрд╕, 10 рдХрд╛ рдорддрд▓рдм рд╣реИ рд╡рд┐рдВрдбреЛрдЬ рдПрдирдЯреАрдПрдлрдПрд╕), рдФрд░ рдирд┐рдЪрд▓реЗ рдЖрда рдмрд┐рдЯреНрд╕ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдПрдирдХреЛрдб рдХрд░рддреЗ рд╣реИрдВред рджрд╢рдорд▓рд╡ рдорд╛рди рдХреЛ 20 рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ PKZip 2.0 рдХреЗ рд╕рд╛рде рд╕рдВрдЧрддрддрд╛ред

gp_flagрдЕрд▓рдЧ рдЭрдВрдбреЗ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рд╣рдореЗ рд░реВрдЪрд┐ рд╣реИ:

  • рдмрд┐рдЯ 0, рддрддреНрд╡ рдХреЗ рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдХреЗ рддрдереНрдп рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ (рд╣рдо рдЗрд╕ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ);
  • рдФрд░ рдмрд┐рдЯреНрд╕ 1 рдФрд░ 2, Deflate рд╕рдВрдкреАрдбрд╝рди рдХреЗ рд╕реНрддрд░ рдХреЛ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ (0 - рд╕рд╛рдорд╛рдиреНрдп, 1 - рдЕрдзрд┐рдХрддрдо, 2 - рддреЗрдЬ, 3 - рдмрд╣реБрдд рддреЗрдЬ)ред

methodрдПрдХ рд╕рдВрдкреАрдбрд╝рди рд╡рд┐рдзрд┐ рд╕рд╛рдВрдХреЗрддрд┐рдХ рд╢рдмреНрджреЛрдВ рдореЗрдВ рдмрджрд▓рдирд╛ред 0 - рдбреЗрдЯрд╛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдирд╣реАрдВ, 8 - рд╡рд┐рд▓рдВрдмрд┐рдд рд▓рд╛рдЧреВред рдЕрдиреНрдп рдореВрд▓реНрдп рдкреБрд░рд╛рдиреЗ рдпрд╛ рдирдП рдПрд▓реНрдЧреЛрд░рд┐рджрдо рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВ, рд▓реЗрдХрд┐рди рд▓рдЧрднрдЧ рд╕рднреА рдЬрд╝рд┐рдк рдЗрди рджреЛ рдореВрд▓реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

mod_timeрдФрд░ MS-DOS рдкреНрд░рд╛рд░реВрдкmod_date рдореЗрдВ рдПрдиреНрдХреЛрдб рдХрд┐рдП рдЧрдП рджрд┐рдирд╛рдВрдХ рдФрд░ рд╕рдордп рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рдЗрд╕ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо MS-DOS рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп C рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреЛ рдФрд░ рдЙрд╕рд╕реЗ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░реЗрдВрдЧреЗ :time_t

/* Convert DOS date and time to time_t. */
static time_t dos2ctime(uint16_t dos_date, uint16_t dos_time)
{
        struct tm tm = {0};

        tm.tm_sec = (dos_time & 0x1f) * 2;  /* Bits 0--4:  Secs divided by 2. */
        tm.tm_min = (dos_time >> 5) & 0x3f; /* Bits 5--10: Minute. */
        tm.tm_hour = (dos_time >> 11);      /* Bits 11-15: Hour (0--23). */

        tm.tm_mday = (dos_date & 0x1f);          /* Bits 0--4: Day (1--31). */
        tm.tm_mon = ((dos_date >> 5) & 0xf) - 1; /* Bits 5--8: Month (1--12). */
        tm.tm_year = (dos_date >> 9) + 80;       /* Bits 9--15: Year-1980. */

        tm.tm_isdst = -1;

        return mktime(&tm);
}

/* Convert time_t to DOS date and time. */
static void ctime2dos(time_t t, uint16_t *dos_date, uint16_t *dos_time)
{
        struct tm *tm = localtime(&t);

        *dos_time = 0;
        *dos_time |= tm->tm_sec / 2;    /* Bits 0--4:  Second divided by two. */
        *dos_time |= tm->tm_min << 5;   /* Bits 5--10: Minute. */
        *dos_time |= tm->tm_hour << 11; /* Bits 11-15: Hour. */

        *dos_date = 0;
        *dos_date |= tm->tm_mday;             /* Bits 0--4:  Day (1--31). */
        *dos_date |= (tm->tm_mon + 1) << 5;   /* Bits 5--8:  Month (1--12). */
        *dos_date |= (tm->tm_year - 80) << 9; /* Bits 9--15: Year from 1980. */
}

рдлрд╝реАрд▓реНрдб crc32рдореЗрдВ рдЕрд╕рдореНрдкреАрдбрд┐рдд рдбреЗрдЯрд╛ рдХреЗ рдЪрдХреНрд░реАрдп рдирд┐рд░рд░реНрдердХ рдХреЛрдб рдХрд╛ рдорд╛рди рд╣реЛрддрд╛ рд╣реИ ред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддрд┐ рдХреЗ рдмрд╛рдж рдбреЗрдЯрд╛ рдЕрдЦрдВрдбрддрд╛ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди: crc32.c ред

comp_sizeрдФрд░ uncomp_sizeрдЖрдЗрдЯрдо рдлрд╝рд╛рдЗрд▓ рдбреЗрдЯрд╛ рдХреЗ рд╕рдВрдХреБрдЪрд┐рдд рдФрд░ рдЕрд╕рдореНрдкреАрдбрд┐рдд рдЖрдХрд╛рд░ рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддреАрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рд╢реАрд░реНрд╖рдХ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рдирд╛рдо, рдЯрд┐рдкреНрдкрдгреА рдФрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рдбреЗрдЯрд╛ рдХреА рд▓рдВрдмрд╛рдИ рд╣реЛрддреА рд╣реИред disk_nbr_startрдХрдИ рдбрд┐рд╕реНрдХреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ред

int_attrsрдФрд░ ext_attrsрдлрд╝рд╛рдЗрд▓ рдХреА рдЖрдВрддрд░рд┐рдХ рдФрд░ рдмрд╛рд╣рд░реА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВред рдЖрдВрддрд░рд┐рдХ рд▓реЛрдЧ рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрдо рд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреЗрд╡рд▓ рдкрд╛рда рд╣реИред рдмрд╛рд╣рд░реА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рд╕реЗ рд╕рдВрдХреЗрдд рдорд┐рд▓рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдлрд╝рд╛рдЗрд▓ рдЫрд┐рдкреА рд╣реБрдИ рд╣реИ, рдХреЗрд╡рд▓-рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрджрд┐ред рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рд╕рд╛рдордЧреНрд░реА OS рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдкрд░made_by_verред рдбреЙрд╕ рдореЗрдВ, рдирд┐рдЪрд▓реЗ 8 рдмрд┐рдЯреНрд╕ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рд╡рд┐рд╢реЗрд╖рддрд╛ рдмрд╛рдЗрдЯ рд╣реЛрддреА рд╣реИ, рдЬрд┐рд╕реЗ Int 21 / AX = 4300h рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдмрд┐рдЯ 4 рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╣реИ, рдФрд░ рдмрд┐рдЯ 5 рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ "рд╕рдВрдЧреНрд░рд╣" рд╡рд┐рд╢реЗрд╖рддрд╛ рд╕реЗрдЯ рд╣реИ (рдбреЙрд╕ рдореЗрдВ рдЕрдзрд┐рдХрд╛рдВрд╢ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдЪ рд╣реИ)ред рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ, рд╕рдВрдЧрддрддрд╛ рдХреЗ рд▓рд┐рдП, рдпреЗ рдмрд┐рдЯреНрд╕ рд╕рдорд╛рди рд░реВрдк рд╕реЗ рдЕрдиреНрдп рдУрдПрд╕ рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдП рдЧрдП рд╣реИрдВред рдпреВрдирд┐рдХреНрд╕ рдкрд░, рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рдЙрдЪреНрдЪ 16 рдмрд┐рдЯ рдлрд╝рд╛рдЗрд▓ рдореЛрдб рдмрд┐рдЯреНрд╕ рдХрд┐ рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ рд╕реНрдЯреЗрдЯ (2) рдореЗрдВ st_modeред

lfh_offsetрд╣рдореЗрдВ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕реНрдерд╛рдиреАрдп рдлрд╝рд╛рдЗрд▓ рд╢реАрд░реНрд╖рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛рдБ рджреЗрдЦрдирд╛ рд╣реИред name- рдлрд╝рд╛рдЗрд▓ рдирд╛рдо (рд╕реА-рд▓рд╛рдЗрди), рдФрд░ comment- рдЗрд╕ рд╕рдВрдЧреНрд░рд╣ рддрддреНрд╡ (рд╕реА-рд▓рд╛рдЗрди) рдХреЗ рд▓рд┐рдП рд╡реИрдХрд▓реНрдкрд┐рдХ рдЯрд┐рдкреНрдкрдгреАред extraрд╡реИрдХрд▓реНрдкрд┐рдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдбреЗрдЯрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдХрд┐ рдпреВрдирд┐рдХреНрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЗ рдорд╛рд▓рд┐рдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА, рдкрд░рд┐рд╡рд░реНрддрди рдХреА рд╕рд╣реА рддрд╛рд░реАрдЦ рдФрд░ рд╕рдордп, рдпрд╛ рдЬрд╝рд┐рдк 64 рдлрд╝реАрд▓реНрдбред

рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдХреЗрдВрджреНрд░реАрдп рд╢реАрд░реНрд╖рдХреЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

/* Size of a Central File Header, not including name, extra, and comment. */
#define CFH_BASE_SZ 46
#define CFH_SIGNATURE 0x02014b50 /* "PK\1\2" little-endian. */

static bool read_cfh(struct cfh *cfh, const uint8_t *src, size_t src_len,
                     size_t offset)
{
        const uint8_t *p;
        uint32_t signature;

        if (offset > src_len || src_len - offset < CFH_BASE_SZ) {
                return false;
        }

        p = &src[offset];
        signature = READ32(p);
        if (signature != CFH_SIGNATURE) {
                return false;
        }

        cfh->made_by_ver = READ16(p);
        cfh->extract_ver = READ16(p);
        cfh->gp_flag = READ16(p);
        cfh->method = READ16(p);
        cfh->mod_time = READ16(p);
        cfh->mod_date = READ16(p);
        cfh->crc32 = READ32(p);
        cfh->comp_size = READ32(p);
        cfh->uncomp_size = READ32(p);
        cfh->name_len = READ16(p);
        cfh->extra_len = READ16(p);
        cfh->comment_len = READ16(p);
        cfh->disk_nbr_start = READ16(p);
        cfh->int_attrs = READ16(p);
        cfh->ext_attrs = READ32(p);
        cfh->lfh_offset = READ32(p);
        cfh->name = p;
        cfh->extra = cfh->name + cfh->name_len;
        cfh->comment = cfh->extra + cfh->extra_len;
        assert(p == &src[offset + CFH_BASE_SZ] && "All fields read.");

        if (src_len - offset - CFH_BASE_SZ <
            cfh->name_len + cfh->extra_len + cfh->comment_len) {
                return false;
        }

        return true;
}

static size_t write_cfh(uint8_t *dst, const struct cfh *cfh)
{
        uint8_t *p = dst;

        WRITE32(p, CFH_SIGNATURE);
        WRITE16(p, cfh->made_by_ver);
        WRITE16(p, cfh->extract_ver);
        WRITE16(p, cfh->gp_flag);
        WRITE16(p, cfh->method);
        WRITE16(p, cfh->mod_time);
        WRITE16(p, cfh->mod_date);
        WRITE32(p, cfh->crc32);
        WRITE32(p, cfh->comp_size);
        WRITE32(p, cfh->uncomp_size);
        WRITE16(p, cfh->name_len);
        WRITE16(p, cfh->extra_len);
        WRITE16(p, cfh->comment_len);
        WRITE16(p, cfh->disk_nbr_start);
        WRITE16(p, cfh->int_attrs);
        WRITE32(p, cfh->ext_attrs);
        WRITE32(p, cfh->lfh_offset);
        assert(p - dst == CFH_BASE_SZ);

        if (cfh->name_len != 0) {
                memcpy(p, cfh->name, cfh->name_len);
                p += cfh->name_len;
        }

        if (cfh->extra_len != 0) {
                memcpy(p, cfh->extra, cfh->extra_len);
                p += cfh->extra_len;
        }

        if (cfh->comment_len != 0) {
                memcpy(p, cfh->comment, cfh->comment_len);
                p += cfh->comment_len;
        }

        return (size_t)(p - dst);
}

рд╕реНрдерд╛рдиреАрдп рдлрд╝рд╛рдЗрд▓ рд╣реЗрдбрд░


рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдЧреНрд░рд╣ рддрддреНрд╡ рдХрд╛ рдбреЗрдЯрд╛ рдПрдХ рд╕реНрдерд╛рдиреАрдп рдлрд╝рд╛рдЗрд▓ рд╣реЗрдбрд░ рд╕реЗ рдкрд╣рд▓реЗ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдХреЗрдВрджреНрд░реАрдп рд╣реЗрдбрд░ рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рджреЛрд╣рд░рд╛рддрд╛ рд╣реИред

рдХреЗрдВрджреНрд░реАрдп рдФрд░ рд╕реНрдерд╛рдиреАрдп рд╣реЗрдбрд░ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рджреЛрд╣рд░рд╛рд╡ рдХреЛ рд╕рдВрднрд╡рддрдпрд╛ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рддрд╛рдХрд┐ рдкреАрдХреЗрдЬрд┐рдк рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рдореЗрдореЛрд░реА рдореЗрдВ рдирд╣реАрдВ рд░рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдЬреИрд╕рд╛ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рд╛рдЗрд▓ рдирд┐рдХрд╛рд▓реА рдЬрд╛рддреА рд╣реИ, рдЙрд╕рдХрд╛ рдирд╛рдо рдФрд░ рдЕрдиреНрдп рдЬрд╛рдирдХрд╛рд░реА рд╕реНрдерд╛рдиреАрдп рд╣реЗрдбрд░ рд╕реЗ рдкрдврд╝реА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕реНрдерд╛рдиреАрдп рд╣реЗрдбрд░ рдЬрд╝рд┐рдк рдЕрднрд┐рд▓реЗрдЦрд╛рдЧрд╛рд░ рд╕реЗ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдХреЗрдВрджреНрд░реАрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдЧрд╛рдпрдм рдпрд╛ рдХреНрд╖рддрд┐рдЧреНрд░рд╕реНрдд рд╣реЛрддреА рд╣реИред

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдЕрддрд┐рд░реЗрдХ рдЕрдирд┐рд╢реНрдЪрд┐рддрддрд╛ рдХрд╛ рдореБрдЦреНрдп рд╕реНрд░реЛрдд рднреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдХреЗрдВрджреНрд░реАрдп рдФрд░ рд╕реНрдерд╛рдиреАрдп рд╣реЗрдбрд░ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрдЧрд╛? рдпрд╣ рдЕрдХреНрд╕рд░ рдмрдЧ рдФрд░ рд╕реБрд░рдХреНрд╖рд╛ рдореБрджреНрджреЛрдВ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИред

рд╕реЗрдВрдЯреНрд░рд▓ рд╣реИрдбрд┐рдВрдЧ рд╕реЗ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдирд╣реАрдВ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд╝рд╛рдЗрд▓ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рд╡рд╛рд▓реЗ рдлрд╝реАрд▓реНрдбред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рддреАрд╕рд░рд╛ рдХрдо рд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯ gp_flags(рд╕реАрдЖрд░рд╕реА -32) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИ , рддреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдФрд░ рдЕрд╕рдореНрдкреАрдбрд┐рдд рдлрд╝реАрд▓реНрдб рд╢реВрдиреНрдп рдкрд░ рд░реАрд╕реЗрдЯ рд╣реЛ рдЬрд╛рдПрдВрдЧреЗ, рдФрд░ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдбреЗрдЯрд╛ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдмреНрд▓реЙрдХ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдХреЗ рдбреЗрдЯрд╛ рдХреЗ рдмрд╛рдж рд╣реА рдорд┐рд▓ рд╕рдХрддреА рд╣реИ (рд╣рдо рдЗрд╕ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ)ред рдпрд╣ рдЖрдкрдХреЛ рддрддреНрд╡ рдХрд╛ рдлрд╝рд╛рдЗрд▓ рдЖрдХрд╛рд░ рдЬреНрдЮрд╛рдд рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдпрд╛ рдпрд╣ рдХрд┐рд╕ рдЖрдХрд╛рд░ рдореЗрдВ рд╕рдВрдкреАрдбрд╝рд┐рдд рд╣реЛрдЧрд╛, рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рд╕реНрдерд╛рдиреАрдп рд╣реЗрдбрд░ рд░рд┐рдХреЙрд░реНрдб рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рд╕реНрдерд╛рдиреАрдп рд╣реЗрдбрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ 'P', 'K', 3, 4 рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЗрд╕ рддрд░рд╣ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╣реЛрддреА рд╣реИ:

/* Local File Header. */
struct lfh {
        uint16_t extract_ver;
        uint16_t gp_flag;
        uint16_t method;
        uint16_t mod_time;
        uint16_t mod_date;
        uint32_t crc32;
        uint32_t comp_size;
        uint32_t uncomp_size;
        uint16_t name_len;
        uint16_t extra_len;
        const uint8_t *name;
        const uint8_t *extra;
};

рдпреЗ рдлрд╝рдВрдХреНрд╢рди рд╕реНрдерд╛рдиреАрдп рд╣реЗрдбрд░ рдХреЛ рдкрдврд╝рддреЗ рд╣реИрдВ рдФрд░ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдЕрдиреНрдп рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреА рддрд░рд╣:

/* Size of a Local File Header, not including name and extra. */
#define LFH_BASE_SZ 30
#define LFH_SIGNATURE 0x04034b50 /* "PK\3\4" little-endian. */

static bool read_lfh(struct lfh *lfh, const uint8_t *src, size_t src_len,
                     size_t offset)
{
        const uint8_t *p;
        uint32_t signature;

        if (offset > src_len || src_len - offset < LFH_BASE_SZ) {
                return false;
        }

        p = &src[offset];
        signature = READ32(p);
        if (signature != LFH_SIGNATURE) {
                return false;
        }

        lfh->extract_ver = READ16(p);
        lfh->gp_flag = READ16(p);
        lfh->method = READ16(p);
        lfh->mod_time = READ16(p);
        lfh->mod_date = READ16(p);
        lfh->crc32 = READ32(p);
        lfh->comp_size = READ32(p);
        lfh->uncomp_size = READ32(p);
        lfh->name_len = READ16(p);
        lfh->extra_len = READ16(p);
        lfh->name = p;
        lfh->extra = lfh->name + lfh->name_len;
        assert(p == &src[offset + LFH_BASE_SZ] && "All fields read.");

        if (src_len - offset - LFH_BASE_SZ < lfh->name_len + lfh->extra_len) {
                return false;
        }

        return true;
}

static size_t write_lfh(uint8_t *dst, const struct lfh *lfh)
{
        uint8_t *p = dst;

        WRITE32(p, LFH_SIGNATURE);
        WRITE16(p, lfh->extract_ver);
        WRITE16(p, lfh->gp_flag);
        WRITE16(p, lfh->method);
        WRITE16(p, lfh->mod_time);
        WRITE16(p, lfh->mod_date);
        WRITE32(p, lfh->crc32);
        WRITE32(p, lfh->comp_size);
        WRITE32(p, lfh->uncomp_size);
        WRITE16(p, lfh->name_len);
        WRITE16(p, lfh->extra_len);
        assert(p - dst == LFH_BASE_SZ);

        if (lfh->name_len != 0) {
                memcpy(p, lfh->name, lfh->name_len);
                p += lfh->name_len;
        }

        if (lfh->extra_len != 0) {
                memcpy(p, lfh->extra, lfh->extra_len);
                p += lfh->extra_len;
        }

        return (size_t)(p - dst);
}

рдЬрд┐рдк рд░реАрдб рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдХреЗ рдкрдврд╝рдиреЗ рдХреЛ рдореЗрдореЛрд░реА рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕рдВрдЧреНрд░рд╣ рддрддреНрд╡реЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:

typedef size_t zipiter_t; /* Zip archive member iterator. */

typedef struct zip_t zip_t;
struct zip_t {
        uint16_t num_members;    /* Number of members. */
        const uint8_t *comment;  /* Zip file comment (not terminated). */
        uint16_t comment_len;    /* Zip file comment length. */
        zipiter_t members_begin; /* Iterator to the first member. */
        zipiter_t members_end;   /* Iterator to the end of members. */

        const uint8_t *src;
        size_t src_len;
};

/* Initialize zip based on the source data. Returns true on success, or false
   if the data could not be parsed as a valid Zip file. */
bool zip_read(zip_t *zip, const uint8_t *src, size_t src_len)
{
        struct eocdr eocdr;
        struct cfh cfh;
        struct lfh lfh;
        size_t i, offset;
        const uint8_t *comp_data;

        zip->src = src;
        zip->src_len = src_len;

        if (!find_eocdr(&eocdr, src, src_len)) {
                return false;
        }

        if (eocdr.disk_nbr != 0 || eocdr.cd_start_disk != 0 ||
            eocdr.disk_cd_entries != eocdr.cd_entries) {
                return false; /* Cannot handle multi-volume archives. */
        }

        zip->num_members = eocdr.cd_entries;
        zip->comment = eocdr.comment;
        zip->comment_len = eocdr.comment_len;

        offset = eocdr.cd_offset;
        zip->members_begin = offset;

        /* Read the member info and do a few checks. */
        for (i = 0; i < eocdr.cd_entries; i++) {
                if (!read_cfh(&cfh, src, src_len, offset)) {
                        return false;
                }

                if (cfh.gp_flag & 1) {
                        return false; /* The member is encrypted. */
                }
                if (cfh.method != ZIP_STORED && cfh.method != ZIP_DEFLATED) {
                        return false; /* Unsupported compression method. */
                }
                if (cfh.method == ZIP_STORED &&
                    cfh.uncomp_size != cfh.comp_size) {
                        return false;
                }
                if (cfh.disk_nbr_start != 0) {
                        return false; /* Cannot handle multi-volume archives. */
                }
                if (memchr(cfh.name, '\0', cfh.name_len) != NULL) {
                        return false; /* Bad filename. */
                }

                if (!read_lfh(&lfh, src, src_len, cfh.lfh_offset)) {
                        return false;
                }

                comp_data = lfh.extra + lfh.extra_len;
                if (cfh.comp_size > src_len - (size_t)(comp_data - src)) {
                        return false; /* Member data does not fit in src. */
                }

                offset += CFH_BASE_SZ + cfh.name_len + cfh.extra_len +
                          cfh.comment_len;
        }

        zip->members_end = offset;

        return true;
}

рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдКрдкрд░ рдмрддрд╛рдпрд╛, рддрддреНрд╡ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпрд╛рдБ рдХреЗрдВрджреНрд░реАрдп рдлрд╝рд╛рдЗрд▓ рд╢реАрд░реНрд╖ рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рдмрд╕ рдСрдлрд╝рд╕реЗрдЯ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдк рддрддреНрд╡ рдбреЗрдЯрд╛ рддрдХ рдкрд╣реБрдБрдЪ рд╕рдХрддреЗ рд╣реИрдВ:

typedef enum { ZIP_STORED = 0, ZIP_DEFLATED = 8 } method_t;

typedef struct zipmemb_t zipmemb_t;
struct zipmemb_t {
        const uint8_t *name;      /* Member name (not null terminated). */
        uint16_t name_len;        /* Member name length. */
        time_t mtime;             /* Modification time. */
        uint32_t comp_size;       /* Compressed size. */
        const uint8_t *comp_data; /* Compressed data. */
        method_t method;          /* Compression method. */
        uint32_t uncomp_size;     /* Uncompressed size. */
        uint32_t crc32;           /* CRC-32 checksum. */
        const uint8_t *comment;   /* Comment (not null terminated). */
        uint16_t comment_len;     /* Comment length. */
        bool is_dir;              /* Whether this is a directory. */
        zipiter_t next;           /* Iterator to the next member. */
};

/* Get the Zip archive member through iterator it. */
zipmemb_t zip_member(const zip_t *zip, zipiter_t it)
{
        struct cfh cfh;
        struct lfh lfh;
        bool ok;
        zipmemb_t m;

        assert(it >= zip->members_begin && it < zip->members_end);

        ok = read_cfh(&cfh, zip->src, zip->src_len, it);
        assert(ok);

        ok = read_lfh(&lfh, zip->src, zip->src_len, cfh.lfh_offset);
        assert(ok);

        m.name = cfh.name;
        m.name_len = cfh.name_len;
        m.mtime = dos2ctime(cfh.mod_date, cfh.mod_time);
        m.comp_size = cfh.comp_size;
        m.comp_data = lfh.extra + lfh.extra_len;
        m.method = cfh.method;
        m.uncomp_size = cfh.uncomp_size;
        m.crc32 = cfh.crc32;
        m.comment = cfh.comment;
        m.comment_len = cfh.comment_len;
        m.is_dir = (cfh.ext_attrs & EXT_ATTR_DIR) != 0;

        m.next = it + CFH_BASE_SZ +
                 cfh.name_len + cfh.extra_len + cfh.comment_len;

        assert(m.next <= zip->members_end);

        return m;
}

рдЬрд┐рдк рд░рд┐рдХреЙрд░реНрдб рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдореЗрдореЛрд░реА рдмрдлрд░ рдореЗрдВ рдЬрд┐рдк рдлрд╛рдЗрд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рдпрд╣ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрд┐рддрдиреА рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреА рд╣реИред рдФрд░ рдЪреВрдБрдХрд┐ рд╣рдо рдпрд╣ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд▓рд┐рдЦрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣рдо рдХрд┐рддрдирд╛ рдбреЗрдЯрд╛ рдХрдВрдкреНрд░реЗрд╕ рдХрд░реЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЕрд╕рдореНрдкреАрдбрд┐рдд рддрддреНрд╡реЛрдВ рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдКрдкрд░реА рд╕реАрдорд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ:

/* Compute an upper bound on the dst size required by zip_write() for an
 * archive with num_memb members with certain filenames, sizes, and archive
 * comment. Returns zero on error, e.g. if a filename is longer than 2^16-1, or
 * if the total file size is larger than 2^32-1. */
uint32_t zip_max_size(uint16_t num_memb, const char *const *filenames,
                      const uint32_t *file_sizes, const char *comment)
{
        size_t comment_len, name_len;
        uint64_t total;
        uint16_t i;

        comment_len = (comment == NULL ? 0 : strlen(comment));
        if (comment_len > UINT16_MAX) {
                return 0;
        }

        total = EOCDR_BASE_SZ + comment_len; /* EOCDR */

        for (i = 0; i < num_memb; i++) {
                assert(filenames[i] != NULL);
                name_len = strlen(filenames[i]);
                if (name_len > UINT16_MAX) {
                        return 0;
                }

                total += CFH_BASE_SZ + name_len; /* Central File Header */
                total += LFH_BASE_SZ + name_len; /* Local File Header */
                total += file_sizes[i];          /* Uncompressed data size. */
        }

        if (total > UINT32_MAX) {
                return 0;
        }

        return (uint32_t)total;
}

рдпрд╣ рдХреЛрдб рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рдЕрдкрд╕реНрдлреАрддрд┐ рд╕рдВрдкреАрдбрд╝рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдХреЛ рд▓рд┐рдЦрддрд╛ рд╣реИ, рдЙрдирдХрд╛ рдЖрдХрд╛рд░ рдХрдо рдХрд░рддрд╛ рд╣реИ:

/* Write a Zip file containing num_memb members into dst, which must be large
   enough to hold the resulting data. Returns the number of bytes written, which
   is guaranteed to be less than or equal to the result of zip_max_size() when
   called with the corresponding arguments. comment shall be a null-terminated
   string or null. callback shall be null or point to a function which will
   get called after the compression of each member. */
uint32_t zip_write(uint8_t *dst, uint16_t num_memb,
                   const char *const *filenames,
                   const uint8_t *const *file_data,
                   const uint32_t *file_sizes,
                   const time_t *mtimes,
                   const char *comment,
                   void (*callback)(const char *filename, uint32_t size,
                                    uint32_t comp_size))
{
        uint16_t i;
        uint8_t *p;
        struct eocdr eocdr;
        struct cfh cfh;
        struct lfh lfh;
        bool ok;
        uint16_t name_len;
        uint8_t *data_dst;
        size_t comp_sz;
        uint32_t lfh_offset, cd_offset, eocdr_offset;

        p = dst;

        /* Write Local File Headers and deflated or stored data. */
        for (i = 0; i < num_memb; i++) {
                assert(filenames[i] != NULL);
                assert(strlen(filenames[i]) <= UINT16_MAX);
                name_len = (uint16_t)strlen(filenames[i]);

                data_dst = p + LFH_BASE_SZ + name_len;

                if (hwdeflate(file_data[i], file_sizes[i], data_dst,
                              file_sizes[i], &comp_sz) &&
                                comp_sz < file_sizes[i]) {
                        lfh.method = ZIP_DEFLATED;
                        assert(comp_sz <= UINT32_MAX);
                        lfh.comp_size = (uint32_t)comp_sz;
                } else {
                        memcpy(data_dst, file_data[i], file_sizes[i]);
                        lfh.method = ZIP_STORED;
                        lfh.comp_size = file_sizes[i];
                }

                if (callback != NULL) {
                        callback(filenames[i], file_sizes[i], lfh.comp_size);
                }

                lfh.extract_ver = (0 << 8) | 20; /* DOS | PKZIP 2.0 */
                lfh.gp_flag = (lfh.method == ZIP_DEFLATED ? (0x1 << 1) : 0x0);
                ctime2dos(mtimes[i], &lfh.mod_date, &lfh.mod_time);
                lfh.crc32 = crc32(file_data[i], file_sizes[i]);
                lfh.uncomp_size = file_sizes[i];
                lfh.name_len = name_len;
                lfh.extra_len = 0;
                lfh.name = (const uint8_t*)filenames[i];
                p += write_lfh(p, &lfh);
                p += lfh.comp_size;
        }

        assert(p - dst <= UINT32_MAX);
        cd_offset = (uint32_t)(p - dst);

        /* Write the Central Directory based on the Local File Headers. */
        lfh_offset = 0;
        for (i = 0; i < num_memb; i++) {
                ok = read_lfh(&lfh, dst, SIZE_MAX, lfh_offset);
                assert(ok);

                cfh.made_by_ver = lfh.extract_ver;
                cfh.extract_ver = lfh.extract_ver;
                cfh.gp_flag = lfh.gp_flag;
                cfh.method = lfh.method;
                cfh.mod_time = lfh.mod_time;
                cfh.mod_date = lfh.mod_date;
                cfh.crc32 = lfh.crc32;
                cfh.comp_size = lfh.comp_size;
                cfh.uncomp_size = lfh.uncomp_size;
                cfh.name_len = lfh.name_len;
                cfh.extra_len = 0;
                cfh.comment_len = 0;
                cfh.disk_nbr_start = 0;
                cfh.int_attrs = 0;
                cfh.ext_attrs = EXT_ATTR_ARC;
                cfh.lfh_offset = lfh_offset;
                cfh.name = lfh.name;
                p += write_cfh(p, &cfh);

                lfh_offset += LFH_BASE_SZ + lfh.name_len + lfh.comp_size;
        }

        assert(p - dst <= UINT32_MAX);
        eocdr_offset = (uint32_t)(p - dst);

        /* Write the End of Central Directory Record. */
        eocdr.disk_nbr = 0;
        eocdr.cd_start_disk = 0;
        eocdr.disk_cd_entries = num_memb;
        eocdr.cd_entries = num_memb;
        eocdr.cd_size = eocdr_offset - cd_offset;
        eocdr.cd_offset = cd_offset;
        eocdr.comment_len = (uint16_t)(comment == NULL ? 0 : strlen(comment));
        eocdr.comment = (const uint8_t*)comment;
        p += write_eocdr(p, &eocdr);

        assert(p - dst <= zip_max_size(num_memb, filenames, file_sizes,
                                       comment));

        return (uint32_t)(p - dst);
}

Hwzip


рдЕрдм рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдХреИрд╕реЗ рдкрдврд╝рдирд╛ рдФрд░ рд▓рд┐рдЦрдирд╛ рд╣реИ, рдЙрдирдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдбреЗрдЯрд╛ рдХреЛ рдХреИрд╕реЗ рд╕рдВрдкреАрдбрд╝рд┐рдд рдФрд░ рд╡рд┐рдШрдЯрд┐рдд рдХрд░рдирд╛ рд╣реИред рдЕрдм рдЖрдЗрдП рдЗрди рд╕рднреА рд╕рд╛рдзрдиреЛрдВ рд╕реЗ рдпреБрдХреНрдд рдПрдХ рд╕рд░рд▓ рдЬрд┐рдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рд▓рд┐рдЦреЗрдВред рдХреЛрдб hwzip.c рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ ред

рд╣рдо рд╕рд╛рдзрд╛рд░рдг рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдореИрдХреНрд░реЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЪреЗрдХ рдХрд┐рдП рдЧрдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрди рдХреЗ рд▓рд┐рдП рдХрдИ рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдп рдХрд░реЗрдВрдЧреЗ:

#define PERROR_IF(cond, msg) if (cond) { perror(msg); exit(1); }

static void *xmalloc(size_t size)
{
        void *ptr = malloc(size);
        PERROR_IF(ptr == NULL, "malloc");
        return ptr;
}

static void *xrealloc(void *ptr, size_t size)
{
        ptr = realloc(ptr, size);
        PERROR_IF(ptr == NULL, "realloc");
        return ptr;
}

рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреНрдп рджреЛ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

static uint8_t *read_file(const char *filename, size_t *file_sz)
{
        FILE *f;
        uint8_t *buf;
        size_t buf_cap;

        f = fopen(filename, "rb");
        PERROR_IF(f == NULL, "fopen");

        buf_cap = 4096;
        buf = xmalloc(buf_cap);

        *file_sz = 0;
        while (feof(f) == 0) {
                if (buf_cap - *file_sz == 0) {
                        buf_cap *= 2;
                        buf = xrealloc(buf, buf_cap);
                }

                *file_sz += fread(&buf[*file_sz], 1, buf_cap - *file_sz, f);
                PERROR_IF(ferror(f), "fread");
        }

        PERROR_IF(fclose(f) != 0, "fclose");
        return buf;
}

static void write_file(const char *filename, const uint8_t *data, size_t n)
{
        FILE *f;

        f = fopen(filename, "wb");
        PERROR_IF(f == NULL, "fopen");
        PERROR_IF(fwrite(data, 1, n, f) != n, "fwrite");
        PERROR_IF(fclose(f) != 0, "fclose");
}

рд╣рдорд╛рд░рд╛ рдЬрд╝рд┐рдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рддреАрди рдХрд╛рд░реНрдп рдХрд░ рд╕рдХрддрд╛ рд╣реИ: рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреА рдПрдХ рд╕реВрдЪреА рдмрдирд╛рдПрдБ рдФрд░ рдЙрд╕реЗ рдирд┐рдХрд╛рд▓реЗрдВ, рд╕рд╛рде рд╣реА рд╕рд╛рде рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓реЗрдВ рдмрдирд╛рдПрдБред рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХрд╣реАрдВ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИ:

static void list_zip(const char *filename)
{
        uint8_t *zip_data;
        size_t zip_sz;
        zip_t z;
        zipiter_t it;
        zipmemb_t m;

        printf("Listing ZIP archive: %s\n\n", filename);

        zip_data = read_file(filename, &zip_sz);

        if (!zip_read(&z, zip_data, zip_sz)) {
                printf("Failed to parse ZIP file!\n");
                exit(1);
        }

        if (z.comment_len != 0) {
                printf("%.*s\n\n", (int)z.comment_len, z.comment);
        }

        for (it = z.members_begin; it != z.members_end; it = m.next) {
                m = zip_member(&z, it);
                printf("%.*s\n", (int)m.name_len, m.name);
        }

        printf("\n");

        free(zip_data);
}

рдирд┐рд╖реНрдХрд░реНрд╖рдг рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИред рд╣рдо рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдХреЗ рд╢реВрдиреНрдп рд╕рдорд╛рдкреНрддрд┐ рдХреЗ рд▓рд┐рдП рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ (рдЗрд╕реЗ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП fopen) рдФрд░ рдЕрдирдкреИрдХрд┐рдВрдЧ:

static char *terminate_str(const char *str, size_t n)
{
        char *p = xmalloc(n + 1);
        memcpy(p, str, n);
        p[n] = '\0';
        return p;
}

static uint8_t *inflate_member(const zipmemb_t *m)
{
        uint8_t *p;
        size_t src_used, dst_used;

        assert(m->method == ZIP_DEFLATED);

        p = xmalloc(m->uncomp_size);

        if (hwinflate(m->comp_data, m->comp_size, &src_used, p, m->uncomp_size,
                      &dst_used) != HWINF_OK) {
                free(p);
                return NULL;
        }

        if (src_used != m->comp_size || dst_used != m->uncomp_size) {
                free(p);
                return NULL;
        }

        return p;
}

рд╣рдорд╛рд░рд╛ рдХрд╛рд░реНрдпрдХреНрд░рдо рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рднреА рд╕рдВрдЧреНрд░рд╣ рддрддреНрд╡ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдЧрд╛ред рдпрд╣ рддрдерд╛рдХрдерд┐рдд рдкрде рдЯреНрд░реИрд╡рд░реНрд╕рд▓ рд╣рдорд▓реЛрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ : рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рдмрд╛рд╣рд░ рд╕реЗ рдлрд╛рдЗрд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг рд╕рдВрдЧреНрд░рд╣ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред Info-ZIP FAQ рдореЗрдВ рд╡рд┐рд╡рд░рдг рдкрдврд╝реЗрдВ ред

static void extract_zip(const char *filename)
{
        uint8_t *zip_data;
        size_t zip_sz;
        zip_t z;
        zipiter_t it;
        zipmemb_t m;
        char *tname;
        uint8_t *inflated;
        const uint8_t *uncomp_data;

        printf("Extracting ZIP archive: %s\n\n", filename);

        zip_data = read_file(filename, &zip_sz);

        if (!zip_read(&z, zip_data, zip_sz)) {
                printf("Failed to read ZIP file!\n");
                exit(1);
        }

        if (z.comment_len != 0) {
                printf("%.*s\n\n", (int)z.comment_len, z.comment);
        }

        for (it = z.members_begin; it != z.members_end; it = m.next) {
                m = zip_member(&z, it);

                if (m.is_dir) {
                        printf(" (Skipping dir: %.*s)\n",
                               (int)m.name_len, m.name);
                        continue;
                }

                if (memchr(m.name, '/',  m.name_len) != NULL ||
                    memchr(m.name, '\\', m.name_len) != NULL) {
                        printf(" (Skipping file in dir: %.*s)\n",
                               (int)m.name_len, m.name);
                        continue;
                }

                assert(m.method == ZIP_STORED || m.method == ZIP_DEFLATED);
                printf(" %s: %.*s",
                       m.method == ZIP_STORED ? "Extracting" : " Inflating",
                       (int)m.name_len, m.name);
                fflush(stdout);

                if (m.method == ZIP_STORED) {
                        assert(m.uncomp_size == m.comp_size);
                        inflated = NULL;
                        uncomp_data = m.comp_data;
                } else {
                        inflated = inflate_member(&m);
                        if (inflated == NULL) {
                                printf("Error: inflation failed!\n");
                                exit(1);
                        }
                        uncomp_data = inflated;
                }

                if (crc32(uncomp_data, m.uncomp_size) != m.crc32) {
                        printf("Error: CRC-32 mismatch!\n");
                        exit(1);
                }

                tname = terminate_str((const char*)m.name, m.name_len);
                write_file(tname, uncomp_data, m.uncomp_size);
                printf("\n");

                free(inflated);
                free(tname);
        }

        printf("\n");
        free(zip_data);
}

рдЬрд╝рд┐рдк рд╕рдВрдЧреНрд░рд╣ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрдирдкреБрдЯ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдкрдврд╝реЗрдВрдЧреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдлреАрдб рдХрд░реЗрдВрдЧреЗ zip_writeред рдЪреВрдВрдХрд┐ рдорд╛рдирдХ рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЖрдкрдХреЛ рдлрд╝рд╛рдЗрд▓ рд╕рдВрд╢реЛрдзрди рд╕рдордп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рд╣рдо рд╡рд░реНрддрдорд╛рди рд╕рдордп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ (рдореИрдВ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рд╣реЛрдорд╡рд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЫреЛрдбрд╝рддрд╛ рд╣реВрдВ)ред

void zip_callback(const char *filename, uint32_t size, uint32_t comp_size)
{
        bool deflated = comp_size < size;

        printf(" %s: %s", deflated ? "Deflated" : "  Stored", filename);
        if (deflated) {
                printf(" (%u%%)", 100 - 100 * comp_size / size);
        }
        printf("\n");
}

static void create_zip(const char *zip_filename, const char *comment,
                       uint16_t n, const char *const *filenames)
{
        time_t mtime;
        time_t *mtimes;
        uint8_t **file_data;
        uint32_t *file_sizes;
        size_t file_size, zip_size;
        uint8_t *zip_data;
        uint16_t i;

        printf("Creating ZIP archive: %s\n\n", zip_filename);

        if (comment != NULL) {
                printf("%s\n\n", comment);
        }

        mtime = time(NULL);

        file_data = xmalloc(sizeof(*file_data) * n);
        file_sizes = xmalloc(sizeof(*file_sizes) * n);
        mtimes = xmalloc(sizeof(*mtimes) * n);

        for (i = 0; i < n; i++) {
                file_data[i] = read_file(filenames[i], &file_size);
                if (file_size >= UINT32_MAX) {
                        printf("%s is too large!\n", filenames[i]);
                        exit(1);
                }
                file_sizes[i] = (uint32_t)file_size;
                mtimes[i] = mtime;
        }

        zip_size = zip_max_size(n, filenames, file_sizes, comment);
        if (zip_size == 0) {
                printf("zip writing not possible");
                exit(1);
        }

        zip_data = xmalloc(zip_size);
        zip_size = zip_write(zip_data, n, filenames,
                             (const uint8_t *const *)file_data,
                             file_sizes, mtimes, comment, zip_callback);

        write_file(zip_filename, zip_data, zip_size);
        printf("\n");

        free(zip_data);
        for (i = 0; i < n; i++) {
                free(file_data[i]);
        }
        free(mtimes);
        free(file_sizes);
        free(file_data);
}

рдЕрдВрдд рдореЗрдВ, рдпрд╣ mainрдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдХреЗ рддрд░реНрдХреЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдирд┐рд░реНрдгрдп рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ:

static void print_usage(const char *argv0)
{
        printf("Usage:\n\n");
        printf("  %s list <zipfile>\n", argv0);
        printf("  %s extract <zipfile>\n", argv0);
        printf("  %s create <zipfile> [-c <comment>] <files...>\n", argv0);
        printf("\n");
}

int main(int argc, char **argv) {
        printf("\n");
        printf("HWZIP " VERSION " -- A very simple ZIP program ");
        printf("from https://www.hanshq.net/zip.html\n");
        printf("\n");

        if (argc == 3 && strcmp(argv[1], "list") == 0) {
                list_zip(argv[2]);
        } else if (argc == 3 && strcmp(argv[1], "extract") == 0) {
                extract_zip(argv[2]);
        } else if (argc >= 3 && strcmp(argv[1], "create") == 0) {
                if (argc >= 5 && strcmp(argv[3], "-c") == 0) {
                        create_zip(argv[2], argv[4], (uint16_t)(argc - 5),
                                   (const char *const *)&argv[5]);
                } else {
                        create_zip(argv[2], NULL, (uint16_t)(argc - 3),
                                   (const char *const *)&argv[3]);
                }
        } else {
                print_usage(argv[0]);
                return 1;
        }

        return 0;
}

рдПрдХрддреНрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢


рд╕реНрд░реЛрдд рдлрд╝рд╛рдЗрд▓реЛрдВ рдХрд╛ рдПрдХ рдкреВрд░рд╛ рд╕реЗрдЯ hwzip-1.0.zip рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ ред рд▓рд┐рдирдХреНрд╕ рдпрд╛ рдореИрдХ рдХреЗ рддрд╣рдд HWZip рдХреЛ рдХреИрд╕реЗ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ:

$ clang generate_tables.c && ./a.out > tables.c
$ clang -O3 -DNDEBUG -march=native -o hwzip crc32.c deflate.c huffman.c \
        hwzip.c lz77.c tables.c zip.c

рд╡рд┐рдВрдбреЛрдЬ рдкрд░, рдбреЗрд╡рд▓рдкрд░ рдХреЗ рдкреНрд░реЙрдореНрдкреНрдЯ рдкрд░ рд╡рд┐рдЬреБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ рдореЗрдВ (рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╡рд┐рдЬреБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ рдирд╣реАрдВ рд╣реИ, рддреЛ рдмрд┐рд▓реНрдб рдЯреВрд▓реНрд╕ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ ):

cl /TC generate_tables.c && generate_tables > tables.c
cl /O2 /DNDEBUG /MT /Fehwzip.exe /TC crc32.c deflate.c huffman.c hwzip.c
        lz77.c tables.c zip.c /link setargv.obj

рд╡рд╛рдЗрд▓реНрдбрдХрд╛рд░реНрдб рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рддрд░реНрдХреЛрдВ рдХреЗ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд▓рд┐рдП Setargv.obj ред)

рдирд┐рд╖реНрдХрд░реНрд╖


рдпрд╣ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рддреЗрдЬреА рд╕реЗ рдФрд░ рдзреАрд░реЗ-рдзреАрд░реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣реА рд╣реИред рдкрдЪрд╛рд╕ рдФрд░ рд╕рддреНрддрд░ рдХреЗ рджрд╢рдХ рдХреА рддрдХрдиреАрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ 30 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдЬрд┐рдк рдкреНрд░рд╛рд░реВрдк рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдФрд░ рд╣рд╛рд▓рд╛рдВрдХрд┐ рддрдм рд╕реЗ рдмрд╣реБрдд рдХреБрдЫ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ, рдЬрд╝рд┐рдк рдлрд╛рдЗрд▓реЗрдВ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╡рд╣реА рдмрдиреА рд╣реБрдИ рд╣реИрдВ рдФрд░ рдЖрдЬ рдкрд╣рд▓реЗ рд╕реЗ рдХрд╣реАрдВ рдЕрдзрд┐рдХ рдЖрдо рд╣реИрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ рдХрд┐ рд╡реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред

рдЕрднреНрдпрд╛рд╕


  • HWZip рдХреЛ рдЙрд╕ рд╕рдордп рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдХрд░реЗрдВ, рдЬрдм рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордп рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдмрдЬрд╛рдп рд╡рд░реНрддрдорд╛рди рд╕рдордп рдХреЗ рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд▓рд┐рдирдХреНрд╕ рдкрд░ рдореИрдХ (2) рдпрд╛ рдореИрдХ рдФрд░ рд╡рд┐рдВрдбреЛрдЬ рдкрд░ GetFileTime рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ ред рдпрд╛ рдПрдХ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдзреНрд╡рдЬ рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдлрд╝рд╛рдЗрд▓ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдордп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
  • gzip-. тАФ , Deflate ( ). RFC 1952.
  • Zip- . HWZip , read_file mmap(2) Linux Mac CreateFileMapping Windows.
  • HWZip , Zip64. appnote.txt.



All Articles