Advertisement
Guest User

Untitled

a guest
Jun 24th, 2017
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.62 KB | None | 0 0
  1. ' huffman more optimized byte oriented version, 1st november 2010
  2.  
  3. #include once "crt.bi"
  4.  
  5. type tree_t
  6. isinternal as integer
  7. c as ubyte
  8. weight as uinteger
  9. l as tree_t ptr
  10. r as tree_t ptr
  11. code as uinteger
  12. code_len as uinteger
  13. declare destructor _
  14. ( _
  15. )
  16. end type
  17.  
  18. destructor tree_t _
  19. ( _
  20. )
  21.  
  22. delete l
  23. delete r
  24.  
  25. end destructor
  26.  
  27. function tree_add _
  28. ( _
  29. byval root as tree_t ptr ptr, _
  30. byval c as ubyte _
  31. ) as tree_t ptr
  32.  
  33. if root[c] = NULL then
  34. root[c] = new tree_t
  35. root[c]->c = c
  36. end if
  37.  
  38. root[c]->weight += 1
  39.  
  40. function = root[c]
  41.  
  42. end function
  43.  
  44. function nodecmp cdecl _
  45. ( _
  46. byval l as tree_t ptr ptr, _
  47. byval r as tree_t ptr ptr _
  48. ) as integer
  49.  
  50. if (*l)->weight < (*r)->weight then
  51. function = 1
  52. elseif (*l)->weight > (*r)->weight then
  53. function = -1
  54. end if
  55.  
  56. end function
  57.  
  58. ' This is the first stage of building the huffman tree
  59. ' we take the input array, and build the tree itself, inserting internal nodes
  60. ' in the right places
  61. function buildhuff _
  62. ( _
  63. byval array as tree_t ptr ptr, _
  64. byval array_len as integer _
  65. ) as tree_t ptr
  66.  
  67. dim as tree_t ptr queueA(0 to array_len - 1)
  68. dim as tree_t ptr queueB(0 to array_len - 1)
  69. dim as integer queueA_len
  70. dim as integer queueB_len
  71.  
  72. for i as integer = 0 to array_len - 1
  73. queueA(queueA_len) = array[i]
  74. queueA_len += 1
  75. next i
  76.  
  77. dim as tree_t ptr huffroot
  78.  
  79. while (queueA_len > 0) or (queueB_len > 0)
  80. dim as tree_t ptr l, r
  81.  
  82. if (queueA_len > 0) and (queueB_len > 0) then
  83. if queueA(queueA_len - 1)->weight <= queueB(queueB_len - 1)->weight then
  84. l = queueA(queueA_len - 1)
  85. queueA_len -= 1
  86. elseif queueA(queueA_len - 1)->weight > queueB(queueB_len - 1)->weight then
  87. l = queueB(queueB_len - 1)
  88. queueB_len -= 1
  89. end if
  90. elseif queueA_len > 0 then
  91. l = queueA(queueA_len - 1)
  92. queueA_len -= 1
  93. elseif queueB_len > 0 then
  94. l = queueB(queueB_len - 1)
  95. queueB_len -= 1
  96. end if
  97.  
  98. if (queueA_len > 0) and (queueB_len > 0) then
  99. if queueA(queueA_len - 1)->weight <= queueB(queueB_len - 1)->weight then
  100. r = queueA(queueA_len - 1)
  101. queueA_len -= 1
  102. elseif queueA(queueA_len - 1)->weight > queueB(queueB_len - 1)->weight then
  103. r = queueB(queueB_len - 1)
  104. queueB_len -= 1
  105. end if
  106. elseif queueA_len > 0 then
  107. r = queueA(queueA_len - 1)
  108. queueA_len -= 1
  109. elseif queueB_len > 0 then
  110. r = queueB(queueB_len - 1)
  111. queueB_len -= 1
  112. end if
  113.  
  114. if r = NULL then
  115. huffroot = l
  116. exit while
  117. end if
  118.  
  119. dim as tree_t ptr node
  120.  
  121. node = new tree_t( -1, 0, l->weight + r->weight, l, r )
  122.  
  123. queueB_len += 1
  124.  
  125. for i as integer = queueB_len - 1 to 1 step -1
  126. queueB(i) = queueB(i - 1)
  127. next i
  128.  
  129. queueB(0) = node
  130. wend
  131.  
  132. function = huffroot
  133.  
  134. end function
  135.  
  136. ' This is the second stage of building the huffman tree
  137. ' we walk the tree, generating the codes
  138. sub buildhuff2 _
  139. ( _
  140. byval node as tree_t ptr, _
  141. byval code as uinteger = 0, _
  142. byval code_len as uinteger = 0 _
  143. )
  144.  
  145. if node = NULL then exit sub
  146.  
  147. if node->isinternal = 0 then
  148. node->code = code
  149. node->code_len = code_len
  150. else
  151. buildhuff2( node->l, code or (0 shl code_len), code_len + 1 )
  152. buildhuff2( node->r, code or (1 shl code_len), code_len + 1 )
  153. end if
  154.  
  155. end sub
  156.  
  157. #macro readbit( in_p, in_size, in_pos, b, bitbuffer, bitbuffer_pos )
  158. if bitbuffer_pos = 0 then
  159. bitbuffer = *cast( uinteger ptr, @in_p[in_pos] )
  160. in_pos += 4
  161. end if
  162.  
  163. b = (bitbuffer shr bitbuffer_pos) and 1
  164. bitbuffer_pos = (bitbuffer_pos + 1) and 31 ' mod 32
  165. #endmacro
  166.  
  167. sub decompress_loop _
  168. ( _
  169. byval in_p as ubyte ptr, _
  170. byval in_size as uinteger, _
  171. byval in_pos as uinteger, _
  172. byval out_p as ubyte ptr, _
  173. byval todo as uinteger, _
  174. byval huffroot as tree_t ptr _
  175. )
  176.  
  177. dim as uinteger bitbuffer
  178. dim as uinteger bitbuffer_pos
  179. dim as uinteger out_pos
  180.  
  181. while todo
  182. dim as tree_t ptr curr = huffroot
  183.  
  184. while curr->isinternal
  185. dim as uinteger b = any
  186.  
  187. readbit( in_p, in_size, in_pos, b, bitbuffer, bitbuffer_pos )
  188.  
  189. if b = 1 then
  190. curr = curr->r
  191. else
  192. curr = curr->l
  193. end if
  194. wend
  195.  
  196. *cast( ubyte ptr, @out_p[out_pos] ) = curr->c
  197. out_pos += 1
  198. todo -= 1
  199. wend
  200.  
  201. end sub
  202.  
  203. sub huff_decode_mem _
  204. ( _
  205. byval in_p as ubyte ptr, _
  206. byval in_size as uinteger, _
  207. byval out_p as ubyte ptr _
  208. )
  209.  
  210. dim as uinteger array_len
  211. dim as uinteger todo
  212. dim as uinteger in_pos
  213.  
  214. todo = *cast( uinteger ptr, @in_p[in_pos] )
  215. in_pos += 4
  216.  
  217. array_len = *cast( uinteger ptr, @in_p[in_pos] )
  218. in_pos += 4
  219.  
  220. dim as tree_t ptr ptr array = callocate( array_len * sizeof( tree_t ptr ) )
  221.  
  222. for i as uinteger = 0 to array_len - 1
  223. array[i] = new tree_t
  224. array[i]->weight = *cast( uinteger ptr, @in_p[in_pos] )
  225. in_pos += 4
  226. array[i]->c = *cast( ubyte ptr, @in_p[in_pos] )
  227. in_pos += 1
  228. next i
  229.  
  230. dim as tree_t ptr huffroot = buildhuff( array, array_len )
  231.  
  232. buildhuff2( huffroot )
  233.  
  234. decompress_loop( in_p, in_size, in_pos, out_p, todo, huffroot )
  235.  
  236. deallocate( array )
  237.  
  238. delete huffroot
  239.  
  240. end sub
  241.  
  242. #macro writebits( out_p, out_size, out_pos, code, code_len, bitbuffer, bitbuffer_pos )
  243. for i as integer = 0 to code_len - 1
  244. dim as integer cb = (code shr i) and 1
  245. bitbuffer or= cb shl bitbuffer_pos
  246. bitbuffer_pos = (bitbuffer_pos + 1) and 31 ' mod 32
  247. if bitbuffer_pos = 0 then
  248. *cast( uinteger ptr, @out_p[out_pos] ) = bitbuffer
  249. out_pos += 4
  250. bitbuffer = 0
  251. end if
  252. next i
  253. #endmacro
  254.  
  255. function emit_compressed _
  256. ( _
  257. byval out_p as ubyte ptr, _
  258. byval out_size as uinteger, _
  259. byval out_pos as uinteger, _
  260. byval root as tree_t ptr ptr, _
  261. byval in_p as ubyte ptr, _
  262. byval in_size as uinteger _
  263. ) as integer
  264.  
  265. dim as uinteger bitbuffer
  266. dim as uinteger bitbuffer_pos
  267.  
  268. for i as uinteger = 0 to in_size - 1
  269. dim as tree_t ptr node = root[in_p[i]]
  270. writebits( out_p, out_size, out_pos, node->code, node->code_len, bitbuffer, bitbuffer_pos )
  271. next i
  272.  
  273. if bitbuffer_pos then
  274. *cast( uinteger ptr, @out_p[out_pos] ) = bitbuffer
  275. out_pos += 4
  276. bitbuffer_pos = 0
  277. bitbuffer = 0
  278. end if
  279.  
  280. function = out_pos
  281.  
  282. end function
  283.  
  284. function huff_encode_mem _
  285. ( _
  286. byval in_p as ubyte ptr, _
  287. byval in_size as uinteger, _
  288. byval out_p as ubyte ptr, _
  289. byval out_size as uinteger _
  290. ) as integer
  291.  
  292. dim as uinteger array_len
  293. dim as tree_t ptr root(0 to 255)
  294. dim as uinteger out_pos
  295.  
  296. for i as uinteger = 0 to in_size - 1
  297. tree_add( @root(0), in_p[i] )
  298. next i
  299.  
  300. *cast( uinteger ptr, @out_p[out_pos] ) = in_size
  301. out_pos += 4
  302.  
  303. dim as tree_t ptr ptr array = callocate( 256 * sizeof( tree_t ptr ) )
  304.  
  305. for i as integer = 0 to 255
  306. if root(i) then
  307. array[array_len] = root(i)
  308. array_len += 1
  309. end if
  310. next i
  311.  
  312. qsort( array, array_len, sizeof( tree_t ptr ), cast( any ptr, @nodecmp ) )
  313.  
  314. dim as tree_t ptr huffroot = buildhuff( array, array_len )
  315.  
  316. buildhuff2( huffroot )
  317.  
  318. *cast( uinteger ptr, @out_p[out_pos] ) = array_len
  319. out_pos += 4
  320.  
  321. for i as uinteger = 0 to array_len - 1
  322. *cast( uinteger ptr, @out_p[out_pos] ) = array[i]->weight
  323. out_pos += 4
  324. *cast( ubyte ptr, @out_p[out_pos] ) = array[i]->c
  325. out_pos += 1
  326. next i
  327.  
  328. out_pos = emit_compressed( out_p, out_size, out_pos, @root(0), in_p, in_size )
  329.  
  330. deallocate( array )
  331.  
  332. delete huffroot
  333.  
  334. function = out_pos
  335.  
  336. end function
  337.  
  338. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  339.  
  340. dim as FILE ptr hfile_out
  341. dim as integer reverse
  342. dim as double t1
  343.  
  344. reverse = (command( 1 ) = "-r")
  345.  
  346. t1 = timer( )
  347. if reverse then
  348. dim as string in_s
  349. dim as ubyte ptr out_p
  350. dim as uinteger out_size
  351.  
  352. open command( 2 ) for binary access read as #1
  353. in_s = input( lof( 1 ), 1 )
  354. close #1
  355.  
  356. out_size = *cast( uinteger ptr, @in_s[0] )
  357. out_p = callocate( out_size )
  358.  
  359. huff_decode_mem( @in_s[0], len( in_s ), out_p )
  360.  
  361. open command( 3 ) for binary access write as #1
  362. put #1, , *out_p, out_size
  363. close #1
  364.  
  365. deallocate( out_p )
  366. else
  367. dim as string in_s
  368. dim as uinteger out_len
  369.  
  370. open command( 1 ) for binary access read as #1
  371. in_s = input( lof( 1 ), 1 )
  372. close #1
  373.  
  374. dim as uinteger out_size = len( in_s ) * 2
  375. dim as ubyte ptr out_p = callocate( out_size )
  376.  
  377. out_len = huff_encode_mem( @in_s[0], len( in_s ), out_p, out_size )
  378.  
  379. open command( 2 ) for binary access write as #1
  380. put #1, , *out_p, out_len
  381. close #1
  382.  
  383. deallocate( out_p )
  384. end if
  385. t1 = timer( ) - t1
  386.  
  387. if reverse then
  388. print "decompressed " & command( 2 ) & " in " & int( t1 * 1000 ) & "ms"
  389. else
  390. print "compressed " & command( 1 ) & " in " & int( t1 * 1000 ) & "ms"
  391. end if
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement