Home | History | Annotate | Line # | Download | only in common
      1 /*
      2  * File:	Version.cpp
      3  *
      4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
      5  * See included license file for license details.
      6  */
      7 
      8 #include "Version.h"
      9 #include "EndianUtilities.h"
     10 
     11 using namespace elftosb;
     12 
     13 /*!
     14  * Parses a string in the form "xxx.xxx.xxx" (where x is a digit) into
     15  * three version fields for major, minor, and revision. The output is
     16  * right aligned BCD in host-natural byte order.
     17  *
     18  * \param versionString String containing the version.
     19  */
     20 void version_t::set(const std::string & versionString)
     21 {
     22 	size_t length = versionString.size();
     23 	unsigned version = 0;
     24 	unsigned index = 0;
     25 
     26 	typedef enum {
     27 		kVersionStateNone,
     28 		kVersionStateMajor,
     29 		kVersionStateMinor,
     30 		kVersionStateRevision
     31 	} VersionParseState;
     32 
     33 	// set initial versions to 0s
     34 	m_major = 0;
     35 	m_minor = 0;
     36 	m_revision = 0;
     37 
     38 	VersionParseState parseState = kVersionStateNone;
     39 	bool done = false;
     40 	for (; index < length && !done; ++index)
     41 	{
     42 		char c = versionString[index];
     43 
     44 		if (isdigit(c))
     45 		{
     46 			switch (parseState)
     47 			{
     48 				case kVersionStateNone:
     49 					parseState = kVersionStateMajor;
     50 					version = c - '0';
     51 					break;
     52 				case kVersionStateMajor:
     53 				case kVersionStateMinor:
     54 				case kVersionStateRevision:
     55 					version = (version << 4) | (c - '0');
     56 					break;
     57 			}
     58 		}
     59 		else if (c == '.')
     60 		{
     61 			switch (parseState)
     62 			{
     63 				case kVersionStateNone:
     64 					parseState = kVersionStateNone;
     65 					break;
     66 				case kVersionStateMajor:
     67 					m_major = version;
     68 					version = 0;
     69 					parseState = kVersionStateMinor;
     70 					break;
     71 				case kVersionStateMinor:
     72 					m_minor = version;
     73 					version = 0;
     74 					parseState = kVersionStateRevision;
     75 					break;
     76 				case kVersionStateRevision:
     77 					m_revision = version;
     78 					version = 0;
     79 					done = true;
     80 					break;
     81 			}
     82 		}
     83 		else
     84 		{
     85 			switch (parseState)
     86 			{
     87 				case kVersionStateNone:
     88 					parseState = kVersionStateNone;
     89 					break;
     90 				case kVersionStateMajor:
     91 					m_major = version;
     92 					done = true;
     93 					break;
     94 				case kVersionStateMinor:
     95 					m_minor = version;
     96 					done = true;
     97 					break;
     98 				case kVersionStateRevision:
     99 					m_revision = version;
    100 					done = true;
    101 					break;
    102 			}
    103 		}
    104 	}
    105 
    106 	switch (parseState)
    107 	{
    108 		case kVersionStateMajor:
    109 			m_major = version;
    110 			break;
    111 		case kVersionStateMinor:
    112 			m_minor = version;
    113 			break;
    114 		case kVersionStateRevision:
    115 			m_revision = version;
    116 			break;
    117 		default:
    118 			// do nothing
    119 			break;
    120 	}
    121 }
    122 
    123 //! \brief Converts host endian BCD version values to the equivalent big-endian BCD values.
    124 //!
    125 //! The output is a half-word. And BCD is inherently big-endian, or byte ordered, if
    126 //! you prefer to think of it that way. So for little endian systems, we need to convert
    127 //! the output half-word in reverse byte order. When it is written to disk or a
    128 //! buffer it will come out big endian.
    129 //!
    130 //! For example:
    131 //!     - The input is BCD in host endian format, so 0x1234. Written to a file, this would
    132 //!       come out as 0x34 0x12, reverse of what we want.
    133 //!     - The desired BCD output is the two bytes 0x12 0x34.
    134 //!     - So the function's uint16_t result must be 0x3412 on a little-endian host.
    135 //!
    136 //! On big endian hosts, we don't have to worry about byte swapping.
    137 void version_t::fixByteOrder()
    138 {
    139 	m_major = ENDIAN_HOST_TO_BIG_U16(m_major);
    140 	m_minor = ENDIAN_HOST_TO_BIG_U16(m_minor);
    141 	m_revision = ENDIAN_HOST_TO_BIG_U16(m_revision);
    142 }
    143 
    144