root/trunk/indra/test/lltemplatemessagebuilder_tut.cpp

Revision 1681, 35.7 kB (checked in by soft.linden, 1 year ago)

Snapshot of internal branch trunk
Last Changed Rev: 107394
Last Changed Date: 2009-01-08 08:59:16 -0800 (Thu, 08 Jan 2009)

Supplementary files:
http://secondlife.com/developers/opensource/downloads/2009/01/md5sums-trunk-r107394.txt
http://secondlife.com/developers/opensource/downloads/2009/01/slviewer-artwork-trunk-r107394.zip
http://secondlife.com/developers/opensource/downloads/2009/01/slviewer-darwin-libs-trunk-r107394.tar.gz
http://secondlife.com/developers/opensource/downloads/2009/01/slviewer-win32-libs-trunk-r107394.zip
http://secondlife.com/developers/opensource/downloads/2009/01/slviewer-linux-libs-trunk-r107394.tar.gz

Source tarballs - redundant to this svn:
http://secondlife.com/developers/opensource/downloads/2009/01/slviewer-src-trunk-r107394.tar.gz
http://secondlife.com/developers/opensource/downloads/2009/01/slviewer-src-trunk-r107394.zip

  • Property svn:eol-style set to native
Line 
1 /**
2  * @file lltemplatemessagebuilder_tut.cpp
3  * @date 2007-04
4  * @brief Tests for building messages.
5  *
6  * $LicenseInfo:firstyear=2007&license=viewergpl$
7  *
8  * Copyright (c) 2007-2009, Linden Research, Inc.
9  *
10  * Second Life Viewer Source Code
11  * The source code in this file ("Source Code") is provided by Linden Lab
12  * to you under the terms of the GNU General Public License, version 2.0
13  * ("GPL"), unless you have obtained a separate licensing agreement
14  * ("Other License"), formally executed by you and Linden Lab.  Terms of
15  * the GPL can be found in doc/GPL-license.txt in this distribution, or
16  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17  *
18  * There are special exceptions to the terms and conditions of the GPL as
19  * it is applied to this Source Code. View the full text of the exception
20  * in the file doc/FLOSS-exception.txt in this software distribution, or
21  * online at
22  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
23  *
24  * By copying, modifying or distributing this software, you acknowledge
25  * that you have read and understood your obligations described above,
26  * and agree to abide by those obligations.
27  *
28  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30  * COMPLETENESS OR PERFORMANCE.
31  * $/LicenseInfo$
32  */
33
34 #include <tut/tut.hpp>
35 #include "linden_common.h"
36 #include "lltut.h"
37
38 #include "llapr.h"
39 #include "llmessagetemplate.h"
40 #include "llquaternion.h"
41 #include "lltemplatemessagebuilder.h"
42 #include "lltemplatemessagereader.h"
43 #include "llversionserver.h"
44 #include "message_prehash.h"
45 #include "u64.h"
46 #include "v3dmath.h"
47 #include "v3math.h"
48 #include "v4math.h"
49
50 namespace tut
51 {       
52         static LLTemplateMessageBuilder::message_template_name_map_t nameMap;
53         static LLTemplateMessageReader::message_template_number_map_t numberMap;
54
55         struct LLTemplateMessageBuilderTestData
56         {
57                 static LLMessageTemplate defaultTemplate()
58                 {
59                         static bool init = false;
60                         if(! init)
61                         {
62                                 ll_init_apr();
63                                 const F32 circuit_heartbeat_interval=5;
64                                 const F32 circuit_timeout=100;
65
66                                 start_messaging_system("notafile", 13035,
67                                                                            LL_VERSION_MAJOR,
68                                                                            LL_VERSION_MINOR,       
69                                                                            LL_VERSION_PATCH,       
70                                                                            FALSE,       
71                                                                            "notasharedsecret",
72                                                                            NULL,
73                                                                            false,
74                                                                            circuit_heartbeat_interval,
75                                                                            circuit_timeout);
76                                 //init_prehash_data();
77                                 init = true;
78                         }
79                         return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
80                 }
81
82                 static LLMessageBlock* defaultBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
83                 {
84                         return createBlock(_PREHASH_Test0, type, size, block);
85                 }
86
87                 static LLMessageBlock* createBlock(char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
88                 {
89                         LLMessageBlock* result = new LLMessageBlock(name, block);
90                         if(type != MVT_NULL)
91                         {
92                                 result->addVariable(_PREHASH_Test0, type, size);
93                         }
94                         return result;
95                 }
96
97                 static LLTemplateMessageBuilder* defaultBuilder(LLMessageTemplate& messageTemplate, char* name = _PREHASH_Test0)
98                 {
99                         nameMap[_PREHASH_TestMessage] = &messageTemplate;
100                         LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(nameMap);
101                         builder->newMessage(_PREHASH_TestMessage);
102                         builder->nextBlock(name);
103                         return builder;
104                 }
105
106                 /** Takes ownership of builder */
107                 static LLTemplateMessageReader* setReader(
108                         LLMessageTemplate& messageTemplate,
109                         LLTemplateMessageBuilder* builder,
110                         U8 offset = 0)
111                 {
112                         numberMap[1] = &messageTemplate;
113                         const U32 bufferSize = 1024;
114                         U8 buffer[bufferSize];
115                         // zero out the packet ID field
116                         memset(buffer, 0, LL_PACKET_ID_SIZE);
117                         U32 builtSize = builder->buildMessage(buffer, bufferSize, offset);
118                         delete builder;
119                         LLTemplateMessageReader* reader = new LLTemplateMessageReader(numberMap);
120                         reader->validateMessage(buffer, builtSize, LLHost());
121                         reader->readMessage(buffer, LLHost());
122                         return reader;
123                 }
124
125         };
126        
127         typedef test_group<LLTemplateMessageBuilderTestData>    LLTemplateMessageBuilderTestGroup;
128         typedef LLTemplateMessageBuilderTestGroup::object               LLTemplateMessageBuilderTestObject;
129         LLTemplateMessageBuilderTestGroup templateMessageBuilderTestGroup("LLTemplateMessageBuilder");
130        
131         template<> template<>
132         void LLTemplateMessageBuilderTestObject::test<1>()
133                 // construction and test of undefined
134         {
135                 LLMessageTemplate messageTemplate = defaultTemplate();
136                 messageTemplate.addBlock(defaultBlock());
137                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
138                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
139                 delete reader;
140         }
141        
142         template<> template<>
143         void LLTemplateMessageBuilderTestObject::test<2>()
144                  // BOOL
145         {
146                 LLMessageTemplate messageTemplate = defaultTemplate();
147                 messageTemplate.addBlock(defaultBlock(MVT_BOOL, 1));
148                 BOOL outValue, inValue = TRUE;
149                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
150                 builder->addBOOL(_PREHASH_Test0, inValue);
151                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
152                 reader->getBOOL(_PREHASH_Test0, _PREHASH_Test0, outValue);
153                 ensure_equals("Ensure BOOL", inValue, outValue);
154                 delete reader;
155         }
156
157         template<> template<>
158         void LLTemplateMessageBuilderTestObject::test<3>()
159                  // U8
160         {
161                 LLMessageTemplate messageTemplate = defaultTemplate();
162                 messageTemplate.addBlock(defaultBlock(MVT_U8, 1));
163                 U8 outValue, inValue = 2;
164                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
165                 builder->addU8(_PREHASH_Test0, inValue);
166                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
167                 reader->getU8(_PREHASH_Test0, _PREHASH_Test0, outValue);
168                 ensure_equals("Ensure U8", inValue, outValue);
169                 delete reader;
170         }
171
172         template<> template<>
173         void LLTemplateMessageBuilderTestObject::test<4>()
174                  // S16
175         {
176                 LLMessageTemplate messageTemplate = defaultTemplate();
177                 messageTemplate.addBlock(defaultBlock(MVT_S16, 2));
178                 S16 outValue, inValue = 90;
179                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
180                 builder->addS16(_PREHASH_Test0, inValue);
181                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
182                 reader->getS16(_PREHASH_Test0, _PREHASH_Test0, outValue);
183                 ensure_equals("Ensure S16", inValue, outValue);
184                 delete reader;
185         }
186
187         template<> template<>
188         void LLTemplateMessageBuilderTestObject::test<5>()
189                  // U16
190         {
191                 LLMessageTemplate messageTemplate = defaultTemplate();
192                 messageTemplate.addBlock(defaultBlock(MVT_U16, 2));
193                 U16 outValue, inValue = 3;
194                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
195                 builder->addU16(_PREHASH_Test0, inValue);
196                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
197                 reader->getU16(_PREHASH_Test0, _PREHASH_Test0, outValue);
198                 ensure_equals("Ensure U16", inValue, outValue);
199                 delete reader;
200         }
201
202         template<> template<>
203         void LLTemplateMessageBuilderTestObject::test<6>()
204                  // S32
205         {
206                 LLMessageTemplate messageTemplate = defaultTemplate();
207                 messageTemplate.addBlock(defaultBlock(MVT_S32, 4));
208                 S32 outValue, inValue = 44;
209                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
210                 builder->addS32(_PREHASH_Test0, inValue);
211                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
212                 reader->getS32(_PREHASH_Test0, _PREHASH_Test0, outValue);
213                 ensure_equals("Ensure S32", inValue, outValue);
214                 delete reader;
215         }
216
217         template<> template<>
218         void LLTemplateMessageBuilderTestObject::test<7>()
219                  // F32
220         {
221                 LLMessageTemplate messageTemplate = defaultTemplate();
222                 messageTemplate.addBlock(defaultBlock(MVT_F32, 4));
223                 F32 outValue, inValue = 121.44f;
224                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
225                 builder->addF32(_PREHASH_Test0, inValue);
226                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
227                 reader->getF32(_PREHASH_Test0, _PREHASH_Test0, outValue);
228                 ensure_equals("Ensure F32", inValue, outValue);
229                 delete reader;
230         }
231
232         template<> template<>
233         void LLTemplateMessageBuilderTestObject::test<8>()
234                  // U32
235         {
236                 LLMessageTemplate messageTemplate = defaultTemplate();
237                 messageTemplate.addBlock(defaultBlock(MVT_U32, 4));
238                 U32 outValue, inValue = 88;
239                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
240                 builder->addU32(_PREHASH_Test0, inValue);
241                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
242                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
243                 ensure_equals("Ensure U32", inValue, outValue);
244                 delete reader;
245         }
246
247         template<> template<>
248         void LLTemplateMessageBuilderTestObject::test<9>()
249                  // U64
250         {
251                 LLMessageTemplate messageTemplate = defaultTemplate();
252                 messageTemplate.addBlock(defaultBlock(MVT_U64, 8));
253                 U64 outValue, inValue = 121;
254                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
255                 builder->addU64(_PREHASH_Test0, inValue);
256                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
257                 reader->getU64(_PREHASH_Test0, _PREHASH_Test0, outValue);
258                 ensure_equals("Ensure U64", inValue, outValue);
259                 delete reader;
260         }
261
262         template<> template<>
263         void LLTemplateMessageBuilderTestObject::test<10>()
264                  // F64
265         {
266                 LLMessageTemplate messageTemplate = defaultTemplate();
267                 messageTemplate.addBlock(defaultBlock(MVT_F64, 8));
268                 F64 outValue, inValue = 3232143.33;
269                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
270                 builder->addF64(_PREHASH_Test0, inValue);
271                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
272                 reader->getF64(_PREHASH_Test0, _PREHASH_Test0, outValue);
273                 ensure_equals("Ensure F64", inValue, outValue);
274                 delete reader;
275         }
276
277         template<> template<>
278         void LLTemplateMessageBuilderTestObject::test<11>()
279                  // Vector3
280         {
281                 LLMessageTemplate messageTemplate = defaultTemplate();
282                 messageTemplate.addBlock(defaultBlock(MVT_LLVector3, 12));
283                 LLVector3 outValue, inValue = LLVector3(1,2,3);
284                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
285                 builder->addVector3(_PREHASH_Test0, inValue);
286                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
287                 reader->getVector3(_PREHASH_Test0, _PREHASH_Test0, outValue);
288                 ensure_equals("Ensure LLVector3", inValue, outValue);
289                 delete reader;
290         }
291
292         template<> template<>
293         void LLTemplateMessageBuilderTestObject::test<12>()
294                  // Vector4
295         {
296                 LLMessageTemplate messageTemplate = defaultTemplate();
297                 messageTemplate.addBlock(defaultBlock(MVT_LLVector4, 16));
298                 LLVector4 outValue, inValue = LLVector4(1,2,3,4);
299                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
300                 builder->addVector4(_PREHASH_Test0, inValue);
301                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
302                 reader->getVector4(_PREHASH_Test0, _PREHASH_Test0, outValue);
303                 ensure_equals("Ensure LLVector4", inValue, outValue);
304                 delete reader;
305         }
306
307         template<> template<>
308         void LLTemplateMessageBuilderTestObject::test<13>()
309                  // Vector3d
310         {
311                 LLMessageTemplate messageTemplate = defaultTemplate();
312                 messageTemplate.addBlock(defaultBlock(MVT_LLVector3d, 24));
313                 LLVector3d outValue, inValue = LLVector3d(1,2,3);
314                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
315                 builder->addVector3d(_PREHASH_Test0, inValue);
316                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
317                 reader->getVector3d(_PREHASH_Test0, _PREHASH_Test0, outValue);
318                 ensure_equals("Ensure LLVector3d", inValue, outValue);
319                 delete reader;
320         }
321
322         template<> template<>
323         void LLTemplateMessageBuilderTestObject::test<14>()
324                  // Quaternion
325         {
326                 LLMessageTemplate messageTemplate = defaultTemplate();
327                 messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
328                 LLQuaternion outValue, inValue = LLQuaternion(1,2,3,0);
329                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
330                 builder->addQuat(_PREHASH_Test0, inValue);
331                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
332                 reader->getQuat(_PREHASH_Test0, _PREHASH_Test0, outValue);
333                 ensure_equals("Ensure LLQuaternion", inValue, outValue);
334                 delete reader;
335         }
336
337         template<> template<>
338         void LLTemplateMessageBuilderTestObject::test<15>()
339                  // UUID
340         {
341                 LLMessageTemplate messageTemplate = defaultTemplate();
342                 messageTemplate.addBlock(defaultBlock(MVT_LLUUID, 16));
343                 LLUUID outValue, inValue;
344                 inValue.generate();
345                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
346                 builder->addUUID(_PREHASH_Test0, inValue);
347                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
348                 reader->getUUID(_PREHASH_Test0, _PREHASH_Test0, outValue);
349                 ensure_equals("Ensure UUID", inValue, outValue);
350                 delete reader;
351         }
352
353         template<> template<>
354         void LLTemplateMessageBuilderTestObject::test<16>()
355                  // IPAddr
356         {
357                 LLMessageTemplate messageTemplate = defaultTemplate();
358                 messageTemplate.addBlock(defaultBlock(MVT_IP_ADDR, 4));
359                 U32 outValue, inValue = 12344556;
360                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
361                 builder->addIPAddr(_PREHASH_Test0, inValue);
362                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
363                 reader->getIPAddr(_PREHASH_Test0, _PREHASH_Test0, outValue);
364                 ensure_equals("Ensure IPAddr", inValue, outValue);
365                 delete reader;
366         }
367
368          template<> template<>
369         void LLTemplateMessageBuilderTestObject::test<17>()
370                  // IPPort
371         {
372                 LLMessageTemplate messageTemplate = defaultTemplate();
373                 messageTemplate.addBlock(defaultBlock(MVT_IP_PORT, 2));
374                 U16 outValue, inValue = 80;
375                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
376                 builder->addIPPort(_PREHASH_Test0, inValue);
377                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
378                 reader->getIPPort(_PREHASH_Test0, _PREHASH_Test0, outValue);
379                 ensure_equals("Ensure IPPort", inValue, outValue);
380                 delete reader;
381         }
382
383         template<> template<>
384         void LLTemplateMessageBuilderTestObject::test<18>()
385                 // String
386         {
387                 LLMessageTemplate messageTemplate = defaultTemplate();
388                 messageTemplate.addBlock(defaultBlock(MVT_VARIABLE, 1));
389                 std::string outValue, inValue = "testing";
390                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
391                 builder->addString(_PREHASH_Test0, inValue.c_str());
392                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
393                 char buffer[MAX_STRING];
394                 reader->getString(_PREHASH_Test0, _PREHASH_Test0, MAX_STRING, buffer);
395                 outValue = buffer;
396                 ensure_equals("Ensure String", inValue, outValue);
397                 delete reader;
398         }
399
400         template<> template<>
401         void LLTemplateMessageBuilderTestObject::test<19>()
402                 // block name !-> binary order
403         {
404                 U8 buffer1[MAX_BUFFER_SIZE];
405                 memset(buffer1, 0, MAX_BUFFER_SIZE);
406                 U8 buffer2[MAX_BUFFER_SIZE];
407                 memset(buffer2, 0, MAX_BUFFER_SIZE);
408                 U32 bufferSize1, bufferSize2;
409
410                 // build template: Test0 before Test1
411                 LLMessageTemplate messageTemplate = defaultTemplate();
412                 messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
413                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
414
415                 // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
416                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
417                 builder->addU32(_PREHASH_Test0, 0xaaaa);
418                 builder->nextBlock(_PREHASH_Test1);
419                 builder->addU32(_PREHASH_Test0, 0xbbbb);
420                 bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
421                 delete builder;
422
423                 // build template: Test1 before Test0
424                 messageTemplate = defaultTemplate();
425                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
426                 messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
427
428                 // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
429                 builder = defaultBuilder(messageTemplate, _PREHASH_Test1);
430                 builder->addU32(_PREHASH_Test0, 0xaaaa);
431                 builder->nextBlock(_PREHASH_Test0);
432                 builder->addU32(_PREHASH_Test0, 0xbbbb);
433                 bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
434                 delete builder;
435
436                 ensure_equals("Ensure Buffer Sizes Equal", bufferSize1, bufferSize2);
437                 ensure_equals("Ensure Buffer Contents Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
438         }
439
440         template<> template<>
441         void LLTemplateMessageBuilderTestObject::test<20>()
442                 // block build order !-> binary order
443         {
444                 U8 buffer1[MAX_BUFFER_SIZE];
445                 memset(buffer1, 0, MAX_BUFFER_SIZE);
446                 U8 buffer2[MAX_BUFFER_SIZE];
447                 memset(buffer2, 0, MAX_BUFFER_SIZE);
448                 U32 bufferSize1, bufferSize2;
449
450                 // build template: Test0 before Test1
451                 LLMessageTemplate messageTemplate = defaultTemplate();
452                 messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
453                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
454
455                 // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
456                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
457                 builder->addU32(_PREHASH_Test0, 0xaaaa);
458                 builder->nextBlock(_PREHASH_Test1);
459                 builder->addU32(_PREHASH_Test0, 0xbbbb);
460                 bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
461                 delete builder;
462
463                 // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
464                 builder = defaultBuilder(messageTemplate, _PREHASH_Test1);
465                 builder->addU32(_PREHASH_Test0, 0xbbbb);
466                 builder->nextBlock(_PREHASH_Test0);
467                 builder->addU32(_PREHASH_Test0, 0xaaaa);
468                 bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
469                 delete builder;
470
471                 ensure_equals("Ensure Buffer Sizes Equal", bufferSize1, bufferSize2);
472                 ensure_equals("Ensure Buffer Contents Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
473         }
474
475         template<> template<>
476         void LLTemplateMessageBuilderTestObject::test<21>()
477                 // block appended in declaration -> data appended in binary
478         {
479                 U8 buffer1[MAX_BUFFER_SIZE];
480                 memset(buffer1, 0, MAX_BUFFER_SIZE);
481                 U8 buffer2[MAX_BUFFER_SIZE];
482                 memset(buffer2, 0, MAX_BUFFER_SIZE);
483                 U32 bufferSize1, bufferSize2;
484
485                 // Build template: Test0 only
486                 LLMessageTemplate messageTemplate = defaultTemplate();
487                 messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
488
489                 // Build message
490                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
491                 builder->addU32(_PREHASH_Test0, 0xaaaa);
492                 bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
493                 delete builder;
494
495                 // Build template: Test0 before Test1
496                 messageTemplate = defaultTemplate();
497                 messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
498                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
499
500                 // Build message
501                 builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
502                 builder->addU32(_PREHASH_Test0, 0xaaaa);
503                 builder->nextBlock(_PREHASH_Test1);
504                 builder->addU32(_PREHASH_Test0, 0xbbbb);
505                 bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
506                 delete builder;
507
508                 ensure_not_equals("Ensure Buffer Sizes Not Equal", bufferSize1, bufferSize2);
509                 ensure_equals("Ensure Buffer Prefix Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
510                 ensure_not_equals("Ensure Buffer Contents Not Equal", memcmp(buffer1, buffer2, bufferSize2), 0);
511         }
512
513         template<> template<>
514         void LLTemplateMessageBuilderTestObject::test<22>()
515                 // repeated penultimate block (crashes when data in LLDynamicArrayIndexed)
516         {
517                 U32 inTest00 = 0, inTest01 = 1, inTest1 = 2;
518                 U32 outTest00, outTest01, outTest1;
519                 LLMessageTemplate messageTemplate = defaultTemplate();
520                 messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4));
521                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4));
522                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
523                 builder->addU32(_PREHASH_Test0, inTest00);
524                 builder->nextBlock(_PREHASH_Test0);
525                 builder->addU32(_PREHASH_Test0, inTest01);
526                 builder->nextBlock(_PREHASH_Test1);
527                 builder->addU32(_PREHASH_Test0, inTest1);
528                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
529                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest00, 0);
530                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest01, 1);
531                 reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outTest1);
532                 ensure_equals("Ensure Test0[0]", inTest00, outTest00);
533                 ensure_equals("Ensure Test0[1]", inTest01, outTest01);
534                 ensure_equals("Ensure Test1", inTest1, outTest1);
535                 delete reader;
536         }
537
538         template<> template<>
539         void LLTemplateMessageBuilderTestObject::test<23>()
540                 // variable repeated block name never accessed
541         {
542                 U32 inTest = 1, outTest;
543                 LLMessageTemplate messageTemplate = defaultTemplate();
544                 messageTemplate.addBlock(
545                         createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
546                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4));
547
548                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
549                 builder->addU32(_PREHASH_Test0, inTest);
550
551                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
552                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest);
553                 S32 blockCount = reader->getNumberOfBlocks(_PREHASH_Test1);
554                 ensure_equals("Ensure block count", blockCount, 0);
555                 ensure_equals("Ensure Test0", inTest, outTest);
556                 delete reader;
557         }
558
559         template<> template<>
560         void LLTemplateMessageBuilderTestObject::test<24>()
561                 // forwarding message
562         {
563                 // build template
564                 LLMessageTemplate messageTemplate = defaultTemplate();
565                 messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4));
566
567                 // build message
568                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
569                 builder->addU32(_PREHASH_Test0, 42);
570
571                 // read message
572                 LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
573
574                 // forward message
575                 builder = defaultBuilder(messageTemplate);
576                 builder->newMessage(_PREHASH_TestMessage);
577                 reader->copyToBuilder(*builder);
578                 U8 buffer[MAX_BUFFER_SIZE];
579                 builder->buildMessage(buffer, MAX_BUFFER_SIZE, 0);
580
581                 delete builder;
582                 delete reader;
583         }
584
585         template<> template<>
586         void LLTemplateMessageBuilderTestObject::test<25>()
587                 // non-zero offset with undefined
588         {
589                 LLMessageTemplate messageTemplate = defaultTemplate();
590                 messageTemplate.addBlock(defaultBlock());
591                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
592                 LLTemplateMessageReader* reader = setReader(
593                         messageTemplate, builder, 10);
594                 delete reader;
595         }
596
597         template<> template<>
598         void LLTemplateMessageBuilderTestObject::test<26>()
599                  // non-zero offset with BOOL
600         {
601                 LLMessageTemplate messageTemplate = defaultTemplate();
602                 messageTemplate.addBlock(defaultBlock(MVT_BOOL, 1));
603                 BOOL outValue, inValue = TRUE;
604                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
605                 builder->addBOOL(_PREHASH_Test0, inValue);
606                 LLTemplateMessageReader* reader = setReader(
607                         messageTemplate, builder, 1);
608                 reader->getBOOL(_PREHASH_Test0, _PREHASH_Test0, outValue);
609                 ensure_equals("Ensure BOOL", inValue, outValue);
610                 delete reader;
611         }
612
613         template<> template<>
614         void LLTemplateMessageBuilderTestObject::test<27>()
615                  // non-zero offset with U8
616         {
617                 LLMessageTemplate messageTemplate = defaultTemplate();
618                 messageTemplate.addBlock(defaultBlock(MVT_U8, 1));
619                 U8 outValue, inValue = 2;
620                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
621                 builder->addU8(_PREHASH_Test0, inValue);
622                 LLTemplateMessageReader* reader = setReader(
623                         messageTemplate, builder, 255);
624                 reader->getU8(_PREHASH_Test0, _PREHASH_Test0, outValue);
625                 ensure_equals("Ensure U8", inValue, outValue);
626                 delete reader;
627         }
628
629         template<> template<>
630         void LLTemplateMessageBuilderTestObject::test<28>()
631                  // non-zero offset with S16
632         {
633                 LLMessageTemplate messageTemplate = defaultTemplate();
634                 messageTemplate.addBlock(defaultBlock(MVT_S16, 2));
635                 S16 outValue, inValue = 90;
636                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
637                 builder->addS16(_PREHASH_Test0, inValue);
638                 LLTemplateMessageReader* reader = setReader(
639                         messageTemplate, builder, 2);
640                 reader->getS16(_PREHASH_Test0, _PREHASH_Test0, outValue);
641                 ensure_equals("Ensure S16", inValue, outValue);
642                 delete reader;
643         }
644
645         template<> template<>
646         void LLTemplateMessageBuilderTestObject::test<29>()
647                  // non-zero offset with U16
648         {
649                 LLMessageTemplate messageTemplate = defaultTemplate();
650                 messageTemplate.addBlock(defaultBlock(MVT_U16, 2));
651                 U16 outValue, inValue = 3;
652                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
653                 builder->addU16(_PREHASH_Test0, inValue);
654                 LLTemplateMessageReader* reader = setReader(
655                         messageTemplate, builder, 4);
656                 reader->getU16(_PREHASH_Test0, _PREHASH_Test0, outValue);
657                 ensure_equals("Ensure U16", inValue, outValue);
658                 delete reader;
659         }
660
661         template<> template<>
662         void LLTemplateMessageBuilderTestObject::test<30>()
663                  // non-zero offset with S32
664         {
665                 LLMessageTemplate messageTemplate = defaultTemplate();
666                 messageTemplate.addBlock(defaultBlock(MVT_S32, 4));
667                 S32 outValue, inValue = 44;
668                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
669                 builder->addS32(_PREHASH_Test0, inValue);
670                 LLTemplateMessageReader* reader = setReader(
671                         messageTemplate, builder, 4);
672                 reader->getS32(_PREHASH_Test0, _PREHASH_Test0, outValue);
673                 ensure_equals("Ensure S32", inValue, outValue);
674                 delete reader;
675         }
676
677         template<> template<>
678         void LLTemplateMessageBuilderTestObject::test<31>()
679                  // non-zero offset with F32
680         {
681                 LLMessageTemplate messageTemplate = defaultTemplate();
682                 messageTemplate.addBlock(defaultBlock(MVT_F32, 4));
683                 F32 outValue, inValue = 121.44f;
684                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
685                 builder->addF32(_PREHASH_Test0, inValue);
686                 LLTemplateMessageReader* reader = setReader(
687                         messageTemplate, builder, 16);
688                 reader->getF32(_PREHASH_Test0, _PREHASH_Test0, outValue);
689                 ensure_equals("Ensure F32", inValue, outValue);
690                 delete reader;
691         }
692
693         template<> template<>
694         void LLTemplateMessageBuilderTestObject::test<32>()
695                  // non-zero offset with U32
696         {
697                 LLMessageTemplate messageTemplate = defaultTemplate();
698                 messageTemplate.addBlock(defaultBlock(MVT_U32, 4));
699                 U32 outValue, inValue = 88;
700                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
701                 builder->addU32(_PREHASH_Test0, inValue);
702                 LLTemplateMessageReader* reader = setReader(
703                         messageTemplate, builder, 127);
704                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
705                 ensure_equals("Ensure U32", inValue, outValue);
706                 delete reader;
707         }
708
709         template<> template<>
710         void LLTemplateMessageBuilderTestObject::test<33>()
711                  // non-zero offset with U64
712         {
713                 LLMessageTemplate messageTemplate = defaultTemplate();
714                 messageTemplate.addBlock(defaultBlock(MVT_U64, 8));
715                 U64 outValue, inValue = 121;
716                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
717                 builder->addU64(_PREHASH_Test0, inValue);
718                 LLTemplateMessageReader* reader = setReader(
719                         messageTemplate, builder, 32);
720                 reader->getU64(_PREHASH_Test0, _PREHASH_Test0, outValue);
721                 ensure_equals("Ensure U64", inValue, outValue);
722                 delete reader;
723         }
724
725         template<> template<>
726         void LLTemplateMessageBuilderTestObject::test<34>()
727                  // non-zero offset with F64
728         {
729                 LLMessageTemplate messageTemplate = defaultTemplate();
730                 messageTemplate.addBlock(defaultBlock(MVT_F64, 8));
731                 F64 outValue, inValue = 3232143.33;
732                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
733                 builder->addF64(_PREHASH_Test0, inValue);
734                 LLTemplateMessageReader* reader = setReader(
735                         messageTemplate, builder, 128);
736                 reader->getF64(_PREHASH_Test0, _PREHASH_Test0, outValue);
737                 ensure_equals("Ensure F64", inValue, outValue);
738                 delete reader;
739         }
740
741         template<> template<>
742         void LLTemplateMessageBuilderTestObject::test<35>()
743                  // non-zero offset with Vector3
744         {
745                 LLMessageTemplate messageTemplate = defaultTemplate();
746                 messageTemplate.addBlock(defaultBlock(MVT_LLVector3, 12));
747                 LLVector3 outValue, inValue = LLVector3(1,2,3);
748                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
749                 builder->addVector3(_PREHASH_Test0, inValue);
750                 LLTemplateMessageReader* reader = setReader(
751                         messageTemplate, builder, 63);
752                 reader->getVector3(_PREHASH_Test0, _PREHASH_Test0, outValue);
753                 ensure_equals("Ensure LLVector3", inValue, outValue);
754                 delete reader;
755         }
756
757         template<> template<>
758         void LLTemplateMessageBuilderTestObject::test<36>()
759                  // non-zero offset with Vector4
760         {
761                 LLMessageTemplate messageTemplate = defaultTemplate();
762                 messageTemplate.addBlock(defaultBlock(MVT_LLVector4, 16));
763                 LLVector4 outValue, inValue = LLVector4(1,2,3,4);
764                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
765                 builder->addVector4(_PREHASH_Test0, inValue);
766                 LLTemplateMessageReader* reader = setReader(
767                         messageTemplate, builder, 64);
768                 reader->getVector4(_PREHASH_Test0, _PREHASH_Test0, outValue);
769                 ensure_equals("Ensure LLVector4", inValue, outValue);
770                 delete reader;
771         }
772
773         template<> template<>
774         void LLTemplateMessageBuilderTestObject::test<37>()
775                  // non-zero offset with Vector3d
776         {
777                 LLMessageTemplate messageTemplate = defaultTemplate();
778                 messageTemplate.addBlock(defaultBlock(MVT_LLVector3d, 24));
779                 LLVector3d outValue, inValue = LLVector3d(1,2,3);
780                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
781                 builder->addVector3d(_PREHASH_Test0, inValue);
782                 LLTemplateMessageReader* reader = setReader(
783                         messageTemplate, builder, 64);
784                 reader->getVector3d(_PREHASH_Test0, _PREHASH_Test0, outValue);
785                 ensure_equals("Ensure LLVector3d", inValue, outValue);
786                 delete reader;
787         }
788
789         template<> template<>
790         void LLTemplateMessageBuilderTestObject::test<38>()
791                  // non-zero offset with Quaternion
792         {
793                 LLMessageTemplate messageTemplate = defaultTemplate();
794                 messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
795                 LLQuaternion outValue, inValue = LLQuaternion(1,2,3,0);
796                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
797                 builder->addQuat(_PREHASH_Test0, inValue);
798                 LLTemplateMessageReader* reader = setReader(
799                         messageTemplate, builder, 12);
800                 reader->getQuat(_PREHASH_Test0, _PREHASH_Test0, outValue);
801                 ensure_equals("Ensure LLQuaternion", inValue, outValue);
802                 delete reader;
803         }
804
805         template<> template<>
806         void LLTemplateMessageBuilderTestObject::test<39>()
807                  // non-zero offset with UUID
808         {
809                 LLMessageTemplate messageTemplate = defaultTemplate();
810                 messageTemplate.addBlock(defaultBlock(MVT_LLUUID, 16));
811                 LLUUID outValue, inValue;
812                 inValue.generate();
813                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
814                 builder->addUUID(_PREHASH_Test0, inValue);
815                 LLTemplateMessageReader* reader = setReader(
816                         messageTemplate, builder, 31);
817                 reader->getUUID(_PREHASH_Test0, _PREHASH_Test0, outValue);
818                 ensure_equals("Ensure UUID", inValue, outValue);
819                 delete reader;
820         }
821
822         template<> template<>
823         void LLTemplateMessageBuilderTestObject::test<40>()
824                  // non-zero offset with IPAddr
825         {
826                 LLMessageTemplate messageTemplate = defaultTemplate();
827                 messageTemplate.addBlock(defaultBlock(MVT_IP_ADDR, 4));
828                 U32 outValue, inValue = 12344556;
829                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
830                 builder->addIPAddr(_PREHASH_Test0, inValue);
831                 LLTemplateMessageReader* reader = setReader(
832                         messageTemplate, builder, 32);
833                 reader->getIPAddr(_PREHASH_Test0, _PREHASH_Test0, outValue);
834                 ensure_equals("Ensure IPAddr", inValue, outValue);
835                 delete reader;
836         }
837
838          template<> template<>
839         void LLTemplateMessageBuilderTestObject::test<41>()
840                  // non-zero offset with IPPort
841         {
842                 LLMessageTemplate messageTemplate = defaultTemplate();
843                 messageTemplate.addBlock(defaultBlock(MVT_IP_PORT, 2));
844                 U16 outValue, inValue = 80;
845                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
846                 builder->addIPPort(_PREHASH_Test0, inValue);
847                 LLTemplateMessageReader* reader = setReader(
848                         messageTemplate, builder, 6);
849                 reader->getIPPort(_PREHASH_Test0, _PREHASH_Test0, outValue);
850                 ensure_equals("Ensure IPPort", inValue, outValue);
851                 delete reader;
852         }
853
854         template<> template<>
855         void LLTemplateMessageBuilderTestObject::test<42>()
856                 // non-zero offset with String
857         {
858                 LLMessageTemplate messageTemplate = defaultTemplate();
859                 messageTemplate.addBlock(defaultBlock(MVT_VARIABLE, 1));
860                 std::string outValue, inValue = "testing";
861                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
862                 builder->addString(_PREHASH_Test0, inValue.c_str());
863                 LLTemplateMessageReader* reader = setReader(
864                         messageTemplate, builder, 255);
865                 char buffer[MAX_STRING];
866                 reader->getString(_PREHASH_Test0, _PREHASH_Test0, MAX_STRING, buffer);
867                 outValue = buffer;
868                 ensure_equals("Ensure String", inValue, outValue);
869                 delete reader;
870         }
871
872         template<> template<>
873         void LLTemplateMessageBuilderTestObject::test<43>()
874                 // read past end of message -> default values (forward compatibility)
875         {
876                 // build message with single block
877                 LLMessageTemplate messageTemplate = defaultTemplate();
878                 messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
879                 U32 outValue, outValue2, inValue = 0xbbbbbbbb;
880                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
881                 builder->addU32(_PREHASH_Test0, inValue);
882                 const U32 bufferSize = 1024;
883                 U8 buffer[bufferSize];
884                 memset(buffer, 0xaa, bufferSize);
885                 memset(buffer, 0, LL_PACKET_ID_SIZE);
886                 U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
887                 delete builder;
888
889                 // add block to reader template
890                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
891
892                 // read message value and default value
893                 numberMap[1] = &messageTemplate;
894                 LLTemplateMessageReader* reader =
895                         new LLTemplateMessageReader(numberMap);
896                 reader->validateMessage(buffer, builtSize, LLHost());
897                 reader->readMessage(buffer, LLHost());
898                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
899                 reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outValue2);
900                 ensure_equals("Ensure present value ", outValue, inValue);
901                 ensure_equals("Ensure default value ", outValue2, 0);
902                 delete reader;
903         }
904
905         template<> template<>
906         void LLTemplateMessageBuilderTestObject::test<44>()
907                 // read variable block past end of message -> 0 repeats
908         {
909                 // build message with single block
910                 LLMessageTemplate messageTemplate = defaultTemplate();
911                 messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
912                 U32 outValue, outValue2, inValue = 0xbbbbbbbb;
913                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
914                 builder->addU32(_PREHASH_Test0, inValue);
915                 const U32 bufferSize = 1024;
916                 U8 buffer[bufferSize];
917                 memset(buffer, 0xaa, bufferSize);
918                 memset(buffer, 0, LL_PACKET_ID_SIZE);
919                 U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
920                 delete builder;
921
922                 // add variable block to reader template
923                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4));
924
925                 // read message value and check block repeat count
926                 numberMap[1] = &messageTemplate;
927                 LLTemplateMessageReader* reader =
928                         new LLTemplateMessageReader(numberMap);
929                 reader->validateMessage(buffer, builtSize, LLHost());
930                 reader->readMessage(buffer, LLHost());
931                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
932                 outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1);
933                 ensure_equals("Ensure present value ", outValue, inValue);
934                 ensure_equals("Ensure 0 repeats ", outValue2, 0);
935                 delete reader;
936         }
937
938         template<> template<>
939         void LLTemplateMessageBuilderTestObject::test<45>()
940                 // read variable length data past end of message -> 0 length
941         {
942                 // build message with single block
943                 LLMessageTemplate messageTemplate = defaultTemplate();
944                 messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
945                 U32 outValue, outValue2, inValue = 0xbbbbbbbb;
946                 LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
947                 builder->addU32(_PREHASH_Test0, inValue);
948                 const U32 bufferSize = 1024;
949                 U8 buffer[bufferSize];
950                 memset(buffer, 0xaa, bufferSize);
951                 memset(buffer, 0, LL_PACKET_ID_SIZE);
952                 U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
953                 delete builder;
954
955                 // add variable block to reader template
956                 messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_VARIABLE, 4,
957                                                                                          MBT_SINGLE));
958
959                 // read message value and default string
960                 numberMap[1] = &messageTemplate;
961                 LLTemplateMessageReader* reader =
962                         new LLTemplateMessageReader(numberMap);
963                 reader->validateMessage(buffer, builtSize, LLHost());
964                 reader->readMessage(buffer, LLHost());
965                 reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
966                 char outBuffer[bufferSize];
967                 memset(buffer, 0xcc, bufferSize);
968                 reader->getString(_PREHASH_Test1, _PREHASH_Test0, bufferSize,
969                                                   outBuffer);
970                 outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1);
971                 ensure_equals("Ensure present value ", outValue, inValue);
972                 ensure_equals("Ensure unchanged buffer ", strlen(outBuffer), 0);
973                 delete reader;
974         }
975 }
976
Note: See TracBrowser for help on using the browser.