summaryrefslogtreecommitdiff
path: root/cesar/mac/pbproc/src/sacki_dec.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/mac/pbproc/src/sacki_dec.c')
-rw-r--r--cesar/mac/pbproc/src/sacki_dec.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/cesar/mac/pbproc/src/sacki_dec.c b/cesar/mac/pbproc/src/sacki_dec.c
new file mode 100644
index 0000000000..11164565e1
--- /dev/null
+++ b/cesar/mac/pbproc/src/sacki_dec.c
@@ -0,0 +1,111 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sacki_dec.c
+ * \brief SACKI decompression.
+ * \ingroup mac_pbproc
+ */
+#include "common/std.h"
+
+#include "inc/sacki_dec.h"
+
+#include "pbproc_sacki_dec_tables.h"
+
+#ifdef PBPROC_SACKI_DEC_DEBUG
+# undef PBPROC_SACKI_DEC_DEBUG
+void
+pbproc_sacki_dec_debug (uint eat, uint prod, uint nok0, uint nok1, uint nok2);
+# define PBPROC_SACKI_DEC_DEBUG(eat, prod, nok0, nok1, nok2) \
+ pbproc_sacki_dec_debug ((eat), (prod), (nok0), (nok1), (nok2))
+#else
+# define PBPROC_SACKI_DEC_DEBUG(eat, prod, nok0, nok1, nok2)
+#endif
+
+uint
+pbproc_sacki_dec_process (u32 si[3], uint sil, uint pbl,
+ void *user, pbproc_sacki_dec_nok_cb_t nok_cb)
+{
+ uint pbs;
+ u32 si0, si1, si2;
+ /* Load cache. */
+ si0 = si[0];
+ si1 = si[1];
+ si2 = si[2];
+ /* Fast decompression. */
+ pbs = 0;
+ while (sil >= 8)
+ {
+ /* Lookup. */
+ uint eat = sack_dec_fast[si0 & 0xff].eat;
+ uint prod = sack_dec_fast[si0 & 0xff].prod;
+ if (prod > pbl)
+ break;
+ uint nok0 = sack_dec_fast[si0 & 0xff].nok0;
+ uint nok1 = sack_dec_fast[si0 & 0xff].nok1;
+ uint nok2 = sack_dec_fast[si0 & 0xff].nok2;
+ PBPROC_SACKI_DEC_DEBUG (eat, prod, nok0, nok1, nok2);
+ /* Call callback. */
+ if (nok0 != SACK_DEC_FAST_NOK_UNDEF)
+ {
+ nok_cb (user, pbs + nok0, 1);
+ if (nok1 != SACK_DEC_FAST_NOK_UNDEF)
+ {
+ nok_cb (user, pbs + nok1, 1);
+ if (nok2 != SACK_DEC_FAST_NOK_UNDEF)
+ {
+ nok_cb (user, pbs + nok2, 1);
+ }
+ }
+ }
+ /* Advance. */
+ si0 = si1 << (32 - eat) | si0 >> eat;
+ si1 = si2 << (32 - eat) | si1 >> eat;
+ si2 = si2 >> eat;
+ sil -= eat;
+ pbs += prod;
+ pbl -= prod;
+ }
+ /* Slow decompression. */
+ while (pbl)
+ {
+ /* Lookup. */
+ uint eat = sack_dec_slow[si0 & 0x3f].eat;
+ if (eat > sil)
+ break;
+ uint prod = sack_dec_slow[si0 & 0x3f].prod;
+ uint nok0 = sack_dec_slow[si0 & 0x3f].nok0;
+ uint nok1 = sack_dec_slow[si0 & 0x3f].nok1;
+ PBPROC_SACKI_DEC_DEBUG (eat, prod, nok0, nok1, 7);
+ prod = MIN (prod, pbl);
+ /* Call callback. */
+ if (nok0 != SACK_DEC_SLOW_NOK_UNDEF && nok0 < pbl)
+ {
+ nok_cb (user, pbs + nok0, 1);
+ if (nok1 != SACK_DEC_SLOW_NOK_UNDEF && nok1 < pbl)
+ {
+ nok_cb (user, pbs + nok1, 1);
+ }
+ }
+ /* Advance. */
+ si0 = si1 << (32 - eat) | si0 >> eat;
+ si1 = si2 << (32 - eat) | si1 >> eat;
+ si2 = si2 >> eat;
+ sil -= eat;
+ pbs += prod;
+ pbl -= prod;
+ }
+ /* Extra PB. */
+ if (pbl)
+ nok_cb (user, pbs, pbl);
+ /* Store cache. */
+ si[0] = si0;
+ si[1] = si1;
+ si[2] = si2;
+ return sil;
+}
+