1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "nsID.h"
8 #include "nsMemory.h"
9 #include "mozilla/Sprintf.h"
10
Clear()11 void nsID::Clear() {
12 m0 = 0;
13 m1 = 0;
14 m2 = 0;
15 memset(m3, 0, sizeof(m3));
16 }
17
18 /**
19 * Multiplies the_int_var with 16 (0x10) and adds the value of the
20 * hexadecimal digit the_char. If it fails it returns false from
21 * the function it's used in.
22 */
23
24 #define ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(the_char, the_int_var) \
25 the_int_var = (the_int_var << 4) + the_char; \
26 if (the_char >= '0' && the_char <= '9') \
27 the_int_var -= '0'; \
28 else if (the_char >= 'a' && the_char <= 'f') \
29 the_int_var -= 'a' - 10; \
30 else if (the_char >= 'A' && the_char <= 'F') \
31 the_int_var -= 'A' - 10; \
32 else \
33 return false
34
35 /**
36 * Parses number_of_chars characters from the char_pointer pointer and
37 * puts the number in the dest_variable. The pointer is moved to point
38 * at the first character after the parsed ones. If it fails it returns
39 * false from the function the macro is used in.
40 */
41
42 #define PARSE_CHARS_TO_NUM(char_pointer, dest_variable, number_of_chars) \
43 do { \
44 int32_t _i = number_of_chars; \
45 dest_variable = 0; \
46 while (_i) { \
47 ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(*char_pointer, dest_variable); \
48 char_pointer++; \
49 _i--; \
50 } \
51 } while (0)
52
53 /**
54 * Parses a hyphen from the char_pointer string. If there is no hyphen there
55 * the function returns false from the function it's used in. The
56 * char_pointer is advanced one step.
57 */
58
59 #define PARSE_HYPHEN(char_pointer) \
60 if (*(char_pointer++) != '-') return false
61
62 /*
63 * Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} string into
64 * an nsID. It can also handle the old format without the { and }.
65 */
66
Parse(const char * aIDStr)67 bool nsID::Parse(const char* aIDStr) {
68 /* Optimized for speed */
69 if (!aIDStr) {
70 return false;
71 }
72
73 bool expectFormat1 = (aIDStr[0] == '{');
74 if (expectFormat1) {
75 ++aIDStr;
76 }
77
78 PARSE_CHARS_TO_NUM(aIDStr, m0, 8);
79 PARSE_HYPHEN(aIDStr);
80 PARSE_CHARS_TO_NUM(aIDStr, m1, 4);
81 PARSE_HYPHEN(aIDStr);
82 PARSE_CHARS_TO_NUM(aIDStr, m2, 4);
83 PARSE_HYPHEN(aIDStr);
84 int i;
85 for (i = 0; i < 2; ++i) {
86 PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
87 }
88 PARSE_HYPHEN(aIDStr);
89 while (i < 8) {
90 PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
91 i++;
92 }
93
94 return expectFormat1 ? *aIDStr == '}' : true;
95 }
96
97 #ifndef XPCOM_GLUE_AVOID_NSPR
98
99 static const char gIDFormat[] =
100 "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
101
102 /*
103 * Returns an allocated string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
104 * format. The string is allocated with moz_xmalloc and should be freed by
105 * the caller.
106 */
107
ToString() const108 char* nsID::ToString() const {
109 char* res = (char*)moz_xmalloc(NSID_LENGTH);
110 snprintf(res, NSID_LENGTH, gIDFormat, m0, (uint32_t)m1, (uint32_t)m2,
111 (uint32_t)m3[0], (uint32_t)m3[1], (uint32_t)m3[2], (uint32_t)m3[3],
112 (uint32_t)m3[4], (uint32_t)m3[5], (uint32_t)m3[6], (uint32_t)m3[7]);
113 return res;
114 }
115
ToProvidedString(char (& aDest)[NSID_LENGTH]) const116 void nsID::ToProvidedString(char (&aDest)[NSID_LENGTH]) const {
117 SprintfLiteral(aDest, gIDFormat, m0, (uint32_t)m1, (uint32_t)m2,
118 (uint32_t)m3[0], (uint32_t)m3[1], (uint32_t)m3[2],
119 (uint32_t)m3[3], (uint32_t)m3[4], (uint32_t)m3[5],
120 (uint32_t)m3[6], (uint32_t)m3[7]);
121 }
122
123 #endif // XPCOM_GLUE_AVOID_NSPR
124
Clone() const125 nsID* nsID::Clone() const {
126 auto id = static_cast<nsID*>(moz_xmalloc(sizeof(nsID)));
127 *id = *this;
128 return id;
129 }
130