blob: 11e02d4df0baa0680495e1c117b12c342304c0e5 [file] [log] [blame]
srs569420e2a972010-02-04 00:55:04 -05001//
2// C++ Implementation: GUIDData
3//
4// Description: GUIDData class header
5// Implements the GUIDData data structure and support methods
6//
7//
8// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2010
9//
10// Copyright: See COPYING file that comes with this distribution
11//
12//
13
14#define __STDC_LIMIT_MACROS
15#define __STDC_CONSTANT_MACROS
16
17#include <stdio.h>
srs56945a081752010-09-24 20:39:41 -040018#include <time.h>
srs569420e2a972010-02-04 00:55:04 -050019#include <string>
20#include <iostream>
21#include "guid.h"
22#include "support.h"
23
24using namespace std;
25
26GUIDData::GUIDData(void) {
srs56945a081752010-09-24 20:39:41 -040027 srand(time(0));
srs569420e2a972010-02-04 00:55:04 -050028 Zero();
29} // constructor
30
31GUIDData::GUIDData(const GUIDData & orig) {
32 int i;
33
34 for (i = 0; i < 16; i++)
35 uuidData[i] = orig.uuidData[i];
36} // copy constructor
37
38GUIDData::GUIDData(const char * orig) {
39 operator=(orig);
40} // copy (from char*) constructor
41
42GUIDData::~GUIDData(void) {
43} // destructor
44
45GUIDData & GUIDData::operator=(const GUIDData & orig) {
46 int i;
47
48 for (i = 0; i < 16; i++)
49 uuidData[i] = orig.uuidData[i];
50 return *this;
51} // GUIDData::operator=(const GUIDData & orig)
52
53// Assign the GUID from a string input value. A GUID is normally formatted
54// with four dashes as element separators, for a total length of 36
55// characters. If the input string is this long or longer, this function
56// assumes standard separator positioning; if the input string is less
57// than 36 characters long, this function assumes the input GUID has
58// been compressed by removal of separators. In either event, there's
59// little in the way of sanity checking, so garbage in = garbage out!
srs56948f1b2d62010-05-23 13:07:19 -040060// One special case: If the first character is 'r' or 'R', a random
61// GUID is assigned.
srs569420e2a972010-02-04 00:55:04 -050062GUIDData & GUIDData::operator=(const string & orig) {
63 string copy, fragment;
64 size_t len;
65 // Break points for segments, either with or without characters separating the segments....
66 size_t longSegs[6] = {0, 9, 14, 19, 24, 36};
67 size_t shortSegs[6] = {0, 8, 12, 16, 20, 32};
srs569455d92612010-03-07 22:16:07 -050068 size_t *segStart = longSegs; // Assume there are separators between segments
srs569420e2a972010-02-04 00:55:04 -050069
srs56948f1b2d62010-05-23 13:07:19 -040070 // If first character is an 'R' or 'r', set a random GUID; otherwise,
71 // try to parse it as a real GUID
72 if ((orig[0] == 'R') || (orig[0] == 'r')) {
73 Randomize();
74 } else {
75 Zero();
srs569420e2a972010-02-04 00:55:04 -050076
srs56948f1b2d62010-05-23 13:07:19 -040077 // Delete stray spaces....
78 copy = DeleteSpaces(orig);
srs569420e2a972010-02-04 00:55:04 -050079
srs56948f1b2d62010-05-23 13:07:19 -040080 // If length is too short, assume there are no separators between segments
81 len = copy.length();
82 if (len < 36) {
83 segStart = shortSegs;
84 };
srs569420e2a972010-02-04 00:55:04 -050085
srs56948f1b2d62010-05-23 13:07:19 -040086 // Extract data fragments at fixed locations and convert to
87 // integral types....
88 if (len >= segStart[1]) {
89 uuidData[3] = StrToHex(copy, 0);
90 uuidData[2] = StrToHex(copy, 2);
91 uuidData[1] = StrToHex(copy, 4);
92 uuidData[0] = StrToHex(copy, 6);
93 } // if
94 if (len >= segStart[2]) {
95 uuidData[5] = StrToHex(copy, segStart[1]);
96 uuidData[4] = StrToHex(copy, segStart[1] + 2);
97 } // if
98 if (len >= segStart[3]) {
99 uuidData[7] = StrToHex(copy, segStart[2]);
100 uuidData[6] = StrToHex(copy, segStart[2] + 2);
101 } // if
102 if (len >= segStart[4]) {
103 uuidData[8] = StrToHex(copy, segStart[3]);
104 uuidData[9] = StrToHex(copy, segStart[3] + 2);
105 } // if
106 if (len >= segStart[5]) {
107 uuidData[10] = StrToHex(copy, segStart[4]);
108 uuidData[11] = StrToHex(copy, segStart[4] + 2);
109 uuidData[12] = StrToHex(copy, segStart[4] + 4);
110 uuidData[13] = StrToHex(copy, segStart[4] + 6);
111 uuidData[14] = StrToHex(copy, segStart[4] + 8);
112 uuidData[15] = StrToHex(copy, segStart[4] + 10);
113 } // if
114 } // if/else randomize/set value
srs569420e2a972010-02-04 00:55:04 -0500115
116 return *this;
117} // GUIDData::operator=(const string & orig)
118
119// Assignment from C-style string; rely on C++ casting....
120GUIDData & GUIDData::operator=(const char * orig) {
121 return operator=((string) orig);
122} // GUIDData::operator=(const char * orig)
123
srs569420e2a972010-02-04 00:55:04 -0500124// Erase the contents of the GUID
125void GUIDData::Zero(void) {
126 int i;
127
128 for (i = 0; i < 16; i++) {
129 uuidData[i] = 0;
130 } // for
131} // GUIDData::Zero()
132
133// Set a completely random GUID value....
134// The uuid_generate() function returns a value that needs to have its
135// first three fields byte-reversed to conform to Intel's GUID layout.
136// If that function isn't defined (e.g., on Windows), set a completely
137// random GUID -- not completely kosher, but it doesn't seem to cause
138// any problems (so far...)
139void GUIDData::Randomize(void) {
140#ifdef _UUID_UUID_H
141 uuid_generate(uuidData);
142 ReverseBytes(&uuidData[0], 4);
143 ReverseBytes(&uuidData[4], 2);
144 ReverseBytes(&uuidData[6], 2);
145#else
146 int i;
147 for (i = 0; i < 16; i++)
srs56945a081752010-09-24 20:39:41 -0400148 uuidData[i] = (unsigned char) (256.0 * (rand() / (RAND_MAX + 1.0)));
srs569420e2a972010-02-04 00:55:04 -0500149#endif
150} // GUIDData::Randomize
151
152// Equality operator; returns 1 if the GUIDs are equal, 0 if they're unequal
srs56945a081752010-09-24 20:39:41 -0400153int GUIDData::operator==(const GUIDData & orig) const {
srs569420e2a972010-02-04 00:55:04 -0500154 int retval = 1; // assume they're equal
155 int i;
156
157 for (i = 0; i < 16; i++)
158 if (uuidData[i] != orig.uuidData[i])
159 retval = 0;
160
161 return retval;
162} // GUIDData::operator==
163
164// Inequality operator; returns 1 if the GUIDs are unequal, 0 if they're equal
srs56945a081752010-09-24 20:39:41 -0400165int GUIDData::operator!=(const GUIDData & orig) const {
srs569420e2a972010-02-04 00:55:04 -0500166 return !operator==(orig);
167} // GUIDData::operator!=
168
169// Return the GUID as a string, suitable for display to the user.
srs56945a081752010-09-24 20:39:41 -0400170string GUIDData::AsString(void) const {
srs569420e2a972010-02-04 00:55:04 -0500171 char theString[40];
172
173 sprintf(theString,
174 "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
175 uuidData[3], uuidData[2], uuidData[1], uuidData[0], uuidData[5],
176 uuidData[4], uuidData[7], uuidData[6], uuidData[8], uuidData[9],
177 uuidData[10], uuidData[11], uuidData[12], uuidData[13], uuidData[14],
178 uuidData[15]);
179 return theString;
180} // GUIDData::AsString(void)
181
182// Delete spaces or braces (which often enclose GUIDs) from the orig string,
183// returning modified string.
srs569455d92612010-03-07 22:16:07 -0500184string GUIDData::DeleteSpaces(string s) {
srs569420e2a972010-02-04 00:55:04 -0500185 size_t position;
186
srs569455d92612010-03-07 22:16:07 -0500187 if (s.length() > 0) {
188 for (position = s.length(); position > 0; position--) {
189 if ((s[position - 1] == ' ') || (s[position - 1] == '{') || (s[position - 1] == '}')) {
190 s.erase(position - 1, 1);
191 } // if
192 } // for
193 } // if
194 return s;
srs569420e2a972010-02-04 00:55:04 -0500195} // GUIDData::DeleteSpaces()
srs56945a081752010-09-24 20:39:41 -0400196
197/*******************************
198 * *
199 * Non-class support functions *
200 * *
201 *******************************/
202
203// Display a GUID as a string....
204ostream & operator<<(ostream & os, const GUIDData & data) {
205 string asString;
206
207 os << data.AsString();
208 return os;
209} // GUIDData::operator<<()