xref: /haiku/src/build/libbe/support/Archivable.cpp (revision 268f99dd7dc4bd7474a8bd2742d3f1ec1de6752a)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, Haiku
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		Archivable.cpp
23 //	Author:			Erik Jaesler (erik@cgsoftware.com)
24 //	Description:	BArchivable mix-in class defines the archiving
25 //					protocol.  Also some global archiving functions.
26 //------------------------------------------------------------------------------
27 
28 // Standard Includes -----------------------------------------------------------
29 #include <ctype.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string>
34 #include <typeinfo>
35 #include <vector>
36 
37 // System Includes -------------------------------------------------------------
38 #include <AppFileInfo.h>
39 #include <Archivable.h>
40 #include <Entry.h>
41 #include <List.h>
42 #include <OS.h>
43 #include <Path.h>
44 //#include <Roster.h>
45 #include <String.h>
46 #include <SupportDefs.h>
47 #include <syslog.h>
48 
49 // Project Includes ------------------------------------------------------------
50 
51 // Local Includes --------------------------------------------------------------
52 
53 // Local Defines ---------------------------------------------------------------
54 
55 // Globals ---------------------------------------------------------------------
56 
57 
58 using std::string;
59 using std::vector;
60 
61 const char* B_CLASS_FIELD = "class";
62 const char* B_ADD_ON_FIELD = "add_on";
63 const int32 FUNC_NAME_LEN = 1024;
64 
65 // TODO: consider moving these
66 //		 to a separate module, and making them more full-featured (e.g., taking
67 //		 NS::ClassName::Function(Param p) instead of just NS::ClassName)
68 static void Demangle(const char *name, BString &out);
69 static void Mangle(const char *name, BString &out);
70 // static instantiation_func FindFuncInImage(BString& funcName, image_id id,
71 // 										  status_t& err);
72 // static bool CheckSig(const char* sig, image_info& info);
73 
74 /*
75 // TODO: Where do these get triggered from?
76 Log entries graciously coughed up by the Be implementation:
77 	Nov 28 01:40:45 instantiate_object failed: NULL BMessage argument
78 	Nov 28 01:40:45 instantiate_object failed: Failed to find an entrydefining the class name (Name not found).
79 	Nov 28 01:40:45 instantiate_object failed: No signature specified in archive, looking for class "TInvalidClassName".
80 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
81 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
82 	Nov 28 01:40:45 instantiate_object failed: Failed to find exported Instantiate static function for class TInvalidClassName.
83 	Nov 28 01:40:45 instantiate_object failed: Invalid argument (80000005)
84 	Nov 28 01:40:45 instantiate_object failed: No signature specified in archive, looking for class "TRemoteTestObject".
85 	Nov 28 01:40:45 instantiate_object - couldn't get mime sig for /boot/home/src/projects/Haiku/app_kit/test/lib/support/BArchivable/./BArchivableSystemTester
86 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
87 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
88 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
89 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
90 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
91 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
92 */
93 
94 //------------------------------------------------------------------------------
BArchivable()95 BArchivable::BArchivable()
96 {
97 	;
98 }
99 //------------------------------------------------------------------------------
BArchivable(BMessage * from)100 BArchivable::BArchivable(BMessage* from)
101 {
102 	;
103 }
104 //------------------------------------------------------------------------------
~BArchivable()105 BArchivable::~BArchivable()
106 {
107 	;
108 }
109 //------------------------------------------------------------------------------
Archive(BMessage * into,bool deep) const110 status_t BArchivable::Archive(BMessage* into, bool deep) const
111 {
112 	if (!into)
113 	{
114 		// TODO: logging/other error reporting?
115 		return B_BAD_VALUE;
116 	}
117 
118 	BString name;
119 	Demangle(typeid(*this).name(), name);
120 
121 	return into->AddString(B_CLASS_FIELD, name);
122 }
123 //------------------------------------------------------------------------------
Instantiate(BMessage * from)124 BArchivable* BArchivable::Instantiate(BMessage* from)
125 {
126 	debugger("Can't create a plain BArchivable object");
127 	return NULL;
128 }
129 //------------------------------------------------------------------------------
Perform(perform_code d,void * arg)130 status_t BArchivable::Perform(perform_code d, void* arg)
131 {
132 	// TODO: Check against original
133 	return B_ERROR;
134 }
135 //------------------------------------------------------------------------------
_ReservedArchivable1()136 void BArchivable::_ReservedArchivable1()
137 {
138 	;
139 }
140 //------------------------------------------------------------------------------
_ReservedArchivable2()141 void BArchivable::_ReservedArchivable2()
142 {
143 	;
144 }
145 //------------------------------------------------------------------------------
_ReservedArchivable3()146 void BArchivable::_ReservedArchivable3()
147 {
148 	;
149 }
150 //------------------------------------------------------------------------------
BuildFuncName(const char * className,BString & funcName)151 void BuildFuncName(const char* className, BString& funcName)
152 {
153 	funcName = "";
154 
155 	//	This is what we're after:
156 	//		Instantiate__Q28Haiku11BArchivableP8BMessage
157 	Mangle(className, funcName);
158 	funcName.Prepend("Instantiate__");
159 	funcName.Append("P8BMessage");
160 }
161 
162 //------------------------------------------------------------------------------
validate_instantiation(BMessage * from,const char * class_name)163 bool validate_instantiation(BMessage* from, const char* class_name)
164 {
165 	errno = B_OK;
166 
167 	// Make sure our params are kosher -- original skimped here =P
168 	if (!from)
169 	{
170 		// Not standard; Be implementation has a segment
171 		// violation on this error mode
172 		errno = B_BAD_VALUE;
173 
174 		return false;
175 	}
176 
177 	status_t err = B_OK;
178 	const char* data;
179 	for (int32 index = 0; err == B_OK; ++index)
180 	{
181 		err = from->FindString(B_CLASS_FIELD, index, &data);
182 		if (!err && strcmp(data, class_name) == 0)
183 		{
184 			return true;
185 		}
186 	}
187 
188 	errno = B_MISMATCHED_VALUES;
189 	syslog(LOG_ERR, "validate_instantiation failed on class %s.", class_name);
190 
191 	return false;
192 }
193 
194 
195 //------------------------------------------------------------------------------
GetNumber(const char * & name)196 int GetNumber(const char*& name)
197 {
198 	int val = atoi(name);
199 	while (isdigit(*name))
200 	{
201 		++name;
202 	}
203 
204 	return val;
205 }
206 //------------------------------------------------------------------------------
Demangle(const char * name,BString & out)207 void Demangle(const char* name, BString& out)
208 {
209 // TODO: add support for template classes
210 //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
211 
212 	out = "";
213 
214 	// Are we in a namespace?
215 	if (*name == 'Q')
216 	{
217 		// Yessir, we are; how many deep are we?
218 		int nsCount = 0;
219 		++name;
220 		if (*name == '_')	// more than 10 deep
221 		{
222 			++name;
223 			if (!isdigit(*name))
224 				;	// TODO: error handling
225 
226 			nsCount = GetNumber(name);
227 			if (*name == '_')	// more than 10 deep
228 				++name;
229 			else
230 				;	// this should be an error condition
231 		}
232 		else
233 		{
234 			nsCount = *name - '0';
235 			++name;
236 		}
237 
238 		int nameLen = 0;
239 		for (int i = 0; i < nsCount - 1; ++i)
240 		{
241 			if (!isdigit(*name))
242 				;	// TODO: error handling
243 
244 			nameLen = GetNumber(name);
245 			out.Append(name, nameLen);
246 			out += "::";
247 			name += nameLen;
248 		}
249 	}
250 
251 	out.Append(name, GetNumber(name));
252 }
253 //------------------------------------------------------------------------------
Mangle(const char * name,BString & out)254 void Mangle(const char* name, BString& out)
255 {
256 // TODO: add support for template classes
257 //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
258 
259 	//	Chop this:
260 	//		testthree::testfour::Testthree::Testfour
261 	//	up into little bite-sized pieces
262 	int count = 0;
263 	string origName(name);
264 	vector<string> spacenames;
265 
266 	string::size_type pos = 0;
267 	string::size_type oldpos = 0;
268 	while (pos != string::npos)
269 	{
270 		pos = origName.find_first_of("::", oldpos);
271 		spacenames.push_back(string(origName, oldpos, pos - oldpos));
272 		pos = origName.find_first_not_of("::", pos);
273 		oldpos = pos;
274 		++count;
275 	}
276 
277 	//	Now mangle it into this:
278 	//		Q49testthree8testfour9Testthree8Testfour
279 	out = "";
280 	if (count > 1)
281 	{
282 		out += 'Q';
283 		if (count > 10)
284 			out += '_';
285 		out << count;
286 		if (count > 10)
287 			out += '_';
288 	}
289 
290 	for (unsigned int i = 0; i < spacenames.size(); ++i)
291 	{
292 		out << (int)spacenames[i].length();
293 		out += spacenames[i].c_str();
294 	}
295 }
296 
297 
298 /*
299  * $Log $
300  *
301  * $Id  $
302  *
303  */
304 
305