1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2015-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8 9%% header 10 11/** @file dk4ahd.h ASCIIHex decoder. 12 13First initialize the decoder using the dk4ahex_dec_init() function. 14 15Add text characters using the dk4ahex_dec_add() function. 16The function returns DK4_EDSTM_ACCEPT if the text character was successfully 17stored in the decoder without completing a byte. 18The DK4_EDSTM_FINISHED return code indicates that a byte was finished, use 19dk4ahex_dec_output() to retrieve it. 20The DK4_EDSTM_STOP return code indicates that an end of data (EOD) marker 21was found. 22 23After feeding all text characters into the decoder use dk4ahex_dec_finish() 24to check whether there is an unprocessed half-byte stored. 25If the function returns DK4_EDSTM_FINISHED, use dk4ahex_dec_output() to 26retrieve the final byte. 27 28Note: The call to dk4ahex_dec_finish() is also necessary after 29obtaining DK4_EDSTM_STOP from dk4ahex_dec_add(). 30 31*/ 32 33 34#ifndef DK4CONF_H_INCLUDED 35#if DK4_BUILDING_DKTOOLS4 36#include "dk4conf.h" 37#else 38#include <dktools-4/dk4conf.h> 39#endif 40#endif 41 42#ifndef DK4ERROR_H_INCLUDED 43#if DK4_BUILDING_DKTOOLS4 44#include <libdk4base/dk4error.h> 45#else 46#include <dktools-4/dk4error.h> 47#endif 48#endif 49 50 51/** ASCII-Hex decoder. 52*/ 53typedef struct { 54 int cpos; /**< Current position. */ 55 unsigned char obyte; /**< Output byte. */ 56} dk4_ahex_dec_t; 57 58#ifdef __cplusplus 59extern "C" { 60#endif 61 62/** Initialize decoder. 63 @param dec Decoder to initialize. 64 @param erp Error report, may be NULL. 65*/ 66void 67 68dk4ahex_dec_init(dk4_ahex_dec_t *dec, dk4_er_t *erp); 69 70/** Add text character to decoder. 71 @param dec Decoder. 72 @param tc Text character to add. 73 @param erp Error report, may be NULL. 74 @return Action to take: 75 - DK4_EDSTM_ACCEPT<br> 76 if the text was saved in the decoder, no action necessary. 77 - DK4_EDSTM_FINISHED<br> 78 if a byte was completed, use dk4ahex_dec_output() to retrieve 79 the byte. 80 - DK4_EDSTM_STOP<br> 81 if the end of data (EOD) marker was detected. 82 Use dk4ahex_dec_finish() to check whether there is still data 83 in the decoder. 84 - DK4_EDSTM_ERROR<br> 85 if an error occured. 86*/ 87int 88 89dk4ahex_dec_add(dk4_ahex_dec_t *dec, char tc, dk4_er_t *erp); 90 91/** Check for final byte. 92 @param dec Decoder. 93 @param erp Error report, may be NULL. 94 @return Action to take, one from: 95 - DK4_EDSTM_ACCEPT<br> 96 if there is no action necessary. 97 - DK4_EDSTM_FINISHED<br> 98 if there is data available, use dk4ahex_dec_output() to retrieve 99 the byte. 100 - DK4_EDSTM_ERROR<br> 101 if an error occured. 102*/ 103int 104 105dk4ahex_dec_finish(dk4_ahex_dec_t *dec, dk4_er_t *erp); 106 107/** Retrieve current decoder content. 108 @param dec Decoder. 109 @param erp Error report, may be NULL. 110 @return The current byte stored in the decoder. 111*/ 112unsigned char 113 114dk4ahex_dec_output(dk4_ahex_dec_t const *dec, dk4_er_t *erp); 115 116#ifdef __cplusplus 117} 118#endif 119 120%% module 121 122#include "dk4conf.h" 123 124#if DK4_HAVE_ASSERT_H 125#ifndef ASSERT_H_INCLUDED 126#include <assert.h> 127#define ASSERT_H_INCLUDED 1 128#endif 129#endif 130 131#include <libdk4c/dk4ahd.h> 132#include <libdk4base/dk4mem.h> 133#include <libdk4c/dk4edstm.h> 134 135 136 137$!trace-include 138 139 140 141void 142 143dk4ahex_dec_init(dk4_ahex_dec_t *dec, dk4_er_t *erp) 144{ 145#if DK4_USE_ASSERT 146 assert(NULL != dec); 147#endif 148 if (NULL != dec) { 149 DK4_MEMRES(dec, sizeof(dk4_ahex_dec_t)); 150 dec->cpos = 0; 151 dec->obyte = 0x00; 152 } else { 153 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 154 } 155} 156 157 158 159int 160 161dk4ahex_dec_add(dk4_ahex_dec_t *dec, char tc, dk4_er_t *erp) 162{ 163 int back = DK4_EDSTM_ERROR; 164#if DK4_USE_ASSERT 165 assert(NULL != dec); 166#endif 167 if (NULL != dec) { 168 switch (tc) { 169 case ' ' : case '\t' : case '\r' : case '\n' : case 0x00 : case 0x0C : { 170 back = DK4_EDSTM_ACCEPT; 171 } break; 172 case '>' : { 173 back = DK4_EDSTM_STOP; 174 } break; 175 case '0' : { 176 if (0 != dec->cpos) { 177 dec->cpos = 2; 178 } else { 179 dec->obyte = 0x00; 180 dec->cpos = 1; 181 } 182 } break; 183 case '1' : { 184 if (0 != dec->cpos) { 185 dec->obyte |= 0x01; dec->cpos = 2; 186 } else { 187 dec->obyte = 0x10; dec->cpos = 1; 188 } 189 } break; 190 case '2' : { 191 if (0 != dec->cpos) { 192 dec->obyte |= 0x02; dec->cpos = 2; 193 } else { 194 dec->obyte = 0x20; dec->cpos = 1; 195 } 196 } break; 197 case '3' : { 198 if (0 != dec->cpos) { 199 dec->obyte |= 0x03; dec->cpos = 2; 200 } else { 201 dec->obyte = 0x30; dec->cpos = 1; 202 } 203 } break; 204 case '4' : { 205 if (0 != dec->cpos) { 206 dec->obyte |= 0x04; dec->cpos = 2; 207 } else { 208 dec->obyte = 0x40; dec->cpos = 1; 209 } 210 } break; 211 case '5' : { 212 if (0 != dec->cpos) { 213 dec->obyte |= 0x05; dec->cpos = 2; 214 } else { 215 dec->obyte = 0x50; dec->cpos = 1; 216 } 217 } break; 218 case '6' : { 219 if (0 != dec->cpos) { 220 dec->obyte |= 0x06; dec->cpos = 2; 221 } else { 222 dec->obyte = 0x60; dec->cpos = 1; 223 } 224 } break; 225 case '7' : { 226 if (0 != dec->cpos) { 227 dec->obyte |= 0x07; dec->cpos = 2; 228 } else { 229 dec->obyte = 0x70; dec->cpos = 1; 230 } 231 } break; 232 case '8' : { 233 if (0 != dec->cpos) { 234 dec->obyte |= 0x08; dec->cpos = 2; 235 } else { 236 dec->obyte = 0x80; dec->cpos = 1; 237 } 238 } break; 239 case '9' : { 240 if (0 != dec->cpos) { 241 dec->obyte |= 0x09; dec->cpos = 2; 242 } else { 243 dec->obyte = 0x90; dec->cpos = 1; 244 } 245 } break; 246 case 'a' : case 'A' : { 247 if (0 != dec->cpos) { 248 dec->obyte |= 0x0A; dec->cpos = 2; 249 } else { 250 dec->obyte = 0xA0; dec->cpos = 1; 251 } 252 } break; 253 case 'b' : case 'B' : { 254 if (0 != dec->cpos) { 255 dec->obyte |= 0x0B; dec->cpos = 2; 256 } else { 257 dec->obyte = 0xB0; dec->cpos = 1; 258 } 259 } break; 260 case 'c' : case 'C' : { 261 if (0 != dec->cpos) { 262 dec->obyte |= 0x0C; dec->cpos = 2; 263 } else { 264 dec->obyte = 0xC0; dec->cpos = 1; 265 } 266 } break; 267 case 'd' : case 'D' : { 268 if (0 != dec->cpos) { 269 dec->obyte |= 0x0D; dec->cpos = 2; 270 } else { 271 dec->obyte = 0xD0; dec->cpos = 1; 272 } 273 } break; 274 case 'e' : case 'E' : { 275 if (0 != dec->cpos) { 276 dec->obyte |= 0x0E; dec->cpos = 2; 277 } else { 278 dec->obyte = 0xE0; dec->cpos = 1; 279 } 280 } break; 281 case 'f' : case 'F' : { 282 if (0 != dec->cpos) { 283 dec->obyte |= 0x0F; dec->cpos = 2; 284 } else { 285 dec->obyte = 0xF0; dec->cpos = 1; 286 } 287 } break; 288 } 289 if (2 == dec->cpos) { 290 dec->cpos = 0; 291 back = DK4_EDSTM_FINISHED; 292 } 293 } else { 294 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 295 } 296 return back; 297} 298 299 300 301int 302 303dk4ahex_dec_finish(dk4_ahex_dec_t *dec, dk4_er_t *erp) 304{ 305 int back = DK4_EDSTM_ERROR; 306#if DK4_USE_ASSERT 307 assert(NULL != dec); 308#endif 309 if (NULL != dec) { 310 switch (dec->cpos) { 311 case 1: { 312 back = DK4_EDSTM_FINISHED; 313 } break; 314 default : { 315 back = DK4_EDSTM_ACCEPT; 316 } break; 317 } 318 } else { 319 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 320 } 321 return back; 322} 323 324 325 326unsigned char 327 328dk4ahex_dec_output(dk4_ahex_dec_t const *dec, dk4_er_t *erp) 329{ 330 unsigned char back = 0x00; 331#if DK4_USE_ASSERT 332 assert(NULL != dec); 333#endif 334 if (NULL != dec) { 335 back = dec->obyte; 336 } else { 337 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 338 } 339 return back; 340} 341 342