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