summaryrefslogtreecommitdiffstats
path: root/gisi/iter.c
diff options
context:
space:
mode:
authorPekka Pessi <Pekka.Pessi@nokia.com>2009-10-08 19:47:15 +0300
committerAki Niemi <aki.niemi@nokia.com>2009-10-09 12:54:04 +0300
commitd1d870ba7a037773ae731a21b9707df8dcb47992 (patch)
tree793bcae692a3e9aab6f1839b0a762a702cd04cf8 /gisi/iter.c
parent8778826638d3f563b7a26746f05e2d0c47a9e238 (diff)
downloadofono-d1d870ba7a037773ae731a21b9707df8dcb47992.tar.bz2
Refactor subblock iterators.
Always initialize iterators. Try to avoid pointer arithmetics on NULL; in other words, move all pointer arithmetics inside g_isi_sb_iter_init(). There are 4 different ways for representing sub blocks in ISI message: - 8-bit sub_blocks count, 8-bit sub_block_id/sub_block_len - 16-bit sub_blocks count, 8-bit sub_block_id/sub_block_len - 8-bit sub_blocks count, 16-bit sub_block_id/sub_block_len - 16-bit sub_blocks count, 16-bit sub_block_id/sub_block_len The compact form g_isi_sb_iter_init() supports 8-bit sub_block count before start of the sub blocks themselves and 8-bit sub_block_id and sub_block_len. The full form g_isi_sb_iter_init_full() with explicit longhdr and sub_block count supports all other cases.
Diffstat (limited to 'gisi/iter.c')
-rw-r--r--gisi/iter.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/gisi/iter.c b/gisi/iter.c
index 5532107a..3764e2d0 100644
--- a/gisi/iter.c
+++ b/gisi/iter.c
@@ -47,22 +47,44 @@ static inline void bcd_to_mccmnc(const uint8_t *restrict bcd, char *mcc, char *m
mnc[3] = '\0';
}
-bool g_isi_sb_iter_init(const void *restrict data, size_t len,
- GIsiSubBlockIter *iter, bool longhdr)
+void g_isi_sb_iter_init_full(GIsiSubBlockIter *iter,
+ const void *restrict data,
+ size_t len,
+ size_t used,
+ bool longhdr,
+ uint16_t sub_blocks)
{
- if (!iter || !data || len == 0)
- return false;
-
- iter->start = (uint8_t *)data;
+ if (!data)
+ len = used = 0;
+ iter->start = (uint8_t *)data + used;
iter->end = iter->start + len;
iter->longhdr = longhdr;
+ iter->sub_blocks = len > used ? sub_blocks : 0;
+}
- return true;
+void g_isi_sb_iter_init(GIsiSubBlockIter *iter,
+ const void *restrict data,
+ size_t len,
+ size_t used)
+{
+
+ if (!data)
+ len = used = 0;
+ iter->start = (uint8_t *)data + used;
+ iter->end = iter->start + len;
+ iter->longhdr = false;
+ iter->sub_blocks = len > used ? iter->start[-1] : 0;
}
bool g_isi_sb_iter_is_valid(const GIsiSubBlockIter *iter)
{
- if (!iter || iter->end - iter->start < (iter->longhdr ? 4 : 2))
+ if (!iter)
+ return false;
+
+ if (iter->sub_blocks == 0)
+ return false;
+
+ if (iter->start + (iter->longhdr ? 4 : 2) > iter->end)
return false;
if (iter->start + g_isi_sb_iter_get_len(iter) > iter->end)
@@ -73,29 +95,24 @@ bool g_isi_sb_iter_is_valid(const GIsiSubBlockIter *iter)
int g_isi_sb_iter_get_id(const GIsiSubBlockIter *iter)
{
- if (iter->longhdr) {
- uint16_t *hdr = (uint16_t *)iter->start;
- return (int)ntohs(hdr[0]);
- }
-
+ if (iter->longhdr)
+ return (iter->start[0] << 8) | (iter->start[1]);
return iter->start[0];
}
size_t g_isi_sb_iter_get_len(const GIsiSubBlockIter *iter)
{
- if (iter->longhdr) {
- uint16_t *hdr = (uint16_t *)iter->start;
- return (size_t)ntohs(hdr[1]);
- }
+ if (iter->longhdr)
+ return (iter->start[2] << 8) | (iter->start[3]);
return iter->start[1];
}
bool g_isi_sb_iter_get_byte(const GIsiSubBlockIter *restrict iter, uint8_t *byte, int pos)
{
- if (pos > (int)g_isi_sb_iter_get_len(iter) || iter->start + pos > iter->end)
+ if ((size_t)(unsigned)pos > g_isi_sb_iter_get_len(iter) ||
+ iter->start + (unsigned)pos > iter->end)
return false;
-
*byte = iter->start[pos];
return true;
}
@@ -183,9 +200,14 @@ bool g_isi_sb_iter_next(GIsiSubBlockIter *iter)
if (len == 0)
len = iter->longhdr ? 4 : 2;
+ if (iter->sub_blocks == 0)
+ return false;
+
if (iter->start + len > iter->end)
return false;
iter->start += len;
+ iter->sub_blocks--;
+
return true;
}