1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Daniel Bratell <bratell@lysator.liu.se>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 : #include "nsID.h"
39 : #include "prprf.h"
40 : #include "nsMemory.h"
41 :
42 : static const char gIDFormat[] =
43 : "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
44 :
45 : static const char gIDFormat2[] =
46 : "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
47 :
48 :
49 : /**
50 : * Multiplies the_int_var with 16 (0x10) and adds the value of the
51 : * hexadecimal digit the_char. If it fails it returns false from
52 : * the function it's used in.
53 : */
54 :
55 : #define ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(the_char, the_int_var) \
56 : the_int_var = (the_int_var << 4) + the_char; \
57 : if(the_char >= '0' && the_char <= '9') the_int_var -= '0'; \
58 : else if(the_char >= 'a' && the_char <= 'f') the_int_var -= 'a'-10; \
59 : else if(the_char >= 'A' && the_char <= 'F') the_int_var -= 'A'-10; \
60 : else return false
61 :
62 :
63 : /**
64 : * Parses number_of_chars characters from the char_pointer pointer and
65 : * puts the number in the dest_variable. The pointer is moved to point
66 : * at the first character after the parsed ones. If it fails it returns
67 : * false from the function the macro is used in.
68 : */
69 :
70 : #define PARSE_CHARS_TO_NUM(char_pointer, dest_variable, number_of_chars) \
71 : do { PRInt32 _i=number_of_chars; \
72 : dest_variable = 0; \
73 : while(_i) { \
74 : ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(*char_pointer, dest_variable); \
75 : char_pointer++; \
76 : _i--; \
77 : } } while(0)
78 :
79 :
80 : /**
81 : * Parses a hyphen from the char_pointer string. If there is no hyphen there
82 : * the function returns false from the function it's used in. The
83 : * char_pointer is advanced one step.
84 : */
85 :
86 : #define PARSE_HYPHEN(char_pointer) if(*(char_pointer++) != '-') return false
87 :
88 : /*
89 : * Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} string into
90 : * an nsID. It can also handle the old format without the { and }.
91 : */
92 :
93 277119 : bool nsID::Parse(const char *aIDStr)
94 : {
95 : /* Optimized for speed */
96 277119 : if(!aIDStr) {
97 0 : return false;
98 : }
99 :
100 277119 : bool expectFormat1 = (aIDStr[0] == '{');
101 277119 : if(expectFormat1) aIDStr++;
102 :
103 277119 : PARSE_CHARS_TO_NUM(aIDStr, m0, 8);
104 277119 : PARSE_HYPHEN(aIDStr);
105 277119 : PARSE_CHARS_TO_NUM(aIDStr, m1, 4);
106 277119 : PARSE_HYPHEN(aIDStr);
107 277119 : PARSE_CHARS_TO_NUM(aIDStr, m2, 4);
108 277119 : PARSE_HYPHEN(aIDStr);
109 : int i;
110 831357 : for(i=0; i<2; i++)
111 554238 : PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
112 277119 : PARSE_HYPHEN(aIDStr);
113 2216952 : while(i < 8) {
114 1662714 : PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
115 1662714 : i++;
116 : }
117 :
118 277119 : return expectFormat1 ? *aIDStr == '}' : true;
119 : }
120 :
121 : #ifndef XPCOM_GLUE_AVOID_NSPR
122 :
123 : /*
124 : * Returns an allocated string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
125 : * format. The string is allocated with NS_Alloc and should be freed by
126 : * the caller.
127 : */
128 :
129 6121 : char *nsID::ToString() const
130 : {
131 6121 : char *res = (char*)NS_Alloc(NSID_LENGTH);
132 :
133 6121 : if (res != NULL) {
134 : PR_snprintf(res, NSID_LENGTH, gIDFormat,
135 : m0, (PRUint32) m1, (PRUint32) m2,
136 18363 : (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
137 18363 : (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
138 42847 : (PRUint32) m3[6], (PRUint32) m3[7]);
139 : }
140 6121 : return res;
141 : }
142 :
143 5470 : void nsID::ToProvidedString(char (&dest)[NSID_LENGTH]) const
144 : {
145 : PR_snprintf(dest, NSID_LENGTH, gIDFormat,
146 : m0, (PRUint32) m1, (PRUint32) m2,
147 16410 : (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
148 16410 : (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
149 38290 : (PRUint32) m3[6], (PRUint32) m3[7]);
150 5470 : }
151 :
152 : #endif // XPCOM_GLUE_AVOID_NSPR
|