decode.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003   decode.c
00004   Heraia's library decode.c
00005 
00006   (C) Copyright 2008 - 2009 Sébastien Tricaud, Olivier Delhomme
00007   e-mail : heraia@delhomme.org
00008   URL    : http://heraia.tuxfamily.org
00009 
00010   This program is free software; you can redistribute it and/or modify
00011   it under the terms of the GNU General Public License as published by
00012   the Free Software Foundation; either version 2, or  (at your option)
00013   any later version.
00014 
00015   This program is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018   GNU General Public License for more details.
00019 
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
00023 /**
00024  * @file decode.c
00025  * This file include all functions that may help in decoding a binary stream
00026  * to something else such as numbers, dates, other binary stream and so on
00027  * @todo I see, while putting some functions documentation that there may be
00028  *       things to do to improve speed with date calculations -> should we fill
00029  *       tab_ns_months at every function calls ? This may not be necessary
00030  */
00031 #include <libheraia.h>
00032 
00033 static gboolean bissextile_year(guint32 year);
00034 static void calc_which_month_day(date_and_time_t *mydate, guint32 day, guint tab_ns_months[12]);
00035 static void which_month_day(date_and_time_t *mydate, guint32 day, gboolean bi);
00036 static guint32 remove_days_from_first_january(guint32 base_year, guint8 base_month, guint8 base_day);
00037 static void which_year_month_day(date_and_time_t *mydate, guint32 days, guint32 base_year, guint base_month, guint8 base_day);
00038 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);
00039 static void transform_bcd_to_human(gchar *bcd, guint8 part, guint8 part_number);
00040 
00041 /**
00042  * @fn gchar *decode_8bits_signed(guchar *data)
00043  *  General purpose of this function is to take a 1 byte data stream
00044  *  and convert it as if it is an 8 bits signed number
00045  *  @param data : 1 guchar
00046  *  @return returns a gchar * that may be freed when no longer needed
00047  */
00048 gchar *decode_8bits_signed(guchar *data)
00049 {
00050         gint8 total = 0;
00051 
00052         if (data == NULL)
00053                 {
00054                         return NULL;
00055                 }
00056         else
00057                 {
00058                         memcpy(&total, data, sizeof (guchar));
00059                         return g_strdup_printf("%d", total);
00060                 }
00061 }
00062 
00063 
00064 /**
00065  * @fn gchar *decode_8bits_unsigned(guchar *data)
00066  *  general purpose of this function is to take a 1 byte data stream
00067  *  and convert it as if it is an 8 bits unsigned number
00068  *  @param data : 1 guchar
00069  *  @return returns a gchar * that may be freed when no longer needed
00070 */
00071 gchar *decode_8bits_unsigned(guchar *data)
00072 {
00073         guint8 total = 0;
00074 
00075         if (data == NULL)
00076                 {
00077                         return NULL;
00078                 }
00079         else
00080                 {
00081                         memcpy(&total, data, sizeof (guchar));
00082                         return g_strdup_printf("%u", total);
00083                 }
00084 }
00085 
00086 
00087 
00088 /**
00089  * @fn gchar *decode_16bits_signed(guchar *data)
00090  *  general purpose of this function is to take a 2 byte data stream
00091  *  and convert it as if it is a 16 bits signed number
00092  *  @param data : 2 guchars
00093  *  @return returns a gchar * that may be freed when no longer needed
00094  */
00095 gchar *decode_16bits_signed(guchar *data)
00096 {
00097         gint16 total = 0;
00098 
00099         if (data == NULL)
00100                 {
00101                         return NULL;
00102                 }
00103         else
00104                 {
00105                         memcpy(&total, data, 2 * sizeof (guchar));
00106                         return g_strdup_printf("%d", total);
00107                 }
00108 }
00109 
00110 
00111 /**
00112  * @fn gchar *decode_16bits_unsigned(guchar *data)
00113  *  general purpose of this function is to take a 2 byte data stream
00114  *  and convert it as if it is a 16 bits unsigned number
00115  *  @param data : 2 guchars
00116  *  @return returns a gchar * that may be freed when no longer needed
00117  */
00118 gchar *decode_16bits_unsigned(guchar *data)
00119 {
00120         guint16 total = 0;
00121 
00122         if (data == NULL)
00123                 {
00124                         return NULL;
00125                 }
00126         else
00127                 {
00128                         memcpy(&total, data, 2 * sizeof (guchar));
00129                         return g_strdup_printf("%u", total);
00130                 }
00131 }
00132 
00133 
00134 /**
00135  * @fn gchar *decode_32bits_signed(guchar *data)
00136  *  general purpose of this function is to take a 4 byte data stream
00137  *  and convert it as if it is a 32 bits signed number
00138  *  @param data : 4 guchars
00139  *  @return returns a gchar * that may be freed when no longer needed
00140 */
00141 gchar *decode_32bits_signed(guchar *data)
00142 {
00143         gint32 total = 0;
00144 
00145         if (data == NULL)
00146                 {
00147                         return NULL;
00148                 }
00149         else
00150                 {
00151                         memcpy(&total, data, 4 * sizeof (guchar));
00152                         return g_strdup_printf("%d", total);
00153                 }
00154 }
00155 
00156 
00157 /**
00158  * @fn gchar *decode_32bits_unsigned(guchar *data)
00159  *  general purpose of this function is to take a 4 byte data stream
00160  *  and convert it as if it is a 32 bits unsigned number
00161  *  @param data : 4 guchars
00162  *  @return returns a gchar * that may be freed when no longer needed
00163 */
00164 gchar *decode_32bits_unsigned(guchar *data)
00165 {
00166         guint32 total = 0;
00167 
00168         if (data == NULL)
00169                 {
00170                         return NULL;
00171                 }
00172         else
00173                 {
00174                         memcpy(&total, data, 4 * sizeof (guchar));
00175                         return g_strdup_printf("%u", total);
00176                 }
00177 }
00178 
00179 /**
00180  * @fn gchar *decode_64bits_signed(guchar *data)
00181  *  general purpose of this function is to take a 8 byte data stream
00182  *  and convert it as if it is a 64 bits signed number
00183  *  @param data : 8 guchars
00184  *  @return returns a gchar * that may be freed when no longer needed
00185 */
00186 gchar *decode_64bits_signed(guchar *data)
00187 {
00188         gint64 total = 0;
00189 
00190         if (data == NULL)
00191                 {
00192                         return NULL;
00193                 }
00194         else
00195                 {
00196                         memcpy(&total, data, 8 * sizeof (guchar));
00197                         return g_strdup_printf("%lld", total);
00198                 }
00199 }
00200 
00201 
00202 /**
00203  * @fn gchar *decode_64bits_unsigned(guchar *data)
00204  *  general purpose of this function is to take a 8 byte data stream
00205  *  and convert it as if it is a 64 bits unsigned number
00206  *  @param data : 8 guchars
00207  *  @return returns a gchar * that may be freed when no longer needed
00208 */
00209 gchar *decode_64bits_unsigned(guchar *data)
00210 {
00211         guint64 total = 0;
00212 
00213         if (data == NULL)
00214                 {
00215                         return NULL;
00216                 }
00217         else
00218                 {
00219                         memcpy(&total, data, 8 * sizeof (guchar));
00220                         return g_strdup_printf("%llu", total);
00221                 }
00222 }
00223 
00224 
00225 /**
00226  * @fn static gboolean bissextile_year(guint32 year)
00227  *  Says whether a year is a leap one or not
00228  * @param year : a guint32 representing a year such as 2009
00229  * @return TRUE if it's a leap year FALSE instead.
00230  */
00231 static gboolean bissextile_year(guint32 year)
00232 {
00233         if ((year % 4) == 0)
00234                 {
00235                         if ((year % 100) == 0)
00236                                 {
00237                                         if ((year % 400) == 0)
00238                                                 {
00239                                                         return TRUE;
00240                                                 }
00241                                         else
00242                                                 {
00243                                                         return FALSE;
00244                                                 }
00245                                 }
00246                         else
00247                                 {
00248                                         return TRUE;
00249                                 }
00250                 }
00251         else
00252                 {
00253                         return FALSE;
00254                 }
00255 }
00256 
00257 
00258 /**
00259  * @fn void calc_which_month_day(date_and_time_t *mydate, guint32 day, guint tab_ns_months[12])
00260  *  Says, from a number of days (eg 154), which month it is (eg  may)
00261  *  and which day in the corresponding month (eg 2 (leap year) or 3)
00262  *  @param[out] mydate : Filled date structure
00263  *      @param day : guint32 representing the number of day in the year (1..365/366)
00264  *  @param tab_ns_months : an array filled with the cumulative number of days for each month (31 to 365/366)
00265  */
00266 static void calc_which_month_day(date_and_time_t *mydate, guint32 day, guint tab_ns_months[12])
00267 {
00268         gushort i = 0;
00269 
00270         while (i<12 && day > tab_ns_months[i])
00271                 {
00272                         i++;
00273                 }
00274 
00275         mydate->month = i + 1;
00276 
00277         if (i == 0)
00278                 {
00279                         mydate->day = 1 + day;
00280                 }
00281         else
00282                 {
00283                         mydate->day = (1 + day) - tab_ns_months[i-1];
00284                 }
00285 }
00286 
00287 /**
00288  * @fn void which_month_day(date_and_time_t *mydate, guint32 day, gboolean bi)
00289  *  Front end function for the calc_which_month_day function !
00290  * @param[out] mydate : Filled date structure
00291  * @param day : guint32 representing the number of day in the year (1..365/366)
00292  * @param bi : TRUE if it's a leap year, FALSE instead
00293  */
00294 static void which_month_day(date_and_time_t *mydate, guint32 day, gboolean bi)
00295 {
00296 
00297         if (bi == TRUE)
00298                 {
00299                         if (day <= 366)
00300                                 {
00301                                         guint tab_ns_months[12] = { 31, 60, 91, 121, 152, 182,
00302                                                                                                                  213, 244, 274, 305, 335, 366 } ;
00303                                         calc_which_month_day(mydate, day, tab_ns_months);
00304                                 }
00305                         else
00306                                 {
00307                                         mydate->day = 0;
00308                                         mydate->month = 0;
00309                                 }
00310                 }
00311         else
00312                 {
00313                         if (day <= 365)
00314                                 {
00315                                         guint tab_ns_months[12] = { 31, 59, 90, 120, 151, 181,
00316                                                                                                                  212, 243, 273, 304, 334, 365 };
00317                                         calc_which_month_day(mydate, day, tab_ns_months);
00318                                 }
00319                         else
00320                                 {
00321                                         mydate->day = 0;
00322                                         mydate->month = 0;
00323                                 }
00324                 }
00325 }
00326 
00327 /**
00328  * @fn guint32 remove_days_from_first_january(guint32 base_year, guint8 base_month, guint8 base_day)
00329  *  Returns the number of days since 01/01/base_year
00330  *  eg 15/02/base_year --> 31 + 15 = 46
00331  * @param base_year : year where we want to begin the calculation
00332  * @param base_month : month (in the example 02)
00333  * @param base_day : day in the month (from the example 15)
00334  * @return returns a number of days since begining of the year (eg 1..365/366)
00335  */
00336 static guint32 remove_days_from_first_january(guint32 base_year, guint8 base_month, guint8 base_day)
00337 {
00338         guint tab_ns_months[11];
00339 
00340         if (base_day > 0 && base_day < 32)
00341                 {
00342                         base_day -= 1;
00343                 }
00344         else
00345                 {
00346                         return 0;  /* Obviously something might be wrong if we fall here */
00347                 }
00348 
00349         tab_ns_months[0] = 31;
00350         if (bissextile_year(base_year))
00351                 {
00352                         tab_ns_months[1] = 60;
00353                         tab_ns_months[2] = 91;
00354                         tab_ns_months[3] = 121;
00355                         tab_ns_months[4] = 152;
00356                         tab_ns_months[5] = 182;
00357                         tab_ns_months[6] = 213;
00358                         tab_ns_months[7] = 244;
00359                         tab_ns_months[8] = 274;
00360                         tab_ns_months[9] = 305;
00361                         tab_ns_months[10] = 335;
00362                 }
00363         else
00364                 {
00365                         tab_ns_months[1] = 59;
00366                         tab_ns_months[2] = 90;
00367                         tab_ns_months[3] = 120;
00368                         tab_ns_months[4] = 151;
00369                         tab_ns_months[5] = 181;
00370                         tab_ns_months[6] = 212;
00371                         tab_ns_months[7] = 243;
00372                         tab_ns_months[8] = 273;
00373                         tab_ns_months[9] = 304;
00374                         tab_ns_months[10] = 334;
00375                 }
00376 
00377         if (base_month > 1 && base_month < 13)
00378                 {
00379                         return (tab_ns_months[base_month-2] + base_day);
00380                 }
00381         else if (base_month == 1)
00382                 {
00383                         return base_day;
00384                 }
00385         else
00386                 {
00387                         return 0;
00388                 }
00389 }
00390 
00391 
00392 
00393 /**
00394  * @fn void which_year_month_day(date_and_time_t *mydate, guint32 days, guint32 base_year, guint base_month, guint8 base_day)
00395  * About date calculation : Leap years are periods of 4 years except
00396  * the years that we can divide by 100 and not 400.
00397  * So we can distinguish 2 periods : one of 400 years and one of 4 years.
00398  *  - we have 100 bissextiles years in a period of 400 years this means that
00399  *    every 400 years we have exactly 146100 days.
00400  *  - we have 1 bissextile year every 4 years : this means that we have exactly
00401  *    1461 days every 4 years.
00402  *  As we can calculate _exactly_ the number of days in a filetime or C_date
00403  *  format, we could calculate _exactly_ the number of periods of 400 years and
00404  *  then the number of periods of 4 years.
00405  * @param[out] mydate : Filled date structure
00406  * @param days : number of days calculated
00407  * @param base_year : base year used for calculation (eg 1601 for filetime)
00408  * @param base_month : base month used for calculation (eg 01, january for filetime)
00409  * @param base_day : base day used for calculation (eg 01 for filetime)
00410 */
00411 static void which_year_month_day(date_and_time_t *mydate, guint32 days, guint32 base_year, guint base_month, guint8 base_day)
00412 {
00413         guint32 modulus = 0;
00414         guint32 reste = 0;
00415         guint32 nbdays = 0;
00416 
00417         days -= remove_days_from_first_january(base_year, base_month, base_day);
00418 
00419         if (days > 146100)
00420                 {
00421                         modulus = days / 146100;
00422                         mydate->year = modulus * 400;
00423                         reste = modulus * 3;     /* To add centuries in the 400 years modulus */
00424                         days = days % 146100;
00425                 }
00426 
00427         modulus = days / 1461;
00428         mydate->year += modulus * 4;
00429         reste += (modulus*4) / 100;    /* To add centuries */
00430         reste += days % 1461;
00431 
00432         mydate->year += base_year;
00433         if (bissextile_year(mydate->year))
00434                 nbdays = 366;
00435         else
00436                 nbdays = 365;
00437 
00438         while (reste > nbdays)
00439                 {
00440                         reste -= nbdays;
00441                         mydate->year += 1;
00442                         if (bissextile_year(mydate->year))
00443                                 nbdays = 366;
00444                         else
00445                                 nbdays = 365;
00446                 }
00447 
00448         which_month_day(mydate, reste, bissextile_year(mydate->year));
00449 }
00450 
00451 
00452 /**
00453  * @fn gchar *date_printf(date_and_time_t *mydate)
00454  *  Return a gchar * that contains the date and time
00455  *  encoded from the values contained in the date_and_time_t structure
00456  *  it may be freed when no longer needed
00457  *  We do not use any of the g_date_strftime or strftime function
00458  *  because interpreted dates are not always valid !
00459  * @param[in] mydate : structure that contains a date
00460  * @return returns a gchar * printed out in a french like format "dd/mm/aaaa - hh:mm:ss"
00461  * @todo Add a way to use a user defined format and/or predefined formats
00462  */
00463 static gchar *date_printf(date_and_time_t *mydate)
00464 {
00465         return g_strdup_printf("%02u/%02u/%04u - %02u:%02u:%02u", mydate->day, mydate->month, mydate->year, mydate->hour, mydate->minutes, mydate->seconds);
00466 }
00467 
00468 
00469 /**
00470  * @fn gchar *decode_dos_date(guchar *data, date_and_time_t *mydate)
00471  *  general purpose of this function is to take a 4 byte data stream
00472  *  and convert it as if it is a dos date. If it is not, the result
00473  *  may be funny !
00474  *  @param data : 4 guchars
00475  *  @param[out] mydate : date_and_time_t * structure that contain the resulting date
00476  *  @return returns a gchar * that may be freed when no longer needed
00477 */
00478 gchar *decode_dos_date(guchar *data, date_and_time_t *mydate)
00479 {
00480 
00481         if (data == NULL)
00482                 {
00483                         return NULL;
00484                 }
00485         else
00486                 {
00487                         mydate->year = (data[3] >> 1) + 1980;
00488                         mydate->month = ((data[3] & 0x01) << 3) + (data[2] >> 5);
00489                         mydate->day = data[2] & 0x1F;
00490                         mydate->hour = (data[1] & 0xF8) >> 3;
00491                         mydate->minutes = ((data[1] & 0x07) << 3) + ((data[0] & 0xE0) >> 5);
00492                         mydate->seconds = (data[0] & 0x1F) << 1;
00493 
00494                         return date_printf(mydate);
00495                 }
00496 }
00497 
00498 
00499 /**
00500  * @fn 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)
00501  *  Reads the data from the stream (specified length !! <= 8 or 64 bits to decode)
00502  *  @param[out] mydate : date_and_time_t * structure that contain the resulting date
00503  *  @param data : a guchar * as a stream to decode as a date
00504  *  @param len : guint8 as length of the stream in bytes (must be <= 8 or 64 bits to decode)
00505  *  @param nbticks : guint64 that tells the number of ticks per seconds (1, 1000, ...)
00506  *  @param base_year : guint32, Epoch year (1970, 1904, ...)
00507  *  @param base_month : guint32, Epoch month (january, ...)
00508  *  @param base_day : guint32 Epoch day (01, 15, ...)
00509  *  @return populates the date_and_time_t structure (my_date)
00510 */
00511 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)
00512 {
00513         guint64 total = 0;
00514         guint32 days = 0;
00515 
00516         memcpy(&total, data, len * sizeof (guchar));
00517 
00518         total = (total / nbticks);         /* 1 seconds represents nbticks */
00519         days = (guint32) (total / 86400);  /* 86400 seconds a day          */;
00520 
00521         which_year_month_day(mydate, days, base_year, base_month, base_day);
00522 
00523         mydate->hour = ((total % 86400) / 3600);  /* 3600 seconds is one hour out of one day */
00524         mydate->minutes = ((total % 3600) / 60);  /* 60 seconds is one minute out of one hour */
00525         mydate->seconds = (total % 60);
00526 }
00527 
00528 
00529 /**
00530  * @fn gchar *decode_filetime_date(guchar *data, date_and_time_t *mydate)
00531  *  general purpose of this function is to take a 8 byte data stream
00532  *  and convert it as if it is a filetime date. If it is not, the result
00533  *  may be funny ! Counting 100th of nanoseconds from 01/01/1601
00534  *  @param data : 8 guchars
00535  *  @param[out] mydate : date_and_time_t * structure that contain the resulting date
00536  *  @return returns a gchar * that may be freed when no longer needed
00537 */
00538 gchar *decode_filetime_date(guchar *data, date_and_time_t *mydate)
00539 {
00540         if (data == NULL)
00541                 {
00542                         return NULL;
00543                 }
00544         else
00545                 {
00546                         make_date_and_time(mydate, data, 8, 10000000, 1601, 1, 1);
00547                         return date_printf(mydate);
00548                 }
00549 }
00550 
00551 
00552 /**
00553  * @fn gchar *decode_C_date(guchar *data, date_and_time_t *mydate)
00554  *  general purpose of this function is to take a 4 byte data stream
00555  *  and convert it as if it is a C date. If it is not, the result may
00556  *  be funny ! Counting seconds from 01/01/1970
00557  *  @param data : 4 guchars
00558  *  @param[out] mydate : date_and_time_t * structure that contain the resulting date
00559  *  @return returns a gchar * that may be freed when no longer needed
00560 */
00561 gchar *decode_C_date(guchar *data, date_and_time_t *mydate)
00562 {
00563         if (data == NULL)
00564                 {
00565                         return NULL;
00566                 }
00567         else
00568                 {
00569                         make_date_and_time(mydate, data, 4, 1, 1970, 1, 1);
00570                         return date_printf(mydate);
00571                 }
00572 }
00573 
00574 /**
00575  * @fn gchar *decode_HFS_date(guchar *data, date_and_time_t *mydate)
00576  *  general purpose of this function is to take a 4 byte data stream
00577  *  and convert it as if it is a HFS date. If it is not, the result may
00578  *  be funny ! Counting seconds 01/01/1904
00579  *  @param data : 4 guchars
00580  *  @param[out] mydate : date_and_time_t * structure that contain the resulting date
00581  *  @return returns a gchar* that may be freed when no longer needed
00582 */
00583 gchar *decode_HFS_date(guchar *data, date_and_time_t *mydate)
00584 {
00585         if (data == NULL)
00586                 {
00587                         return NULL;
00588                 }
00589         else
00590                 {
00591                         make_date_and_time(mydate, data, 4, 1, 1904, 1, 1);
00592                         return date_printf(mydate);
00593                 }
00594 }
00595 
00596 
00597 
00598 /**
00599  * @fn gchar *decode_to_bits(guchar *data)
00600  *  decodes the stream represented by *data (one byte) to a
00601  *  string containing eight 0 or 1 (Little Endian style)
00602  *  @param data : 1 guchar
00603  *  @return 8 gchars that are either "1" or "0", the string may be freed when
00604  *          no longer needed
00605  */
00606 gchar *decode_to_bits(guchar *data)
00607 {
00608 
00609         if (data == NULL)
00610                 {
00611                         return NULL;
00612                 }
00613         else
00614                 {
00615                         return g_strdup_printf("%1u%1u%1u%1u%1u%1u%1u%1u",
00616                                                                                   (data[0] & 0x80) > 0 ? 1 : 0,
00617                                                                                   (data[0] & 0x40) > 0 ? 1 : 0,
00618                                                                                   (data[0] & 0x20) > 0 ? 1 : 0,
00619                                                                                   (data[0] & 0x10) > 0 ? 1 : 0,
00620                                                                                   (data[0] & 0x08) > 0 ? 1 : 0,
00621                                                                                   (data[0] & 0x04) > 0 ? 1 : 0,
00622                                                                                   (data[0] & 0x02) > 0 ? 1 : 0,
00623                                                                                   (data[0] & 0x01));
00624                 }
00625 }
00626 
00627 
00628 /**
00629  * @fn static void transform_bcd_to_human(gchar *bcd, guint8 part, guint8 part_number)
00630  *  transcribes the bcd number "part" into a
00631  *  @param[out] bcd : gchar * human readable string
00632  *  @param part : guint8 as an half byte to decode
00633  *  @param part_number : 0 or 1 as MSB and LSB
00634  *  Coding style is from ETSI GSM 04.08 ETS 300557 p387
00635  *  @todo give choice of coding style (eg for numbers >=10)
00636  */
00637 static void transform_bcd_to_human(gchar *bcd, guint8 part, guint8 part_number)
00638 {
00639         switch (part)
00640                 {
00641                 case 0 :
00642                         bcd[part_number] = '0';
00643                         break;
00644                 case 1 :
00645                         bcd[part_number] = '1';
00646                         break;
00647                 case 2 :
00648                         bcd[part_number] = '2';
00649                         break;
00650                 case 3 :
00651                         bcd[part_number] = '3';
00652                         break;
00653                 case 4 :
00654                         bcd[part_number] = '4';
00655                         break;
00656                 case 5 :
00657                         bcd[part_number] = '5';
00658                         break;
00659                 case 6 :
00660                         bcd[part_number] = '6';
00661                         break;
00662                 case 7 :
00663                         bcd[part_number] = '7';
00664                         break;
00665                 case 8 :
00666                         bcd[part_number] = '8';
00667                         break;
00668                 case 9 :
00669                         bcd[part_number] = '9';
00670                         break;
00671                 case 10 :
00672                         bcd[part_number] = '*';
00673                         break;
00674                 case 11 :
00675                         bcd[part_number] = '#';
00676                         break;
00677                 case 12 :
00678                         bcd[part_number] = 'a';
00679                         break;
00680                 case 13 :
00681                         bcd[part_number] = 'b';
00682                         break;
00683                 case 14 :
00684                         bcd[part_number] = 'c';
00685                         break;
00686                 case 15 :
00687                         bcd[part_number] = ' ';  /* Endmark */
00688                         break;
00689                 default :
00690                         bcd[part_number] = '?';  /* This default case should never happen */
00691                         break;
00692                 }
00693 }
00694 
00695 
00696 /**
00697  * @fn gchar *decode_packed_BCD(guchar *data)
00698  *  Decode one byte as a Packed BCD (Binary Coded Decimal)
00699  *  and return a gchar* that may be freed when no longer
00700  *  needed
00701  *  @param data : stream to decode as 1 guchar
00702  *  @return returns a gchar * that contain the packed BCD interpretation
00703  */
00704 gchar *decode_packed_BCD(guchar *data)
00705 {
00706         guint8 total = 0;
00707         gchar *bcd = NULL;
00708 
00709         if (data == NULL)
00710                 {
00711                         return NULL;
00712                 }
00713         else
00714                 {
00715                         memcpy(&total, data, sizeof(guchar));
00716                         bcd = (gchar *) g_malloc0(3 * sizeof(gchar));
00717                         transform_bcd_to_human(bcd, (total & 0x0F), 0);
00718                         transform_bcd_to_human(bcd, ((total & 0xF0)>>4), 1);
00719                         bcd[2] = '\0';
00720 
00721                         return bcd;
00722                 }
00723 }
00724 
00725 /**
00726  * @fn gboolean swap_bytes(guchar *to_swap, guint first, guint last)
00727  *  Swap bytes from the buffer to_swap
00728  *  @warning recursive function !! Call with first = 0 and last = last byte 
00729  *  of buffer to swap
00730  *  @param[in,out] to_swap : buffer to swap
00731  *  @param first : first byte in the buffer to swap
00732  *  @param last : last byte in the buffer to swap
00733  *  @return returns TRUE when first is >= to last and this end recursivity
00734  */
00735 gboolean swap_bytes(guchar *to_swap, guint first, guint last)
00736 {
00737         guchar aux;
00738 
00739         if (first >= last)
00740                 {
00741                         return TRUE;
00742                 }
00743         else
00744                 {
00745                         aux = to_swap[first];
00746                         to_swap[first] = to_swap[last];
00747                         to_swap[last] = aux;
00748                         return swap_bytes(to_swap, ++first, --last);
00749                 }
00750 }
00751 
00752 /**
00753  * @fn reverse_byte_order(guchar *to_reverse)
00754  *  Reverse the byte order LSB -> MSB in MSB -> LSB
00755  *  12345678 in 87654321
00756  * @param[in,out] to_reverse : one guchar to be reversed
00757  */
00758 void reverse_byte_order(guchar *to_reverse)
00759 {
00760         guint8 car = (guint8) to_reverse[0];
00761         guint8 aux = 0;
00762 
00763         aux = ((car & 0x80) >> 7);
00764         aux += ((car & 0x40) >> 5);
00765         aux += ((car & 0x20) >> 3);
00766         aux += ((car & 0x10) >> 1);
00767         aux += ((car & 0x08) << 1);
00768         aux += ((car & 0x04) << 3);
00769         aux += ((car & 0x02) << 5);
00770         aux += ((car & 0x01) << 7);
00771 
00772         to_reverse[0] = (guchar) aux;
00773 }

Generated on Sat Feb 14 11:44:16 2009 for Heraia by  doxygen 1.5.6