1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
//
// C++ Implementation: GUIDData
//
// Description: GUIDData class header
// Implements the GUIDData data structure and support methods
//
//
// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2010-2011
//
// Copyright: See COPYING file that comes with this distribution
//
//
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <string>
#include <iostream>
#include "guid.h"
#include "support.h"
using namespace std;
bool GUIDData::firstInstance = 1;
GUIDData::GUIDData(void) {
if (firstInstance) {
srand((unsigned int) time(0));
firstInstance = 0;
} // if
Zero();
} // constructor
GUIDData::GUIDData(const GUIDData & orig) {
memcpy(uuidData, orig.uuidData, sizeof(uuidData));
} // copy constructor
GUIDData::GUIDData(const string & orig) {
operator=(orig);
} // copy (from string) constructor
GUIDData::GUIDData(const char * orig) {
operator=(orig);
} // copy (from char*) constructor
GUIDData::~GUIDData(void) {
} // destructor
GUIDData & GUIDData::operator=(const GUIDData & orig) {
memcpy(uuidData, orig.uuidData, sizeof(uuidData));
return *this;
} // GUIDData::operator=(const GUIDData & orig)
// Assign the GUID from a string input value. A GUID is normally formatted
// with four dashes as element separators, for a total length of 36
// characters. If the input string is this long or longer, this function
// assumes standard separator positioning; if the input string is less
// than 36 characters long, this function assumes the input GUID has
// been compressed by removal of separators. In either event, there's
// little in the way of sanity checking, so garbage in = garbage out!
// One special case: If the first character is 'r' or 'R', a random
// GUID is assigned.
GUIDData & GUIDData::operator=(const string & orig) {
string copy, fragment;
size_t len;
// Break points for segments, either with or without characters separating the segments....
size_t longSegs[6] = {0, 9, 14, 19, 24, 36};
size_t shortSegs[6] = {0, 8, 12, 16, 20, 32};
size_t *segStart = longSegs; // Assume there are separators between segments
// If first character is an 'R' or 'r', set a random GUID; otherwise,
// try to parse it as a real GUID
if ((orig[0] == 'R') || (orig[0] == 'r')) {
Randomize();
} else {
Zero();
// Delete stray spaces....
copy = DeleteSpaces(orig);
// If length is too short, assume there are no separators between segments
len = copy.length();
if (len < 36) {
segStart = shortSegs;
};
// Extract data fragments at fixed locations and convert to
// integral types....
if (len >= segStart[1]) {
uuidData[3] = StrToHex(copy, 0);
uuidData[2] = StrToHex(copy, 2);
uuidData[1] = StrToHex(copy, 4);
uuidData[0] = StrToHex(copy, 6);
} // if
if (len >= segStart[2]) {
uuidData[5] = StrToHex(copy, (unsigned int) segStart[1]);
uuidData[4] = StrToHex(copy, (unsigned int) segStart[1] + 2);
} // if
if (len >= segStart[3]) {
uuidData[7] = StrToHex(copy, (unsigned int) segStart[2]);
uuidData[6] = StrToHex(copy, (unsigned int) segStart[2] + 2);
} // if
if (len >= segStart[4]) {
uuidData[8] = StrToHex(copy, (unsigned int) segStart[3]);
uuidData[9] = StrToHex(copy, (unsigned int) segStart[3] + 2);
} // if
if (len >= segStart[5]) {
uuidData[10] = StrToHex(copy, (unsigned int) segStart[4]);
uuidData[11] = StrToHex(copy, (unsigned int) segStart[4] + 2);
uuidData[12] = StrToHex(copy, (unsigned int) segStart[4] + 4);
uuidData[13] = StrToHex(copy, (unsigned int) segStart[4] + 6);
uuidData[14] = StrToHex(copy, (unsigned int) segStart[4] + 8);
uuidData[15] = StrToHex(copy, (unsigned int) segStart[4] + 10);
} // if
} // if/else randomize/set value
return *this;
} // GUIDData::operator=(const string & orig)
// Assignment from C-style string; rely on C++ casting....
GUIDData & GUIDData::operator=(const char * orig) {
return operator=((string) orig);
} // GUIDData::operator=(const char * orig)
// Erase the contents of the GUID
void GUIDData::Zero(void) {
memset(uuidData, 0, sizeof(uuidData));
} // GUIDData::Zero()
// Set a completely random GUID value....
// The uuid_generate() function returns a value that needs to have its
// first three fields byte-reversed to conform to Intel's GUID layout.
// The Windows UuidCreate() function doesn't need this adjustment. If
// neither function is defined, or if UuidCreate() fails, set a completely
// random GUID -- not completely kosher, but it works on most platforms
// (immediately after creating the UUID on Windows 7 being an important
// exception).
void GUIDData::Randomize(void) {
int i, uuidGenerated = 0;
#if defined (_UUID_UUID_H) || defined (_UL_LIBUUID_UUID_H)
uuid_generate(uuidData);
ReverseBytes(&uuidData[0], 4);
ReverseBytes(&uuidData[4], 2);
ReverseBytes(&uuidData[6], 2);
uuidGenerated = 1;
#endif
#if defined (_RPC_H) || defined (__RPC_H__)
UUID MsUuid;
if (UuidCreate(&MsUuid) == RPC_S_OK) {
memcpy(uuidData, &MsUuid, 16);
uuidGenerated = 1;
} // if
#endif
if (!uuidGenerated) {
cerr << "Warning! Unable to generate a proper UUID! Creating an improper one as a last\n"
<< "resort! Windows 7 may crash if you save this partition table!\a\n";
for (i = 0; i < 16; i++)
uuidData[i] = (unsigned char) (256.0 * (rand() / (RAND_MAX + 1.0)));
} // if
} // GUIDData::Randomize
// Equality operator; returns 1 if the GUIDs are equal, 0 if they're unequal
int GUIDData::operator==(const GUIDData & orig) const {
return !memcmp(uuidData, orig.uuidData, sizeof(uuidData));
} // GUIDData::operator==
// Inequality operator; returns 1 if the GUIDs are unequal, 0 if they're equal
int GUIDData::operator!=(const GUIDData & orig) const {
return !operator==(orig);
} // GUIDData::operator!=
// Return the GUID as a string, suitable for display to the user.
string GUIDData::AsString(void) const {
char theString[40];
sprintf(theString,
"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
uuidData[3], uuidData[2], uuidData[1], uuidData[0], uuidData[5],
uuidData[4], uuidData[7], uuidData[6], uuidData[8], uuidData[9],
uuidData[10], uuidData[11], uuidData[12], uuidData[13], uuidData[14],
uuidData[15]);
return theString;
} // GUIDData::AsString(void)
// Delete spaces or braces (which often enclose GUIDs) from the orig string,
// returning modified string.
string GUIDData::DeleteSpaces(string s) {
size_t position;
if (s.length() > 0) {
for (position = s.length(); position > 0; position--) {
if ((s[position - 1] == ' ') || (s[position - 1] == '{') || (s[position - 1] == '}')) {
s.erase(position - 1, 1);
} // if
} // for
} // if
return s;
} // GUIDData::DeleteSpaces()
/*******************************
* *
* Non-class support functions *
* *
*******************************/
// Display a GUID as a string....
ostream & operator<<(ostream & os, const GUIDData & data) {
// string asString;
os << data.AsString();
return os;
} // GUIDData::operator<<()
|