Heraia  0.1.8
decode.c
Go to the documentation of this file.
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  decode.c
4  Heraia's library decode.c
5 
6  (C) Copyright 2008 - 2011 Sébastien Tricaud, Olivier Delhomme
7  e-mail : heraia@delhomme.org
8  URL : http://heraia.tuxfamily.org
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2, or (at your option)
13  any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
23 /**
24  * @file decode.c
25  * This file include all functions that may help in decoding a binary stream
26  * to something else such as numbers, dates, other binary stream and so on
27  * @todo I see, while putting some functions documentation that there may be
28  * things to do to improve speed with date calculations -> should we fill
29  * tab_ns_months at every function calls ? This may not be necessary
30  */
31 #include <libheraia.h>
32 
33 static gboolean bissextile_year(guint32 year);
34 static void calc_which_month_day(date_and_time_t *mydate, guint32 day, guint tab_ns_months[12]);
35 static void which_month_day(date_and_time_t *mydate, guint32 day, gboolean bi);
36 static guint32 remove_days_from_first_january(guint32 base_year, guint8 base_month, guint8 base_day);
37 static void which_year_month_day(date_and_time_t *mydate, guint32 days, guint32 base_year, guint base_month, guint8 base_day);
38 static void make_date_and_time(date_and_time_t *mydate, guchar *data, guint8 len, guint64 nbticks, guint32 base_year, guint base_month, guint8 base_day);
39 static void transform_bcd_to_human(gchar *bcd, guint8 part, guint8 part_number);
40 
41 
42 /**
43  * General purpose of this function is to take a 1 byte data stream
44  * and convert it as if it is an 8 bits signed number
45  * @param data : 1 guchar
46  * @param data_struct a pointer to a user defined data structure
47  * @return returns a gchar * that may be freed when no longer needed
48  */
49 gchar *decode_8bits_signed(guchar *data, gpointer data_struct)
50 {
51  gint8 total = 0;
52 
53  if (data == NULL)
54  {
55  return NULL;
56  }
57  else
58  {
59  memcpy(&total, data, sizeof (guchar));
60  return g_strdup_printf("%d", total);
61  }
62 }
63 
64 
65 /**
66  * general purpose of this function is to take a 1 byte data stream
67  * and convert it as if it is an 8 bits unsigned number
68  * @param data : 1 guchar
69  * @param data_struct a pointer to a user defined data structure
70  * @return returns a gchar * that may be freed when no longer needed
71 */
72 gchar *decode_8bits_unsigned(guchar *data, gpointer data_struct)
73 {
74  guint8 total = 0;
75 
76  if (data == NULL)
77  {
78  return NULL;
79  }
80  else
81  {
82  memcpy(&total, data, sizeof (guchar));
83  return g_strdup_printf("%u", total);
84  }
85 }
86 
87 
88 /**
89  * general purpose of this function is to take a 2 byte data stream
90  * and convert it as if it is a 16 bits signed number
91  * @param data : 2 guchars
92  * @param data_struct a pointer to a user defined data structure
93  * @return returns a gchar * that may be freed when no longer needed
94  */
95 gchar *decode_16bits_signed(guchar *data, gpointer data_struct)
96 {
97  gint16 total = 0;
98 
99  if (data == NULL)
100  {
101  return NULL;
102  }
103  else
104  {
105  memcpy(&total, data, 2 * sizeof (guchar));
106  return g_strdup_printf("%d", total);
107  }
108 }
109 
110 
111 /**
112  * general purpose of this function is to take a 2 byte data stream
113  * and convert it as if it is a 16 bits unsigned number
114  * @param data : 2 guchars
115  * @param data_struct a pointer to a user defined data structure
116  * @return returns a gchar * that may be freed when no longer needed
117  */
118 gchar *decode_16bits_unsigned(guchar *data, gpointer data_struct)
119 {
120  guint16 total = 0;
121 
122  if (data == NULL)
123  {
124  return NULL;
125  }
126  else
127  {
128  memcpy(&total, data, 2 * sizeof (guchar));
129  return g_strdup_printf("%u", total);
130  }
131 }
132 
133 
134 /**
135  * general purpose of this function is to take a 4 byte data stream
136  * and convert it as if it is a 32 bits signed number
137  * @param data : 4 guchars
138  * @param data_struct a pointer to a user defined data structure
139  * @return returns a gchar * that may be freed when no longer needed
140 */
141 gchar *decode_32bits_signed(guchar *data, gpointer data_struct)
142 {
143  gint32 total = 0;
144 
145  if (data == NULL)
146  {
147  return NULL;
148  }
149  else
150  {
151  memcpy(&total, data, 4 * sizeof (guchar));
152  return g_strdup_printf("%d", total);
153  }
154 }
155 
156 
157 /**
158  * general purpose of this function is to take a 4 byte data stream
159  * and convert it as if it is a 32 bits unsigned number
160  * @param data : 4 guchars
161  * @param data_struct a pointer to a user defined data structure
162  * @return returns a gchar * that may be freed when no longer needed
163 */
164 gchar *decode_32bits_unsigned(guchar *data, gpointer data_struct)
165 {
166  guint32 total = 0;
167 
168  if (data == NULL)
169  {
170  return NULL;
171  }
172  else
173  {
174  memcpy(&total, data, 4 * sizeof (guchar));
175  return g_strdup_printf("%u", total);
176  }
177 }
178 
179 
180 /**
181  * general purpose of this function is to take a 8 byte data stream
182  * and convert it as if it is a 64 bits signed number
183  * @param data : 8 guchars
184  * @param data_struct a pointer to a user defined data structure
185  * @return returns a gchar * that may be freed when no longer needed
186 */
187 gchar *decode_64bits_signed(guchar *data, gpointer data_struct)
188 {
189  gint64 total = 0;
190 
191  if (data == NULL)
192  {
193  return NULL;
194  }
195  else
196  {
197  memcpy(&total, data, 8 * sizeof (guchar));
198  return g_strdup_printf("%lld", (long long int) total);
199  }
200 }
201 
202 
203 /**
204  * general purpose of this function is to take a 8 byte data stream
205  * and convert it as if it is a 64 bits unsigned number
206  * @param data : 8 guchars
207  * @param data_struct a pointer to a user defined data structure
208  * @return returns a gchar * that may be freed when no longer needed
209 */
210 gchar *decode_64bits_unsigned(guchar *data, gpointer data_struct)
211 {
212  guint64 total = 0;
213 
214  if (data == NULL)
215  {
216  return NULL;
217  }
218  else
219  {
220  memcpy(&total, data, 8 * sizeof (guchar));
221  return g_strdup_printf("%llu", (long long unsigned int) total);
222  }
223 }
224 
225 
226 /**
227  * general purpose of this function is to take a 4 byte data stream
228  * and convert it as if it is a float number normal notation
229  * @param data : 4 guchars
230  * @param data_struct a pointer to a user defined data structure
231  * @return returns a gchar * that may be freed when no longer needed
232 */
233 gchar *decode_float_normal(guchar *data, gpointer data_struct)
234 {
235  gfloat total = 0.0;
236 
237  if (data == NULL)
238  {
239  return NULL;
240  }
241  else
242  {
243  memcpy(&total, data, 4 * sizeof (guchar));
244  return g_strdup_printf("%f", total);
245  }
246 }
247 
248 
249 /**
250  * general purpose of this function is to take a 4 byte data stream
251  * and convert it as if it is a float number normal notation
252  * @param data : 4 guchars
253  * @param data_struct a pointer to a user defined data structure
254  * @return returns a gchar * that may be freed when no longer needed
255 */
256 gchar *decode_float_scientific(guchar *data, gpointer data_struct)
257 {
258  gfloat total = 0.0;
259 
260  if (data == NULL)
261  {
262  return NULL;
263  }
264  else
265  {
266  memcpy(&total, data, 4 * sizeof (guchar));
267  return g_strdup_printf("%g", total);
268  }
269 }
270 
271 
272 /**
273  * general purpose of this function is to take a 8 byte data stream
274  * and convert it as if it is a float number normal notation
275  * @param data : 4 guchars
276  * @param data_struct a pointer to a user defined data structure
277  * @return returns a gchar * that may be freed when no longer needed
278 */
279 gchar *decode_double_normal(guchar *data, gpointer data_struct)
280 {
281  gdouble total = 0.0;
282 
283  if (data == NULL)
284  {
285  return NULL;
286  }
287  else
288  {
289  memcpy(&total, data, 8 * sizeof (guchar));
290  return g_strdup_printf("%f", total);
291  }
292 }
293 
294 
295 /**
296  * general purpose of this function is to take a 8 byte data stream
297  * and convert it as if it is a float number normal notation
298  * @param data : 4 guchars
299  * @param data_struct a pointer to a user defined data structure
300  * @return returns a gchar * that may be freed when no longer needed
301 */
302 gchar *decode_double_scientific(guchar *data, gpointer data_struct)
303 {
304  gdouble total = 0.0;
305 
306  if (data == NULL)
307  {
308  return NULL;
309  }
310  else
311  {
312  memcpy(&total, data, 8 * sizeof (guchar));
313  return g_strdup_printf("%g", total);
314  }
315 }
316 
317 
318 /**
319  * Says whether a year is a leap one or not
320  * @param year : a guint32 representing a year such as 2009
321  * @return TRUE if it's a leap year FALSE instead.
322  */
323 static gboolean bissextile_year(guint32 year)
324 {
325  if ((year % 4) == 0)
326  {
327  if ((year % 100) == 0)
328  {
329  if ((year % 400) == 0)
330  {
331  return TRUE;
332  }
333  else
334  {
335  return FALSE;
336  }
337  }
338  else
339  {
340  return TRUE;
341  }
342  }
343  else
344  {
345  return FALSE;
346  }
347 }
348 
349 
350 /**
351  * Says, from a number of days (eg 154), which month it is (eg may)
352  * and which day in the corresponding month (eg 2 (leap year) or 3)
353  * @param[out] mydate : Filled date structure
354  * @param day : guint32 representing the number of day in the year (1..365/366)
355  * @param tab_ns_months : an array filled with the cumulative number of days for each month (31 to 365/366)
356  */
357 static void calc_which_month_day(date_and_time_t *mydate, guint32 day, guint tab_ns_months[12])
358 {
359  gushort i = 0;
360 
361  while (i<12 && day > tab_ns_months[i])
362  {
363  i++;
364  }
365 
366  mydate->month = i + 1;
367 
368  if (i == 0)
369  {
370  mydate->day = 1 + day;
371  }
372  else
373  {
374  mydate->day = (1 + day) - tab_ns_months[i-1];
375  }
376 }
377 
378 
379 /**
380  * Front end function for the calc_which_month_day function !
381  * @param[out] mydate : Filled date structure
382  * @param day : guint32 representing the number of day in the year (1..365/366)
383  * @param bi : TRUE if it's a leap year, FALSE instead
384  */
385 static void which_month_day(date_and_time_t *mydate, guint32 day, gboolean bi)
386 {
387 
388  if (bi == TRUE)
389  {
390  if (day <= 366)
391  {
392  guint tab_ns_months[12] = { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } ;
393  calc_which_month_day(mydate, day, tab_ns_months);
394  }
395  else
396  {
397  mydate->day = 0;
398  mydate->month = 0;
399  }
400  }
401  else
402  {
403  if (day <= 365)
404  {
405  guint tab_ns_months[12] = { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
406  calc_which_month_day(mydate, day, tab_ns_months);
407  }
408  else
409  {
410  mydate->day = 0;
411  mydate->month = 0;
412  }
413  }
414 }
415 
416 
417 /**
418  * Returns the number of days since 01/01/base_year
419  * eg 15/02/base_year --> 31 + 15 = 46
420  * @param base_year : year where we want to begin the calculation
421  * @param base_month : month (in the example 02)
422  * @param base_day : day in the month (from the example 15)
423  * @return returns a number of days since begining of the year (eg 1..365/366)
424  */
425 static guint32 remove_days_from_first_january(guint32 base_year, guint8 base_month, guint8 base_day)
426 {
427  guint tab_ns_months[11];
428 
429  if (base_day > 0 && base_day < 32)
430  {
431  base_day -= 1;
432  }
433  else
434  {
435  return 0; /* Obviously something might be wrong if we fall here */
436  }
437 
438  tab_ns_months[0] = 31;
439  if (bissextile_year(base_year))
440  {
441  tab_ns_months[1] = 60;
442  tab_ns_months[2] = 91;
443  tab_ns_months[3] = 121;
444  tab_ns_months[4] = 152;
445  tab_ns_months[5] = 182;
446  tab_ns_months[6] = 213;
447  tab_ns_months[7] = 244;
448  tab_ns_months[8] = 274;
449  tab_ns_months[9] = 305;
450  tab_ns_months[10] = 335;
451  }
452  else
453  {
454  tab_ns_months[1] = 59;
455  tab_ns_months[2] = 90;
456  tab_ns_months[3] = 120;
457  tab_ns_months[4] = 151;
458  tab_ns_months[5] = 181;
459  tab_ns_months[6] = 212;
460  tab_ns_months[7] = 243;
461  tab_ns_months[8] = 273;
462  tab_ns_months[9] = 304;
463  tab_ns_months[10] = 334;
464  }
465 
466  if (base_month > 1 && base_month < 13)
467  {
468  return (tab_ns_months[base_month-2] + base_day);
469  }
470  else if (base_month == 1)
471  {
472  return base_day;
473  }
474  else
475  {
476  return 0;
477  }
478 }
479 
480 
481 /**
482  * About date calculation : Leap years are periods of 4 years except
483  * the years that we can divide by 100 and not 400.
484  * So we can distinguish 2 periods : one of 400 years and one of 4 years.
485  * - we have 100 bissextiles years in a period of 400 years this means that
486  * every 400 years we have exactly 146100 days.
487  * - we have 1 bissextile year every 4 years : this means that we have exactly
488  * 1461 days every 4 years.
489  * As we can calculate _exactly_ the number of days in a filetime or C_date
490  * format, we could calculate _exactly_ the number of periods of 400 years and
491  * then the number of periods of 4 years.
492  * @param[out] mydate : Filled date structure
493  * @param days : number of days calculated
494  * @param base_year : base year used for calculation (eg 1601 for filetime)
495  * @param base_month : base month used for calculation (eg 01, january for filetime)
496  * @param base_day : base day used for calculation (eg 01 for filetime)
497 */
498 static void which_year_month_day(date_and_time_t *mydate, guint32 days, guint32 base_year, guint base_month, guint8 base_day)
499 {
500  guint32 modulus = 0;
501  guint32 reste = 0;
502  guint32 nbdays = 0;
503 
504  days -= remove_days_from_first_january(base_year, base_month, base_day);
505 
506  if (days > 146100)
507  {
508  modulus = days / 146100;
509  mydate->year = modulus * 400;
510  reste = modulus * 3; /* To add centuries in the 400 years modulus */
511  days = days % 146100;
512  }
513 
514  modulus = days / 1461;
515  mydate->year += modulus * 4;
516  reste += (modulus*4) / 100; /* To add centuries */
517  reste += days % 1461;
518 
519  mydate->year += base_year;
520  if (bissextile_year(mydate->year))
521  nbdays = 366;
522  else
523  nbdays = 365;
524 
525  while (reste > nbdays)
526  {
527  reste -= nbdays;
528  mydate->year += 1;
529  if (bissextile_year(mydate->year))
530  nbdays = 366;
531  else
532  nbdays = 365;
533  }
534 
535  which_month_day(mydate, reste, bissextile_year(mydate->year));
536 }
537 
538 
539 /**
540  * Return a gchar * that contains the date and time
541  * encoded from the values contained in the date_and_time_t structure
542  * it may be freed when no longer needed
543  * We do not use any of the g_date_strftime or strftime function
544  * because interpreted dates are not always valid !
545  * @param[in] mydate : structure that contains a date
546  * @return returns a gchar * printed out in a french like format "dd/mm/aaaa - hh:mm:ss"
547  * @todo Add a way to use a user defined format and/or predefined formats
548  */
549 static gchar *date_printf(date_and_time_t *mydate)
550 {
551  return g_strdup_printf("%02u/%02u/%04u - %02u:%02u:%02u", mydate->day, mydate->month, mydate->year, mydate->hour, mydate->minutes, mydate->seconds);
552 }
553 
554 
555 /**
556  * general purpose of this function is to take a 4 byte data stream
557  * and convert it as if it is a dos date. If it is not, the result
558  * may be funny !
559  * @param data : 4 guchars
560  * @param data_struct a pointer to a user defined data structure
561  * @return returns a gchar * that may be freed when no longer needed
562 */
563 gchar *decode_dos_date(guchar *data, gpointer data_struct)
564 {
565  date_and_time_t *mydate = NULL; /**< date resulting of interpretation */
566  gchar *interpreted_date = NULL; /**< text that is the result of date interpretation */
567 
568  if (data == NULL)
569  {
570  return NULL;
571  }
572  else
573  {
574  mydate = (date_and_time_t *) g_malloc0 (sizeof(date_and_time_t));
575 
576  mydate->year = (data[3] >> 1) + 1980;
577  mydate->month = ((data[3] & 0x01) << 3) + (data[2] >> 5);
578  mydate->day = data[2] & 0x1F;
579  mydate->hour = (data[1] & 0xF8) >> 3;
580  mydate->minutes = ((data[1] & 0x07) << 3) + ((data[0] & 0xE0) >> 5);
581  mydate->seconds = (data[0] & 0x1F) << 1;
582 
583  interpreted_date = date_printf(mydate);
584  g_free(mydate);
585 
586  return interpreted_date;
587  }
588 }
589 
590 
591 /**
592  * Reads the data from the stream (specified length !! <= 8 or 64 bits to decode)
593  * @param[out] mydate : date_and_time_t * structure that contain the resulting date
594  * @param data : a guchar * as a stream to decode as a date
595  * @param len : guint8 as length of the stream in bytes (must be <= 8 or 64 bits to decode)
596  * @param nbticks : guint64 that tells the number of ticks per seconds (1, 1000, ...)
597  * @param base_year : guint32, Epoch year (1970, 1904, ...)
598  * @param base_month : guint32, Epoch month (january, ...)
599  * @param base_day : guint32 Epoch day (01, 15, ...)
600  * @return populates the date_and_time_t structure (my_date)
601 */
602 static void make_date_and_time(date_and_time_t *mydate, guchar *data, guint8 len, guint64 nbticks, guint32 base_year, guint base_month, guint8 base_day)
603 {
604  guint64 total = 0;
605  guint32 days = 0;
606 
607  memcpy(&total, data, len * sizeof (guchar));
608 
609  total = (total / nbticks); /* 1 seconds represents nbticks */
610  days = (guint32) (total / 86400); /* 86400 seconds a day */;
611 
612  which_year_month_day(mydate, days, base_year, base_month, base_day);
613 
614  mydate->hour = ((total % 86400) / 3600); /* 3600 seconds is one hour out of one day */
615  mydate->minutes = ((total % 3600) / 60); /* 60 seconds is one minute out of one hour */
616  mydate->seconds = (total % 60);
617 }
618 
619 
620 /**
621  * general purpose of this function is to take a 8 byte data stream
622  * and convert it as if it is a filetime date. If it is not, the result
623  * may be funny ! Counting 100th of nanoseconds from 01/01/1601
624  * @param data : 8 guchars
625  * @param data_struct a pointer to a user defined data structure
626  * @return returns a gchar * that may be freed when no longer needed
627 */
628 gchar *decode_filetime_date(guchar *data, gpointer data_struct)
629 {
630  date_and_time_t *mydate = NULL; /**< date resulting of interpretation */
631  gchar *interpreted_date = NULL; /**< text that is the result of date interpretation */
632 
633  if (data == NULL)
634  {
635  return NULL;
636  }
637  else
638  {
639  mydate = (date_and_time_t *) g_malloc0 (sizeof(date_and_time_t));
640 
641  make_date_and_time(mydate, data, 8, 10000000, 1601, 1, 1);
642 
643  interpreted_date = date_printf(mydate);
644  g_free(mydate);
645 
646  return interpreted_date;
647  }
648 }
649 
650 
651 /**
652  * general purpose of this function is to take a 4 byte data stream
653  * and convert it as if it is a C date. If it is not, the result may
654  * be funny ! Counting seconds from 01/01/1970
655  * @param data : 4 guchars
656  * @param data_struct a pointer to a user defined data structure
657  * @return returns a gchar * that may be freed when no longer needed
658 */
659 gchar *decode_C_date(guchar *data, gpointer data_struct)
660 {
661  date_and_time_t *mydate = NULL; /**< date resulting of interpretation */
662  gchar *interpreted_date = NULL; /**< text that is the result of date interpretation */
663 
664  if (data == NULL)
665  {
666  return NULL;
667  }
668  else
669  {
670  mydate = (date_and_time_t *) g_malloc0 (sizeof(date_and_time_t));
671 
672  make_date_and_time(mydate, data, 4, 1, 1970, 1, 1);
673 
674  interpreted_date = date_printf(mydate);
675  g_free(mydate);
676 
677  return interpreted_date;
678  }
679 }
680 
681 
682 /**
683  * general purpose of this function is to take a 4 byte data stream
684  * and convert it as if it is a HFS date. If it is not, the result may
685  * be funny ! Counting seconds 01/01/1904
686  * @param data : 4 guchars
687  * @param data_struct a pointer to a user defined data structure
688  * @return returns a gchar* that may be freed when no longer needed
689 */
690 gchar *decode_HFS_date(guchar *data, gpointer data_struct)
691 {
692  date_and_time_t *mydate = NULL; /**< date resulting of interpretation */
693  gchar *interpreted_date = NULL; /**< text that is the result of date interpretation */
694 
695  if (data == NULL)
696  {
697  return NULL;
698  }
699  else
700  {
701  mydate = (date_and_time_t *) g_malloc0 (sizeof(date_and_time_t));
702 
703  make_date_and_time(mydate, data, 4, 1, 1904, 1, 1);
704 
705  interpreted_date = date_printf(mydate);
706  g_free(mydate);
707 
708  return interpreted_date;
709  }
710 }
711 
712 
713 /**
714  * Returns a guchar that is 1 or 0 respectiveky if data is > 0 or not
715  * @param data : a value to analyse
716  * @return : 1 or 0 f data is > 0 or not
717  */
718 static guchar data_to_one_bit(guchar data)
719 {
720  if (data > 0)
721  {
722  return '1';
723  }
724  else
725  {
726  return '0';
727  }
728 }
729 
730 
731 /**
732  * decodes the stream represented by *data (one byte) to a
733  * string containing eight 0 or 1 (Little Endian style)
734  * @param data : 1 guchar
735  * @param data_struct a pointer to a user defined data structure
736  * @return n*9 gchars that are either '1' or '0' or ' ' (as a separator), the
737  * string may be freed when no longer needed
738  */
739 gchar *decode_to_bits(guchar *data, gpointer data_struct)
740 {
741  gchar *bits = NULL;
742  guint i = 0;
743  guint j = 0;
744  decode_parameters_t *decode_parameters = (decode_parameters_t *) data_struct;
745 
746  if (data == NULL)
747  {
748  return NULL;
749  }
750  else
751  {
752  bits = (gchar *) g_malloc0(decode_parameters->stream_size * 10 * (sizeof(gchar)) + 1);
753 
754  j = 0;
755  for (i = 0 ; i < decode_parameters->stream_size ; i++)
756  {
757  bits[j] = data_to_one_bit(data[i] & 0x80);
758  j++;
759 
760  bits[j] = data_to_one_bit(data[i] & 0x40);
761  j++;
762 
763  bits[j] = data_to_one_bit(data[i] & 0x20);
764  j++;
765 
766  bits[j] = data_to_one_bit(data[i] & 0x10);
767  j++;
768 
769  bits[j] = ' ';
770  j++;
771 
772  bits[j] = data_to_one_bit(data[i] & 0x08);
773  j++;
774 
775  bits[j] = data_to_one_bit(data[i] & 0x04);
776  j++;
777 
778  bits[j] = data_to_one_bit(data[i] & 0x02);
779  j++;
780 
781  bits[j] = data_to_one_bit(data[i] & 0x01);
782  j++;
783 
784  bits[j] = ' ';
785  j++;
786  }
787 
788  j--;
789  bits[j] = (gchar) 0;
790 
791  return bits;
792 
793  }
794 }
795 
796 
797 /**
798  * transcribes the bcd number "part" into a
799  * @param[out] bcd : gchar * human readable string
800  * @param part : guint8 as an half byte to decode
801  * @param part_number : 0 or 1 as MSB and LSB
802  * Coding style is from ETSI GSM 04.08 ETS 300557 p387
803  * @todo give choice of coding style (eg for numbers >=10)
804  */
805 static void transform_bcd_to_human(gchar *bcd, guint8 part, guint8 part_number)
806 {
807  switch (part)
808  {
809  case 0 :
810  bcd[part_number] = '0';
811  break;
812  case 1 :
813  bcd[part_number] = '1';
814  break;
815  case 2 :
816  bcd[part_number] = '2';
817  break;
818  case 3 :
819  bcd[part_number] = '3';
820  break;
821  case 4 :
822  bcd[part_number] = '4';
823  break;
824  case 5 :
825  bcd[part_number] = '5';
826  break;
827  case 6 :
828  bcd[part_number] = '6';
829  break;
830  case 7 :
831  bcd[part_number] = '7';
832  break;
833  case 8 :
834  bcd[part_number] = '8';
835  break;
836  case 9 :
837  bcd[part_number] = '9';
838  break;
839  case 10 :
840  bcd[part_number] = '*';
841  break;
842  case 11 :
843  bcd[part_number] = '#';
844  break;
845  case 12 :
846  bcd[part_number] = 'a';
847  break;
848  case 13 :
849  bcd[part_number] = 'b';
850  break;
851  case 14 :
852  bcd[part_number] = 'c';
853  break;
854  case 15 :
855  bcd[part_number] = ' '; /* Endmark */
856  break;
857  default :
858  bcd[part_number] = '?'; /* This default case should never happen */
859  break;
860  }
861 }
862 
863 
864 /**
865  * Decode one byte as a Packed BCD (Binary Coded Decimal)
866  * and return a gchar* that may be freed when no longer
867  * needed
868  * @param data : stream to decode as 1 guchar
869  * @param data_struct a pointer to a user defined data structure
870  * @return returns a gchar * that contain the packed BCD interpretation
871  */
872 gchar *decode_packed_BCD(guchar *data, gpointer data_struct)
873 {
874  guint8 total = 0;
875  guint i = 0;
876  guint j = 0;
877  gchar *bcd = NULL;
878  decode_parameters_t *decode_parameters = (decode_parameters_t *) data_struct;
879 
880  if (data == NULL)
881  {
882  return NULL;
883  }
884  else
885  {
886  i = 0;
887  j = 0;
888  bcd = (gchar *) g_malloc0((2 * decode_parameters->stream_size + 1) * sizeof(gchar));
889  while (i < decode_parameters->stream_size)
890  {
891  memcpy(&total, data + i, sizeof(guchar));
892  transform_bcd_to_human(bcd + j, (total & 0x0F), 0);
893  transform_bcd_to_human(bcd + j, ((total & 0xF0)>>4), 1);
894  i++;
895  j = j + 2;
896  }
897  bcd[j+1] = '\0';
898 
899  return bcd;
900  }
901 }
902 
903 
904 /**
905  * Swap bytes from the buffer to_swap
906  * @warning recursive function !! Call with first = 0 and last = last byte
907  * of buffer to swap
908  * @param[in,out] to_swap : buffer to swap
909  * @param first : first byte in the buffer to swap
910  * @param last : last byte in the buffer to swap
911  * @return returns TRUE when first is >= to last and this end recursivity
912  */
913 gboolean swap_bytes(guchar *to_swap, guint first, guint last)
914 {
915  guchar aux;
916 
917  if (first >= last)
918  {
919  return TRUE;
920  }
921  else
922  {
923  aux = to_swap[first];
924  to_swap[first] = to_swap[last];
925  to_swap[last] = aux;
926  return swap_bytes(to_swap, ++first, --last);
927  }
928 }
929 
930 
931 /**
932  * Reverse the byte order LSB -> MSB in MSB -> LSB
933  * 12345678 in 87654321
934  * @param[in,out] to_reverse : one guchar to be reversed
935  */
936 void reverse_byte_order(guchar *to_reverse)
937 {
938  guint8 car = (guint8) to_reverse[0];
939  guint8 aux = 0;
940 
941  aux = ((car & 0x80) >> 7);
942  aux += ((car & 0x40) >> 5);
943  aux += ((car & 0x20) >> 3);
944  aux += ((car & 0x10) >> 1);
945  aux += ((car & 0x08) << 1);
946  aux += ((car & 0x04) << 3);
947  aux += ((car & 0x02) << 5);
948  aux += ((car & 0x01) << 7);
949 
950  to_reverse[0] = (guchar) aux;
951 }
952 
953 
954 /**
955  * Make an new decode_parameters_t in order to pass to the functions
956  * @param endianness : endianness as setup in data interpertor's window
957  * @param stream_size : stream size as setup with the spin button
958  * @return returns a newly allocated decode_parameters_t structure which may be
959  * freed when no longer needed
960  */
961 decode_parameters_t *new_decode_parameters_t(guint endianness, guint stream_size)
962 {
963  decode_parameters_t *decode_parameters = NULL;
964 
965  decode_parameters = (decode_parameters_t *) g_malloc0(sizeof(decode_parameters_t));
966 
967  decode_parameters->endianness = endianness;
968  decode_parameters->stream_size = stream_size;
969 
970  return decode_parameters;
971 }
972 
973 
974 /**
975  * Make a new decode_t structure
976  * @param decode_func : pointer to a function that may decode a stream
977  * this function must follow DecodeFunc prototype
978  * @param entry : A GtkWidget entry that will receive the result of the
979  * decoding function
980  * @return returns a newly allocated decode_t structure filled with the two
981  * parameters.
982  */
983 decode_t *new_decode_t(DecodeFunc decode_func, GtkWidget *entry, const gchar *err_msg)
984 {
985  decode_t *decode_struct = NULL;
986 
987  if (decode_func != NULL && entry != NULL)
988  {
989  decode_struct = (decode_t *) g_malloc0(sizeof(decode_t));
990  decode_struct->func = decode_func;
991  decode_struct->entry = entry;
992  decode_struct->err_msg = g_strdup(err_msg);
993 
994  return decode_struct;
995  }
996  else
997  {
998  return NULL;
999  }
1000 }
1001 
1002 
1003 /**
1004  * Make a new decode_generic_t structure and creates the associated widgets
1005  * @param label : the label for this row
1006  * @param data_size : a default data_size
1007  * @param fixed_size : TRUE if the size is fixed and should not be updated,
1008  * FALSE otherwise
1009  * @param err_msg : an error message to be displayed if dcoding can not be
1010  * processed
1011  * @param nb_cols : number of decoding columns we want
1012  * @param ... : va_list of functions to fill in the columns (you MUST have the
1013  * same number of columns and functions you passes here as
1014  * arguments)
1015  * @return returns a newly allocated decode_generic_t structure filled with the
1016  * right parameters
1017  */
1018 decode_generic_t *new_decode_generic_t(const gchar *label, guint data_size, gboolean fixed_size, const gchar *err_msg, guint nb_cols, ...)
1019 {
1020  va_list args; /**< va_list arguments : decoding function names */
1021  decode_generic_t *my_struct = NULL; /** structure to be initialized and returned */
1022  decode_t *decode; /** Entry and associated function */
1023  guint i = 0;
1024  DecodeFunc decode_it; /**< one decoding function */
1025  GtkWidget *entry = NULL; /**< entry associated to the decoding function */
1026  GPtrArray *decode_array; /**< To keep track of those couples */
1027 
1028  decode_array = g_ptr_array_new();
1029 
1030  my_struct = (decode_generic_t *) g_malloc0(sizeof(decode_generic_t));
1031 
1032  va_start(args, nb_cols);
1033  for (i = 0 ; i < nb_cols ; i++)
1034  {
1035  decode_it = (DecodeFunc) va_arg(args, DecodeFunc);
1036  entry = gtk_entry_new();
1037  gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1038  decode = new_decode_t(decode_it, entry, err_msg);
1039  g_ptr_array_add(decode_array, (gpointer) decode);
1040  }
1041  va_end(args);
1042 
1043  my_struct->decode_array = decode_array;
1044  my_struct->label = gtk_label_new(label);
1045  gtk_misc_set_padding(GTK_MISC(my_struct->label), 3, 3);
1046  gtk_misc_set_alignment(GTK_MISC(my_struct->label), 0.5, 0.5);
1047  my_struct->data_size = data_size;
1048  my_struct->fixed_size = fixed_size;
1049 
1050  return my_struct;
1051 }
static void which_year_month_day(date_and_time_t *mydate, guint32 days, guint32 base_year, guint base_month, guint8 base_day)
About date calculation : Leap years are periods of 4 years except the years that we can divide by 100...
Definition: decode.c:498
static gchar * date_printf(date_and_time_t *mydate)
Return a gchar * that contains the date and time encoded from the values contained in the date_and_ti...
Definition: decode.c:549
gchar * decode_16bits_unsigned(guchar *data, gpointer data_struct)
general purpose of this function is to take a 2 byte data stream and convert it as if it is a 16 bits...
Definition: decode.c:118
gboolean fixed_size
says whether we can modify data_size or not
Definition: libheraia.h:181
gchar * err_msg
error message if something went wrong when decoding expects a d somewhere in the message to represent...
Definition: libheraia.h:164
gchar * decode_double_scientific(guchar *data, gpointer data_struct)
general purpose of this function is to take a 8 byte data stream and convert it as if it is a float n...
Definition: decode.c:302
gchar * decode_32bits_unsigned(guchar *data, gpointer data_struct)
general purpose of this function is to take a 4 byte data stream and convert it as if it is a 32 bits...
Definition: decode.c:164
guint data_size
size of what we may decode
Definition: libheraia.h:180
DecodeFunc func
a function to decode into something
Definition: libheraia.h:162
gchar * decode_float_scientific(guchar *data, gpointer data_struct)
general purpose of this function is to take a 4 byte data stream and convert it as if it is a float n...
Definition: decode.c:256
void reverse_byte_order(guchar *to_reverse)
Reverse the byte order LSB -> MSB in MSB -> LSB 12345678 in 87654321.
Definition: decode.c:936
static void which_month_day(date_and_time_t *mydate, guint32 day, gboolean bi)
Front end function for the calc_which_month_day function !
Definition: decode.c:385
static gboolean bissextile_year(guint32 year)
Says whether a year is a leap one or not.
Definition: decode.c:323
gchar * decode_dos_date(guchar *data, gpointer data_struct)
general purpose of this function is to take a 4 byte data stream and convert it as if it is a dos dat...
Definition: decode.c:563
gchar * decode_filetime_date(guchar *data, gpointer data_struct)
general purpose of this function is to take a 8 byte data stream and convert it as if it is a filetim...
Definition: decode.c:628
guint32 year
Definition: libheraia.h:128
static void calc_which_month_day(date_and_time_t *mydate, guint32 day, guint tab_ns_months[12])
Says, from a number of days (eg 154), which month it is (eg may) and which day in the corresponding m...
Definition: decode.c:357
static guint32 remove_days_from_first_january(guint32 base_year, guint8 base_month, guint8 base_day)
Returns the number of days since 01/01/base_year eg 15/02/base_year –> 31 + 15 = 46...
Definition: decode.c:425
gchar * decode_8bits_unsigned(guchar *data, gpointer data_struct)
general purpose of this function is to take a 1 byte data stream and convert it as if it is an 8 bits...
Definition: decode.c:72
gchar * decode_32bits_signed(guchar *data, gpointer data_struct)
general purpose of this function is to take a 4 byte data stream and convert it as if it is a 32 bits...
Definition: decode.c:141
gchar * decode_to_bits(guchar *data, gpointer data_struct)
decodes the stream represented by *data (one byte) to a string containing eight 0 or 1 (Little Endian...
Definition: decode.c:739
gchar * decode_8bits_signed(guchar *data, gpointer data_struct)
General purpose of this function is to take a 1 byte data stream and convert it as if it is an 8 bits...
Definition: decode.c:49
guint32 month
Definition: libheraia.h:129
A human struct to store a date with a time.
Definition: libheraia.h:126
guint32 seconds
Definition: libheraia.h:134
static void make_date_and_time(date_and_time_t *mydate, guchar *data, guint8 len, guint64 nbticks, guint32 base_year, guint base_month, guint8 base_day)
Reads the data from the stream (specified length !! <= 8 or 64 bits to decode)
Definition: decode.c:602
static guchar data_to_one_bit(guchar data)
Returns a guchar that is 1 or 0 respectiveky if data is > 0 or not.
Definition: decode.c:718
Basic way to associate a decode function and an entry that will receive the result.
Definition: libheraia.h:160
guint32 hour
Definition: libheraia.h:132
decode_parameters_t * new_decode_parameters_t(guint endianness, guint stream_size)
Make an new decode_parameters_t in order to pass to the functions.
Definition: decode.c:961
gchar * decode_double_normal(guchar *data, gpointer data_struct)
general purpose of this function is to take a 8 byte data stream and convert it as if it is a float n...
Definition: decode.c:279
gchar *(* DecodeFunc)(guchar *, gpointer)
Templates for the decoding functions.
Definition: libheraia.h:139
GPtrArray * decode_array
Pointer Array of decode_t functions and corresponding entries.
Definition: libheraia.h:178
gchar * decode_64bits_signed(guchar *data, gpointer data_struct)
general purpose of this function is to take a 8 byte data stream and convert it as if it is a 64 bits...
Definition: decode.c:187
gchar * decode_HFS_date(guchar *data, gpointer data_struct)
general purpose of this function is to take a 4 byte data stream and convert it as if it is a HFS dat...
Definition: decode.c:690
gchar * decode_float_normal(guchar *data, gpointer data_struct)
general purpose of this function is to take a 4 byte data stream and convert it as if it is a float n...
Definition: decode.c:233
gboolean swap_bytes(guchar *to_swap, guint first, guint last)
Swap bytes from the buffer to_swap.
Definition: decode.c:913
GtkWidget * label
label for these decoding functions
Definition: libheraia.h:179
This file contains all the definitions and includes all other .h files.
gchar * decode_packed_BCD(guchar *data, gpointer data_struct)
Decode one byte as a Packed BCD (Binary Coded Decimal) and return a gchar* that may be freed when no ...
Definition: decode.c:872
static void transform_bcd_to_human(gchar *bcd, guint8 part, guint8 part_number)
transcribes the bcd number "part" into a
Definition: decode.c:805
guint32 minutes
Definition: libheraia.h:133
GtkWidget * entry
the widget that will receive the result
Definition: libheraia.h:163
gchar * decode_64bits_unsigned(guchar *data, gpointer data_struct)
general purpose of this function is to take a 8 byte data stream and convert it as if it is a 64 bits...
Definition: decode.c:210
guint stream_size
stream_size
Definition: libheraia.h:150
gchar * decode_C_date(guchar *data, gpointer data_struct)
general purpose of this function is to take a 4 byte data stream and convert it as if it is a C date...
Definition: decode.c:659
guint endianness
endianness
Definition: libheraia.h:149
decode_generic_t * new_decode_generic_t(const gchar *label, guint data_size, gboolean fixed_size, const gchar *err_msg, guint nb_cols,...)
Make a new decode_generic_t structure and creates the associated widgets.
Definition: decode.c:1018
Basic way to have as many as we want decoding functions corresponding to one label.
Definition: libheraia.h:176
decode_t * new_decode_t(DecodeFunc decode_func, GtkWidget *entry, const gchar *err_msg)
Make a new decode_t structure.
Definition: decode.c:983
Used to pass decoding options to the functions.
Definition: libheraia.h:147
gchar * decode_16bits_signed(guchar *data, gpointer data_struct)
general purpose of this function is to take a 2 byte data stream and convert it as if it is a 16 bits...
Definition: decode.c:95