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 {
13   m0 = 0;
14   m1 = 0;
15   m2 = 0;
16   for (int i = 0; i < 8; ++i) {
17     m3[i] = 0;
18   }
19 }
20 
21 /**
22  * Multiplies the_int_var with 16 (0x10) and adds the value of the
23  * hexadecimal digit the_char. If it fails it returns false from
24  * the function it's used in.
25  */
26 
27 #define ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(the_char, the_int_var) \
28     the_int_var = (the_int_var << 4) + the_char; \
29     if(the_char >= '0' && the_char <= '9') the_int_var -= '0'; \
30     else if(the_char >= 'a' && the_char <= 'f') the_int_var -= 'a'-10; \
31     else if(the_char >= 'A' && the_char <= 'F') the_int_var -= 'A'-10; \
32     else return false
33 
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 { int32_t _i=number_of_chars; \
44   dest_variable = 0; \
45   while(_i) { \
46     ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(*char_pointer, dest_variable); \
47     char_pointer++; \
48     _i--; \
49   } } while(0)
50 
51 
52 /**
53  * Parses a hyphen from the char_pointer string. If there is no hyphen there
54  * the function returns false from the function it's used in. The
55  * char_pointer is advanced one step.
56  */
57 
58 #define PARSE_HYPHEN(char_pointer) if (*(char_pointer++) != '-') return false
59 
60 /*
61  * Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} string into
62  * an nsID. It can also handle the old format without the { and }.
63  */
64 
65 bool
Parse(const char * aIDStr)66 nsID::Parse(const char* aIDStr)
67 {
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 NS_Alloc and should be freed by
105  * the caller.
106  */
107 
108 char*
ToString() const109 nsID::ToString() const
110 {
111   char* res = (char*)NS_Alloc(NSID_LENGTH);
112 
113   if (res) {
114     snprintf(res, NSID_LENGTH, gIDFormat,
115              m0, (uint32_t)m1, (uint32_t)m2,
116              (uint32_t)m3[0], (uint32_t)m3[1], (uint32_t)m3[2],
117              (uint32_t)m3[3], (uint32_t)m3[4], (uint32_t)m3[5],
118              (uint32_t)m3[6], (uint32_t)m3[7]);
119   }
120   return res;
121 }
122 
123 void
ToProvidedString(char (& aDest)[NSID_LENGTH]) const124 nsID::ToProvidedString(char (&aDest)[NSID_LENGTH]) const
125 {
126   SprintfLiteral(aDest, gIDFormat,
127                  m0, (uint32_t)m1, (uint32_t)m2,
128                  (uint32_t)m3[0], (uint32_t)m3[1], (uint32_t)m3[2],
129                  (uint32_t)m3[3], (uint32_t)m3[4], (uint32_t)m3[5],
130                  (uint32_t)m3[6], (uint32_t)m3[7]);
131 }
132 
133 #endif // XPCOM_GLUE_AVOID_NSPR
134