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 11using 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 */ 20void 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. 137void 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