rlc: Move the ack state array into a separate class that can be tested
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 4319c49..1a2aa0f 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -31,3 +31,9 @@
 
 	return block;
 }
+
+void gprs_rlc_v_b::reset()
+{
+	for (size_t i = 0; i < ARRAY_SIZE(m_v_b); ++i)
+		mark_invalid(i);
+}
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 19a0d81..ab77d93 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -895,12 +895,11 @@
 	for (bsn = dir.dl.v_a; bsn != dir.dl.v_s; 
 	     bsn = (bsn + 1) & mod_sns) {
 		index = (bsn & mod_sns_half);
-		if (dir.dl.v_b[index] == 'N'
-		 || dir.dl.v_b[index] == 'X') {
+		if (dir.dl.v_b.is_nacked(index) || dir.dl.v_b.is_resend(index)) {
 			LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n",
 				bsn);
 			/* re-send block with negative aknowlegement */
-			dir.dl.v_b[index] = 'U'; /* unacked */
+			dir.dl.v_b.mark_unacked(index);
 			bts->rlc_resent();
 			return create_dl_acked_block(fn, ts, index, first_fin_ack);
 		}
@@ -941,9 +940,9 @@
 		for (bsn = dir.dl.v_a; bsn != dir.dl.v_s;
 		     bsn = (bsn + 1) & mod_sns) {
 			index = (bsn & mod_sns_half);
-			if (dir.dl.v_b[index] == 'U') {
+			if (dir.dl.v_b.is_unacked(index)) {
 				/* mark to be re-send */
-				dir.dl.v_b[index] = 'X';
+				dir.dl.v_b.mark_resend(index);
 				resend++;
 			}
 		}
@@ -1111,7 +1110,7 @@
 #warning "move this up?"
 	m_rlc.blocks[index].len = block_length;
 	/* raise send state and set ack state array */
-	dir.dl.v_b[index] = 'U'; /* unacked */
+	dir.dl.v_b.mark_unacked(index);
 	dir.dl.v_s = (dir.dl.v_s + 1) & mod_sns; /* inc send state */
 
 	return create_dl_acked_block(fn, ts, index, first_fin_ack);
@@ -1463,14 +1462,13 @@
 			if (bit) {
 				LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
 					"ack for BSN=%d\n", bsn);
-				if (dir.dl.v_b[bsn & mod_sns_half]
-								!= 'A')
+				if (!dir.dl.v_b.is_acked(bsn & mod_sns_half))
 					received++;
-				dir.dl.v_b[bsn & mod_sns_half] = 'A';
+				dir.dl.v_b.mark_acked(bsn & mod_sns_half);
 			} else {
 				LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
 					"NACK for BSN=%d\n", bsn);
-				dir.dl.v_b[bsn & mod_sns_half] = 'N';
+				dir.dl.v_b.mark_nacked(bsn & mod_sns_half);
 				bts->rlc_nacked();
 				lost++;
 			}
@@ -1481,11 +1479,9 @@
 		/* raise V(A), if possible */
 		for (i = 0, bsn = dir.dl.v_a; bsn != dir.dl.v_s;
 		     i++, bsn = (bsn + 1) & mod_sns) {
-			if (dir.dl.v_b[bsn & mod_sns_half] == 'A') {
-				dir.dl.v_b[bsn & mod_sns_half] = 'I';
-					/* mark invalid */
-				dir.dl.v_a = (dir.dl.v_a + 1)
-								& mod_sns;
+			if (dir.dl.v_b.is_acked(bsn & mod_sns_half)) {
+				dir.dl.v_b.mark_invalid(bsn & mod_sns_half);
+				dir.dl.v_a = (dir.dl.v_a + 1) & mod_sns;
 			} else
 				break;
 		}
@@ -1493,7 +1489,7 @@
 		/* show receive state array in debug (V(A)..V(S)-1) */
 		for (i = 0, bsn = dir.dl.v_a; bsn != dir.dl.v_s;
 		     i++, bsn = (bsn + 1) & mod_sns) {
-			show_v_b[i] = dir.dl.v_b[bsn & mod_sns_half];
+			show_v_b[i] = dir.dl.v_b.state(bsn & mod_sns_half);
 			if (show_v_b[i] == 0)
 				show_v_b[i] = ' ';
 		}
@@ -1517,7 +1513,7 @@
 	/* range V(A)..V(S)-1 */
 	for (bsn = dir.dl.v_a; bsn != dir.dl.v_s;
 	     bsn = (bsn + 1) & mod_sns) {
-		if (dir.dl.v_b[bsn & mod_sns_half] != 'A')
+		if (!dir.dl.v_b.is_acked(bsn & mod_sns_half))
 			received++;
 	}
 
@@ -1852,6 +1848,7 @@
 
 	/* reset rlc states */
 	memset(&dir.dl, 0, sizeof(dir.dl));
+	dir.dl.v_b.reset();
 
 	/* keep to flags */
 	state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
diff --git a/src/tbf.h b/src/tbf.h
index 0eacec5..a25f62d 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -102,6 +102,29 @@
 	gprs_rlc_data blocks[RLC_MAX_SNS/2];
 };
 
+struct gprs_rlc_v_b {
+	bool is_nacked(int index) const;
+	bool is_acked(int index) const;
+	bool is_unacked(int index) const;
+	bool is_resend(int index) const;
+
+	char state(int index) const;
+
+	void mark_unacked(int index);
+	void mark_nacked(int index);
+	void mark_acked(int index);
+	void mark_resend(int index);
+	void mark_invalid(int index);
+
+	void reset();
+
+private:
+	bool is_state(int index, const char state) const;
+	void mark(int index, const char state);
+
+	char m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */
+};
+
 struct gprs_rlcmac_tbf {
 
 	static void free_all(struct gprs_rlcmac_trx *trx);
@@ -188,7 +211,7 @@
 			uint16_t bsn;	/* block sequence number */
 			uint16_t v_s;	/* send state */
 			uint16_t v_a;	/* ack state */
-			char v_b[RLC_MAX_SNS/2]; /* acknowledge state array */
+			gprs_rlc_v_b v_b;
 			int32_t tx_counter; /* count all transmitted blocks */
 			uint8_t wait_confirm; /* wait for CCCH IMM.ASS cnf */
 		} dl;
@@ -324,3 +347,63 @@
 }
 
 const char *tbf_name(gprs_rlcmac_tbf *tbf);
+
+inline bool gprs_rlc_v_b::is_state(int index, const char type) const
+{
+	return m_v_b[index] == type;
+}
+
+inline void gprs_rlc_v_b::mark(int index, const char type)
+{
+	m_v_b[index] = type;
+}
+
+inline char gprs_rlc_v_b::state(int index) const
+{
+	return m_v_b[index];
+}
+
+inline bool gprs_rlc_v_b::is_nacked(int index) const
+{
+	return is_state(index, 'N');
+}
+
+inline bool gprs_rlc_v_b::is_acked(int index) const
+{
+	return is_state(index, 'A');
+}
+
+inline bool gprs_rlc_v_b::is_unacked(int index) const
+{
+	return is_state(index, 'U');
+}
+
+inline bool gprs_rlc_v_b::is_resend(int index) const
+{
+	return is_state(index, 'X');
+}
+
+inline void gprs_rlc_v_b::mark_resend(int index)
+{
+	return mark(index, 'X');
+}
+
+inline void gprs_rlc_v_b::mark_unacked(int index)
+{
+	return mark(index, 'U');
+}
+
+inline void gprs_rlc_v_b::mark_acked(int index)
+{
+	return mark(index, 'A');
+}
+
+inline void gprs_rlc_v_b::mark_nacked(int index)
+{
+	return mark(index, 'N');
+}
+
+inline void gprs_rlc_v_b::mark_invalid(int index)
+{
+	return mark(index, 'I');
+}