1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF) */
3 /* (C) Copyright IBM Corp. 2001 */
4 /* */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
6 /*****************************************************************************/
7
8 #include "STAF.h"
9 #include "STAFUtil.h"
10 #include "STAFRefPtr.h"
11 #include "STAFException.h"
12 #include <deque>
13 #include <map>
14
15 typedef std::deque<STAFObject_t> STAFObjectList;
16 typedef std::map<STAFString, STAFObject_t> STAFObjectMap;
17
18 enum STAFObjectIteratorType_t
19 {
20 kSTAFObjectListIterator = 0,
21 kSTAFObjectMapKeyIterator = 1,
22 kSTAFObjectMapValueIterator = 2
23 };
24
25 struct STAFObjectListIterator
26 {
27 STAFObjectList::iterator iter;
28 STAFObjectList *listObject;
29 };
30
31 struct STAFObjectMapIterator
32 {
33 STAFObjectMap::iterator iter;
34 STAFObjectMap *mapObject;
35 };
36
37 struct STAFObjectIteratorImpl
38 {
39 STAFObjectIteratorType_t type;
40
41 union
42 {
43 STAFObjectListIterator *listIterator;
44 STAFObjectMapIterator *mapIterator;
45 };
46 };
47
48
49 struct STAFObjectMarshallingContext
50 {
51 STAFObject_t mapClassMap;
52 STAFObject_t rootObject;
53 };
54
55
56 struct STAFObjectImpl
57 {
58 STAFObjectType_t type;
59 bool isRef;
60
61 union
62 {
63 STAFObjectList *listValue;
64 STAFObjectMap *mapValue;
65 STAFObjectMarshallingContext *contextValue;
66 STAFString *scalarStringValue;
67 };
68 };
69
70
71 static STAFObjectImpl sNoneObj = { kSTAFNoneObject, true };
72 static STAFObject_t sNoneObjT = &sNoneObj;
73 static STAFString sColon(kUTF8_COLON);
74
incrementNChars(const STAFString & theString,const unsigned int beginIndex,const unsigned int incrementLength)75 inline unsigned int incrementNChars(const STAFString &theString,
76 const unsigned int beginIndex,
77 const unsigned int incrementLength)
78 {
79 // This is the only viable way to increment characters as we have a length
80 // in "chars", but we really want to be working in bytes.
81
82 unsigned int endOfString = beginIndex;
83
84 for (unsigned int i = 0; i < incrementLength; ++i)
85 endOfString += theString.sizeOfChar(endOfString);
86
87 return endOfString;
88 }
89
90
getCLCLength(const STAFString & theString,unsigned int & index)91 inline unsigned int getCLCLength(const STAFString &theString, unsigned int &index)
92 {
93 unsigned int colonIndex1 = theString.find(sColon, index);
94
95 if (colonIndex1 == STAFString::kNPos)
96 throw STAFException("No first colon found");
97
98 unsigned int colonIndex2 = theString.find(sColon, colonIndex1 + 1);
99
100 if (colonIndex2 == STAFString::kNPos)
101 throw STAFException("No second colon found");
102
103 index = colonIndex2 + 1;
104
105 return theString.subString(
106 colonIndex1 + 1, colonIndex2 - colonIndex1 - 1).asUInt();
107 }
108
109
getCLCString(const STAFString & theString,unsigned int & index)110 inline STAFString getCLCString(const STAFString &theString, unsigned int &index)
111 {
112 unsigned int colonIndex1 = theString.find(sColon, index);
113
114 if (colonIndex1 == STAFString::kNPos)
115 throw STAFException("No first colon found");
116
117 unsigned int colonIndex2 = theString.find(sColon, colonIndex1 + 1);
118
119 if (colonIndex2 == STAFString::kNPos)
120 throw STAFException("No second colon found");
121
122 unsigned int stringLength = theString.subString(
123 colonIndex1 + 1, colonIndex2 - colonIndex1 - 1).asUInt();
124
125 index = incrementNChars(theString, colonIndex2 + 1, stringLength);
126
127 return theString.subString(colonIndex2 + 1, index - colonIndex2 - 1);
128 }
129
130
adoptPrimaryObject(STAFObject_t & context)131 inline STAFObject_t adoptPrimaryObject(STAFObject_t &context)
132 {
133 // Initialize the output object to be the context itself. If the context
134 // doesn't have any map classes, then we set the output object to be the
135 // adopted root object and then destruct the context itself.
136
137 STAFObject_t obj = context;
138
139 if (context->contextValue->mapClassMap->mapValue->size() == 0)
140 {
141 STAFObjectMarshallingContextAdoptRootObject(context, &obj);
142 STAFObjectDestruct(&context);
143 }
144
145 return obj;
146 }
147
unmarshallToPrimaryObject(STAFString & theString,STAFObject_t context,unsigned int beginIndex,unsigned int endIndex,unsigned int flags)148 inline STAFObject_t unmarshallToPrimaryObject(STAFString &theString,
149 STAFObject_t context,
150 unsigned int beginIndex,
151 unsigned int endIndex,
152 unsigned int flags)
153 {
154
155 STAFObject_t newContext = 0;
156
157 STAFObjectUnmarshallFromString(
158 &newContext,
159 theString.subString(beginIndex, endIndex - beginIndex).getImpl(),
160 context,
161 flags);
162
163 return adoptPrimaryObject(newContext);
164 }
165
unmarshallObject(STAFString & theString,STAFObject_t context,unsigned int & index,unsigned int flags)166 inline STAFObject_t unmarshallObject(STAFString &theString, STAFObject_t context,
167 unsigned int &index, unsigned int flags)
168 {
169 unsigned int beginIndex = index;
170 unsigned int colonIndex1 = theString.find(sColon, beginIndex);
171 unsigned int colonIndex2 = theString.find(sColon, colonIndex1 + 1);
172 unsigned int objectLength = theString.subString(colonIndex1 + 1,
173 colonIndex2 - colonIndex1 -
174 1).asUInt();
175 index = incrementNChars(theString, colonIndex2 + 1, objectLength);
176
177 return unmarshallToPrimaryObject(theString, context, beginIndex, index,
178 flags);
179 }
180
181
STAFObjectConstructReference(STAFObject_t * pObject,STAFObject_t source)182 STAFRC_t STAFObjectConstructReference(STAFObject_t *pObject, STAFObject_t source)
183 {
184 if (pObject == 0) return kSTAFInvalidObject;
185 if (source == 0) return kSTAFInvalidObject;
186
187 *pObject = new STAFObjectImpl;
188 STAFObjectImpl &obj = **pObject;
189
190 obj = *source;
191 obj.isRef = true;
192
193 return kSTAFOk;
194 }
195
196
STAFObjectConstructNone(STAFObject_t * pObject)197 STAFRC_t STAFObjectConstructNone(STAFObject_t *pObject)
198 {
199 if (pObject == 0) return kSTAFInvalidObject;
200
201 *pObject = new STAFObjectImpl;
202 STAFObjectImpl &obj = **pObject;
203
204 obj.type = kSTAFNoneObject;
205 obj.isRef = false;
206
207 return kSTAFOk;
208 }
209
210
STAFObjectConstructScalarString(STAFObject_t * pObject,STAFStringConst_t aString)211 STAFRC_t STAFObjectConstructScalarString(STAFObject_t *pObject,
212 STAFStringConst_t aString)
213 {
214 if (pObject == 0) return kSTAFInvalidObject;
215
216 *pObject = new STAFObjectImpl;
217 STAFObjectImpl &obj = **pObject;
218
219 obj.type = kSTAFScalarStringObject;
220 obj.isRef = false;
221
222 // XXX: Used to be this
223 // STAFStringConstructCopy(&obj.scalarStringValue, aString, 0);
224 obj.scalarStringValue = new STAFString(aString);
225
226 return kSTAFOk;
227 }
228
229
STAFObjectConstructList(STAFObject_t * pObject)230 STAFRC_t STAFObjectConstructList(STAFObject_t *pObject)
231 {
232 if (pObject == 0) return kSTAFInvalidObject;
233
234 *pObject = new STAFObjectImpl;
235 STAFObjectImpl &obj = **pObject;
236
237 obj.type = kSTAFListObject;
238 obj.isRef = false;
239
240 obj.listValue = new STAFObjectList;
241
242 return kSTAFOk;
243 }
244
245
STAFObjectConstructListIterator(STAFObjectIterator_t * pIter,STAFObject_t list)246 STAFRC_t STAFObjectConstructListIterator(STAFObjectIterator_t *pIter,
247 STAFObject_t list)
248 {
249 if (pIter == 0) return kSTAFInvalidObject;
250 // XXX: Might this want to be a new kSTAFInvalidOperation ?
251 if (list->type != kSTAFListObject) return kSTAFInvalidObject;
252
253 *pIter = new STAFObjectIteratorImpl;
254 STAFObjectIteratorImpl &iter = **pIter;
255
256 iter.type = kSTAFObjectListIterator;
257
258 iter.listIterator = new STAFObjectListIterator;
259 iter.listIterator->iter = list->listValue->begin();
260 iter.listIterator->listObject = list->listValue;
261
262 return kSTAFOk;
263 }
264
265
STAFObjectConstructMap(STAFObject_t * pObject)266 STAFRC_t STAFObjectConstructMap(STAFObject_t *pObject)
267 {
268 if (pObject == 0) return kSTAFInvalidObject;
269
270 *pObject = new STAFObjectImpl;
271 STAFObjectImpl &obj = **pObject;
272
273 obj.type = kSTAFMapObject;
274 obj.isRef = false;
275
276 obj.mapValue = new STAFObjectMap;
277
278 return kSTAFOk;
279 }
280
281
STAFObjectConstructMapKeyIterator(STAFObjectIterator_t * pIter,STAFObject_t map)282 STAFRC_t STAFObjectConstructMapKeyIterator(STAFObjectIterator_t *pIter,
283 STAFObject_t map)
284 {
285 if (pIter == 0) return kSTAFInvalidObject;
286 // XXX: Might this want to be a new kSTAFInvalidOperation ?
287 if (map->type != kSTAFMapObject) return kSTAFInvalidObject;
288
289 *pIter = new STAFObjectIteratorImpl;
290 STAFObjectIteratorImpl &iter = **pIter;
291
292 iter.type = kSTAFObjectMapKeyIterator;
293
294 iter.mapIterator = new STAFObjectMapIterator;
295 iter.mapIterator->iter = map->mapValue->begin();
296 iter.mapIterator->mapObject = map->mapValue;
297
298 return kSTAFOk;
299 }
300
301
STAFObjectConstructMapValueIterator(STAFObjectIterator_t * pIter,STAFObject_t map)302 STAFRC_t STAFObjectConstructMapValueIterator(STAFObjectIterator_t *pIter,
303 STAFObject_t map)
304 {
305 if (pIter == 0) return kSTAFInvalidObject;
306 // XXX: Might this want to be a new kSTAFInvalidOperation ?
307 if (map->type != kSTAFMapObject) return kSTAFInvalidObject;
308
309 *pIter = new STAFObjectIteratorImpl;
310 STAFObjectIteratorImpl &iter = **pIter;
311
312 iter.type = kSTAFObjectMapValueIterator;
313
314 iter.mapIterator = new STAFObjectMapIterator;
315 iter.mapIterator->iter = map->mapValue->begin();
316 iter.mapIterator->mapObject = map->mapValue;
317
318 return kSTAFOk;
319 }
320
321
STAFObjectConstructMapClassDefinitionIterator(STAFObjectIterator_t * pIter,STAFObject_t context)322 STAFRC_t STAFObjectConstructMapClassDefinitionIterator(
323 STAFObjectIterator_t *pIter, STAFObject_t context)
324 {
325 if (pIter == 0) return kSTAFInvalidObject;
326 // XXX: Might this want to be a new kSTAFInvalidOperation ?
327 if (context->type != kSTAFMarshallingContextObject)
328 return kSTAFInvalidObject;
329
330 return STAFObjectConstructMapKeyIterator(
331 pIter, context->contextValue->mapClassMap);
332 }
333
334
STAFObjectConstructMarshallingContext(STAFObject_t * pObject)335 STAFRC_t STAFObjectConstructMarshallingContext(STAFObject_t *pObject)
336 {
337 if (pObject == 0) return kSTAFInvalidObject;
338
339 *pObject = new STAFObjectImpl;
340 STAFObjectImpl &obj = **pObject;
341
342 obj.type = kSTAFMarshallingContextObject;
343 obj.isRef = false;
344
345 obj.contextValue = new STAFObjectMarshallingContext;
346 STAFObjectConstructNone(&obj.contextValue->rootObject);
347 STAFObjectConstructMap(&obj.contextValue->mapClassMap);
348
349 return kSTAFOk;
350 }
351
STAFObjectDestruct(STAFObject_t * pObject)352 STAFRC_t STAFObjectDestruct(STAFObject_t *pObject)
353 {
354 if (pObject == 0) return kSTAFInvalidObject;
355 if (*pObject == 0) return kSTAFInvalidObject;
356
357 STAFObjectImpl &obj = **pObject;
358
359 if (!obj.isRef)
360 {
361 if (obj.type == kSTAFScalarStringObject)
362 {
363 delete obj.scalarStringValue;
364 }
365 else if (obj.type == kSTAFListObject)
366 {
367 // First destruct everything in the list
368
369 for (STAFObjectList::iterator iter = obj.listValue->begin();
370 iter != obj.listValue->end();
371 ++iter)
372 {
373 STAFObjectDestruct(&(*iter));
374 }
375
376 // Then, get rid of the list
377
378 delete obj.listValue;
379 }
380 else if (obj.type == kSTAFMapObject)
381 {
382 // First get rid of all the object values in the map.
383 // The keys will be deleted automatically.
384
385 for (STAFObjectMap::iterator iter = obj.mapValue->begin();
386 iter != obj.mapValue->end();
387 ++iter)
388 {
389 STAFObjectDestruct(&iter->second);
390 }
391
392 // Then, get rid of the map
393
394 delete obj.mapValue;
395 }
396 else if (obj.type == kSTAFMarshallingContextObject)
397 {
398 STAFObjectDestruct(&obj.contextValue->mapClassMap);
399 STAFObjectDestruct(&obj.contextValue->rootObject);
400
401 delete obj.contextValue;
402 }
403 }
404
405 delete *pObject;
406
407 *pObject = 0;
408
409 return kSTAFOk;
410 }
411
412
STAFObjectIsStringMarshalledData(STAFStringConst_t string,unsigned int * isMarshalledData)413 STAFRC_t STAFObjectIsStringMarshalledData(STAFStringConst_t string,
414 unsigned int *isMarshalledData)
415 {
416 if (string == 0) return kSTAFInvalidObject;
417 if (isMarshalledData == 0) return kSTAFInvalidParm;
418
419 static STAFString marshalledDataMarker("@SDT/");
420
421 return STAFStringStartsWith(string, marshalledDataMarker.getImpl(),
422 isMarshalledData, 0);
423 }
424
425
426
STAFObjectGetType(STAFObject_t object,STAFObjectType_t * type)427 STAFRC_t STAFObjectGetType(STAFObject_t object, STAFObjectType_t *type)
428 {
429 if (object == 0) return kSTAFInvalidObject;
430 if (type == 0) return kSTAFInvalidParm;
431
432 *type = object->type;
433
434 return kSTAFOk;
435 }
436
437
STAFObjectGetSize(STAFObject_t object,unsigned int * size)438 STAFRC_t STAFObjectGetSize(STAFObject_t object, unsigned int *size)
439 {
440 if (object == 0) return kSTAFInvalidObject;
441 if (size == 0) return kSTAFInvalidParm;
442
443 if (object->type == kSTAFNoneObject)
444 *size = 0;
445 else if (object->type == kSTAFScalarStringObject)
446 *size = object->scalarStringValue->length();
447 else if (object->type == kSTAFMapObject)
448 *size = object->mapValue->size();
449 else if (object->type == kSTAFListObject)
450 *size = object->listValue->size();
451 else if (object->type == kSTAFMarshallingContextObject)
452 return STAFObjectGetSize(object->contextValue->mapClassMap, size);
453 else
454 *size = 0;
455
456 return kSTAFOk;
457 }
458
459
STAFObjectIsReference(STAFObject_t object,unsigned int * isRef)460 STAFRC_t STAFObjectIsReference(STAFObject_t object, unsigned int *isRef)
461 {
462 if (object == 0) return kSTAFInvalidObject;
463 if (isRef == 0) return kSTAFInvalidParm;
464
465 *isRef = object->isRef ? 1 : 0;
466
467 return kSTAFOk;
468 }
469
470
STAFObjectGetStringValue(STAFObject_t object,STAFString_t * pString)471 STAFRC_t STAFObjectGetStringValue(STAFObject_t object, STAFString_t *pString)
472 {
473 if (object == 0) return kSTAFInvalidObject;
474 if (pString == 0) return kSTAFInvalidParm;
475
476 if (object->type == kSTAFNoneObject)
477 {
478 static STAFString sNoneString("<None>");
479 STAFStringConstructCopy(pString, sNoneString.getImpl(), 0);
480 }
481 else if (object->type == kSTAFScalarStringObject)
482 {
483 STAFStringConstructCopy(pString,
484 object->scalarStringValue->getImpl(), 0);
485 }
486 else if (object->type == kSTAFListObject)
487 {
488 unsigned int size = 0;
489
490 STAFObjectGetSize(object, &size);
491
492 STAFString sListString = STAFString("<List>[") + size + "]";
493 STAFStringConstructCopy(pString, sListString.getImpl(), 0);
494 }
495 else if (object->type == kSTAFMapObject)
496 {
497 static STAFString sMapClassKey("staf-map-class-name");
498 unsigned int size = 0;
499
500 STAFObjectGetSize(object, &size);
501
502 STAFObjectMap::iterator iter =
503 object->mapValue->find(sMapClassKey);
504
505 if (iter != object->mapValue->end())
506 {
507 STAFString_t mapClassNameT = 0;
508
509 STAFObjectGetStringValue(iter->second, &mapClassNameT);
510
511 STAFString sMapString = STAFString("<Map:") +
512 STAFString(mapClassNameT, STAFString::kShallow) +
513 ">[" + size + "]";
514
515 STAFStringConstructCopy(pString, sMapString.getImpl(), 0);
516 }
517 else
518 {
519 STAFString sMapString = STAFString("<Map>[") + size + "]";
520 STAFStringConstructCopy(pString, sMapString.getImpl(), 0);
521 }
522 }
523 else if (object->type == kSTAFMarshallingContextObject)
524 {
525 unsigned int size = 0;
526
527 STAFObjectGetSize(object, &size);
528
529 STAFString sContextString =
530 STAFString("<MarshalingContext>[") + size + "]";
531 STAFStringConstructCopy(pString, sContextString.getImpl(), 0);
532 }
533 else *pString = STAFString("<Unknown>").adoptImpl();
534
535 return kSTAFOk;
536 }
537
538
ISTAFQuoteString(const STAFString & input)539 STAFString ISTAFQuoteString(const STAFString &input)
540 {
541 static STAFString sSingleQuote(kUTF8_SQUOTE);
542 static STAFString sDoubleQuote(kUTF8_DQUOTE);
543 static STAFString sEscapedSingleQuote("\\'");
544
545 if (input.find(sSingleQuote) == STAFString::kNPos)
546 return STAFString(sSingleQuote) + input + STAFString(sSingleQuote);
547
548 if (input.find(sDoubleQuote) == STAFString::kNPos)
549 return STAFString(sDoubleQuote) + input + STAFString(sDoubleQuote);
550
551 return STAFString(sSingleQuote) +
552 input.replace(sSingleQuote, sEscapedSingleQuote) +
553 STAFString(sSingleQuote);
554 }
555
556
ISTAFGetLineSep()557 STAFString ISTAFGetLineSep()
558 {
559 struct STAFConfigInfo configInfo = { 0 };
560
561 STAFUtilGetConfigInfo(&configInfo, 0, 0);
562
563 return configInfo.lineSeparator;
564 }
565
566
ISTAFObjectGetFormattedStringValue(STAFString & output,STAFObjectPtr & objPtr,STAFObjectPtr & context,unsigned int indentLevel)567 void ISTAFObjectGetFormattedStringValue(STAFString &output,
568 STAFObjectPtr &objPtr,
569 STAFObjectPtr &context,
570 unsigned int indentLevel)
571 {
572 static unsigned int sIndentDelta = 2;
573 static STAFString sSpaces(" "
574 " ");
575 static STAFString sListIndent("[");
576 static STAFString sListOutdent("]");
577 static STAFString sMapIndent("{");
578 static STAFString sMapOutdent("}");
579 static STAFString sEntrySeparator("");
580 static STAFString sMapKeySeparator(": ");
581 static STAFString sKey("key");
582 static STAFString sMapClassKey("staf-map-class-name");
583 static STAFString sDisplayName("display-name");
584 static STAFString sLineSep = ISTAFGetLineSep();
585
586 switch (objPtr->type())
587 {
588 case kSTAFListObject:
589 {
590 output += sListIndent;
591
592 ++indentLevel;
593
594 if (objPtr->size() > 0) output += sLineSep;
595
596 // Print out each object
597
598 // Get the size of the list and create an array with that size.
599 // Add a string representing each element in the list to the array
600 // and then join the strings in the array.
601 // Using an array and then doing a join is done for performance
602 // reasons as it's faster than concatenating strings using +=.
603
604 unsigned int size = objPtr->size();
605 STAFString *stringArray = new STAFString[size];
606 unsigned int i = 0;
607
608 for (STAFObjectIteratorPtr iterPtr = objPtr->iterate();
609 iterPtr->hasNext();)
610 {
611 STAFString entryOutput;
612 STAFObjectPtr thisObj = iterPtr->next();
613
614 if ((thisObj->type() == kSTAFListObject) ||
615 (thisObj->type() == kSTAFMapObject) ||
616 (thisObj->type() == kSTAFMarshallingContextObject))
617 {
618 entryOutput += sSpaces.subString(0, indentLevel * sIndentDelta);
619
620 ISTAFObjectGetFormattedStringValue(
621 entryOutput, thisObj, context, indentLevel);
622 }
623 else
624 {
625 entryOutput += sSpaces.subString(0, indentLevel * sIndentDelta);
626
627 if (thisObj->type() == kSTAFNoneObject)
628 entryOutput += thisObj->asString();
629 else
630 entryOutput += thisObj->asString();
631 }
632
633 if (iterPtr->hasNext()) entryOutput += sEntrySeparator;
634
635 entryOutput += sLineSep;
636
637 stringArray[i++].replaceImpl(entryOutput.adoptImpl());
638 }
639
640 output.join(stringArray, size);
641
642 delete [] stringArray;
643
644 --indentLevel;
645
646 if (objPtr->size() > 0)
647 output += sSpaces.subString(0, indentLevel * sIndentDelta);
648
649 output += sListOutdent;
650
651 break;
652 }
653 case kSTAFMapObject:
654 {
655 output += sMapIndent;
656
657 ++indentLevel;
658
659 if (objPtr->size() > 0) output += sLineSep;
660
661 // Check if the map object has a map class key and if the context
662 // is valid and contains a map class definition for this map class.
663 // If not, treat as a plain map class.
664
665 if (objPtr->hasKey(sMapClassKey) &&
666 context && (context->type() == kSTAFMarshallingContextObject) &&
667 context->hasMapClassDefinition(objPtr->get(sMapClassKey)->asString()))
668 {
669 // Map object has a map class definition in the context
670
671 STAFMapClassDefinitionPtr mapClass =
672 context->getMapClassDefinition(
673 objPtr->get(sMapClassKey)->asString());
674
675 // Determine maximum key length
676
677 STAFObjectIteratorPtr iterPtr;
678 unsigned int maxKeyLength = 0;
679 unsigned int size = 0; // Number of keys
680
681 for (iterPtr = mapClass->keyIterator(); iterPtr->hasNext();)
682 {
683 size++;
684 STAFObjectPtr theKey = iterPtr->next();
685 STAFString theKeyString;
686
687 if (theKey->hasKey(sDisplayName))
688 theKeyString = theKey->get(sDisplayName)->asString();
689 else
690 theKeyString = theKey->get(sKey)->asString();
691
692 if (theKeyString.length(STAFString::kChar) > maxKeyLength)
693 maxKeyLength = theKeyString.length(STAFString::kChar);
694 }
695
696 // Now print each object in the map
697
698 // Get the size of the map and create an array with that size.
699 // Add a string representing each element in the map to the array
700 // and then join the strings in the array.
701 // Using an array and then doing a join is done for performance
702 // reasons as it's faster than concatenating strings using +=.
703
704 STAFString *stringArray = new STAFString[size];
705 unsigned int i = 0;
706
707 for (iterPtr = mapClass->keyIterator(); iterPtr->hasNext();)
708 {
709 STAFObjectPtr theKey = iterPtr->next();
710 STAFString theKeyString;
711
712 if (theKey->hasKey(sDisplayName))
713 theKeyString = theKey->get(sDisplayName)->asString();
714 else
715 theKeyString = theKey->get(sKey)->asString();
716
717 STAFString entryOutput = sSpaces.subString(
718 0, indentLevel * sIndentDelta);
719 entryOutput += theKeyString;
720 entryOutput += sSpaces.subString(0, maxKeyLength -
721 theKeyString.length(STAFString::kChar));
722 entryOutput += sMapKeySeparator;
723
724 STAFObjectPtr thisObj =
725 objPtr->get(theKey->get(sKey)->asString());
726
727 if ((thisObj->type() == kSTAFListObject) ||
728 (thisObj->type() == kSTAFMapObject) ||
729 (thisObj->type() == kSTAFMarshallingContextObject))
730 {
731 ISTAFObjectGetFormattedStringValue(
732 entryOutput, thisObj, context, indentLevel);
733 }
734 else if (thisObj->type() == kSTAFNoneObject)
735 {
736 entryOutput += thisObj->asString();
737 }
738 else
739 {
740 entryOutput += thisObj->asString();
741 }
742
743 if (iterPtr->hasNext()) entryOutput += sEntrySeparator;
744
745 entryOutput += sLineSep;
746
747 stringArray[i++].replaceImpl(entryOutput.adoptImpl());
748 }
749
750 output.join(stringArray, size);
751
752 delete [] stringArray;
753 }
754 else
755 {
756 // The map does not have a map class key or the map class
757 // definition is not provided in the context
758
759 // Determine maximum key length
760
761 STAFObjectIteratorPtr iterPtr;
762 unsigned int maxKeyLength = 0;
763
764 for (iterPtr = objPtr->keyIterator(); iterPtr->hasNext();)
765 {
766 STAFString theKeyString = iterPtr->next()->asString();
767
768 if (theKeyString.length(STAFString::kChar) > maxKeyLength)
769 maxKeyLength = theKeyString.length(STAFString::kChar);
770 }
771
772 // Now print each object in the map
773
774 // Get the size of the map and create an array with that size.
775 // Add a string representing each element in the map to the array
776 // and then join the strings in the array.
777 // Using an array and then doing a join is done for performance
778 // reasons as it's faster than concatenating strings using +=.
779
780 unsigned int size = objPtr->size();
781 STAFString *stringArray = new STAFString[size];
782 unsigned int i = 0;
783
784 for (iterPtr = objPtr->keyIterator(); iterPtr->hasNext();)
785 {
786 STAFString theKeyString = iterPtr->next()->asString();
787
788 STAFString entryOutput = sSpaces.subString(
789 0, indentLevel * sIndentDelta);
790 entryOutput += theKeyString;
791 entryOutput += sSpaces.subString(
792 0, maxKeyLength - theKeyString.length(STAFString::kChar));
793 entryOutput += sMapKeySeparator;
794
795 STAFObjectPtr thisObj = objPtr->get(theKeyString);
796
797 if ((thisObj->type() == kSTAFListObject) ||
798 (thisObj->type() == kSTAFMapObject) ||
799 (thisObj->type() == kSTAFMarshallingContextObject))
800 {
801 ISTAFObjectGetFormattedStringValue(
802 entryOutput, thisObj, context, indentLevel);
803 }
804 else if (thisObj->type() == kSTAFNoneObject)
805 {
806 entryOutput += thisObj->asString();
807 }
808 else
809 {
810 entryOutput += thisObj->asString();
811 }
812
813 if (iterPtr->hasNext()) entryOutput += sEntrySeparator;
814
815 entryOutput += sLineSep;
816
817 stringArray[i++].replaceImpl(entryOutput.adoptImpl());
818 }
819
820
821 output.join(stringArray, size);
822
823 delete [] stringArray;
824 }
825
826 --indentLevel;
827
828 if (objPtr->size() > 0)
829 output += sSpaces.subString(0, indentLevel * sIndentDelta);
830
831 output += sMapOutdent;
832
833 break;
834 }
835 case kSTAFMarshallingContextObject:
836 {
837 STAFObjectPtr thisObj = objPtr->getRootObject();
838
839 ISTAFObjectGetFormattedStringValue(output, thisObj, objPtr,
840 indentLevel);
841 break;
842 }
843 default:
844 {
845 output += sSpaces.subString(0, indentLevel * sIndentDelta);
846 output += objPtr->asString();
847 break;
848 }
849 }
850 }
851
852
STAFObjectGetFormattedStringValue(STAFObject_t object,STAFString_t * pString,unsigned int flags)853 STAFRC_t STAFObjectGetFormattedStringValue(STAFObject_t object,
854 STAFString_t *pString,
855 unsigned int flags)
856 {
857 if (object == 0) return kSTAFInvalidObject;
858 if (pString == 0) return kSTAFInvalidParm;
859
860 if (object->type == kSTAFNoneObject)
861 {
862 static STAFString sNoneString("<None>");
863 STAFStringConstructCopy(pString, sNoneString.getImpl(), 0);
864 }
865 else if (object->type == kSTAFScalarStringObject)
866 {
867 STAFStringConstructCopy(pString,
868 object->scalarStringValue->getImpl(), 0);
869 }
870 else
871 {
872 STAFObjectPtr theObj = STAFObject::createReference(object);
873 STAFObjectPtr context = STAFObject::createNone();
874 STAFString output;
875
876 ISTAFObjectGetFormattedStringValue(output, theObj, context, 0);
877
878 *pString = output.adoptImpl();
879 }
880
881 return kSTAFOk;
882 }
883
884
STAFObjectFreeSTAFStringTArray(STAFString_t * theArray,unsigned int size)885 void STAFObjectFreeSTAFStringTArray(STAFString_t *theArray, unsigned int size)
886 {
887 for (unsigned int i = 0; i < size; ++i)
888 STAFStringDestruct(&theArray[i], 0);
889
890 delete [] theArray;
891 }
892
893
STAFObjectMarshallToString(STAFObject_t object,STAFObject_t context,STAFString_t * pString,unsigned int flags)894 STAFRC_t STAFObjectMarshallToString(STAFObject_t object, STAFObject_t context,
895 STAFString_t *pString, unsigned int flags)
896 {
897 if (object == 0) return kSTAFInvalidObject;
898 if (pString == 0) return kSTAFInvalidParm;
899 // XXX: Might this want to be a new kSTAFInvalidOperation ?
900 if ((context != 0) && (context->type != kSTAFMarshallingContextObject))
901 return kSTAFInvalidParm;
902
903 static STAFString sMapClassKey("staf-map-class-name");
904
905 STAFString outString;
906
907 if (object->type == kSTAFScalarStringObject)
908 {
909 outString += "@SDT/$S:";
910 outString += object->scalarStringValue->length(STAFString::kChar);
911 outString += sColon;
912 outString += *object->scalarStringValue;
913 }
914 else if (object->type == kSTAFNoneObject)
915 {
916 outString += "@SDT/$0:0:";
917 }
918 else if (object->type == kSTAFListObject)
919 {
920 // Get the size of the list and create an array with that size.
921 // Instead of creating an array using:
922 // STAFString_t *stringArray = new STAFString_t[size];
923 // we're using a STAFRefPtr<STAFString_t> custom array type so that
924 // the array and it's contents will get destructed (even if an
925 // exception occurs).
926 // For each entry in the list, add a string representation of the entry
927 // to the array and then join the strings in the array.
928 // Using an array and then doing a join is done for performance
929 // reasons as it's faster than concatenating strings using +=.
930
931 unsigned int size = 0;
932 STAFObjectGetSize(object, &size);
933
934 STAFRefPtr<STAFString_t> stringArray = STAFRefPtr<STAFString_t>
935 (new STAFString_t[size],
936 STAFRefPtr<STAFString_t>::INIT,
937 size, STAFObjectFreeSTAFStringTArray);
938
939 unsigned int i = 0;
940
941 for (STAFObjectList::iterator iter = object->listValue->begin();
942 iter != object->listValue->end();
943 ++iter)
944 {
945 STAFString_t thisItemStringT = 0;
946 // XXX: Check RC?
947 STAFObjectMarshallToString(*iter, context, &thisItemStringT, flags);
948 stringArray[i++] = thisItemStringT;
949 }
950
951 STAFString_t joinedStringT = 0;
952 unsigned int osRC;
953
954 // XXX: Check RC from STAFStringConstructJoin?
955 STAFStringConstructJoin(&joinedStringT, stringArray, size, &osRC);
956
957 STAFString dataString = STAFString(joinedStringT, STAFString::kShallow);
958
959 outString += "@SDT/[";
960 outString += object->listValue->size();
961 outString += sColon;
962 outString += dataString.length(STAFString::kChar);
963 outString += sColon;
964 outString += dataString;
965 }
966 else if (object->type == kSTAFMapObject)
967 {
968 // If a staf-map-class-name key exists in the map, make sure that it's
969 // map class definition is provided in the marshalling context.
970 // If it's not, then treat the map as a plain map object.
971
972 bool isMapClass = false;
973 STAFString mapClassName;
974
975 if (context &&
976 (object->mapValue->find(sMapClassKey) != object->mapValue->end()))
977 {
978 mapClassName = *(*object->mapValue)[sMapClassKey]->
979 scalarStringValue;
980
981 unsigned int hasMapClassDefinition = 0;
982
983 STAFRC_t rc = STAFObjectMarshallingContextHasMapClassDefinition(
984 context, mapClassName.getImpl(), &hasMapClassDefinition);
985
986 if ((rc == kSTAFOk) && (hasMapClassDefinition)) isMapClass = true;
987 }
988
989 if (isMapClass)
990 {
991 // Note: Not much checking is done here as all the checking is done
992 // in STAFObjectMarshallingContextSetMapClassDefinition
993
994 // XXX: This whole block could use some rework to simplify all
995 // the dereferences
996
997 STAFString dataString;
998 dataString += sColon;
999 dataString += mapClassName.length(STAFString::kChar);
1000 dataString += sColon;
1001 dataString += mapClassName;
1002
1003 STAFObject_t keyList = (*(*context->contextValue->
1004 mapClassMap->mapValue)[mapClassName]->
1005 mapValue)["keys"];
1006
1007 // Get the number of keys in the map class definition and create an
1008 // array with that size.
1009 // Instead of creating an array using:
1010 // STAFString_t *stringArray = new STAFString_t[size];
1011 // we're using a STAFRefPtr<STAFString_t> custom array type so that
1012 // the array and it's contents will get destructed (even if an
1013 // exception occurs).
1014 // For each key in the map class, add a string representation to
1015 // the array and then join the strings in the array.
1016 // Using an array and then doing a join is done for performance
1017 // reasons as it's faster than concatenating strings using +=.
1018
1019 unsigned int size = 0;
1020 STAFObjectGetSize(keyList, &size);
1021
1022 STAFRefPtr<STAFString_t> stringArray = STAFRefPtr<STAFString_t>
1023 (new STAFString_t[size],
1024 STAFRefPtr<STAFString_t>::INIT,
1025 size, STAFObjectFreeSTAFStringTArray);
1026
1027 unsigned int i = 0;
1028
1029 for (STAFObjectList::iterator iter = keyList->listValue->begin();
1030 iter != keyList->listValue->end();
1031 ++iter)
1032 {
1033 STAFString &keyName =
1034 *(*(*iter)->mapValue)["key"]->scalarStringValue;
1035 STAFString_t thisItemStringT = 0;
1036 STAFObject_t thisItem = (*object->mapValue)[keyName];
1037
1038 if (thisItem == 0) thisItem = sNoneObjT;
1039
1040 STAFObjectMarshallToString(thisItem, context, &thisItemStringT,
1041 flags);
1042
1043 stringArray[i++] = thisItemStringT;
1044 }
1045
1046 STAFString_t joinedStringT = 0;
1047 unsigned int osRC;
1048
1049 STAFStringConstructJoin(&joinedStringT, stringArray, size, &osRC);
1050
1051 dataString += STAFString(joinedStringT, STAFString::kShallow);
1052
1053 outString += "@SDT/%:";
1054 outString += dataString.length(STAFString::kChar);
1055 outString += sColon;
1056 outString += dataString;
1057 }
1058 else
1059 {
1060 // Get the size of the map and create an array with that size.
1061 // Instead of creating an array using:
1062 // STAFString_t *stringArray = new STAFString_t[size];
1063 // we're using a STAFRefPtr<STAFString_t> custom array type so that
1064 // the array and it's contents will get destructed (even if an
1065 // exception occurs).
1066 // For each key/value in the map, add a string representation to
1067 // the array and then join the strings in the array.
1068 // Using an array and then doing a join is done for performance
1069 // reasons as it's faster than concatenating strings using +=.
1070
1071 unsigned int size = 0;
1072 STAFObjectGetSize(object, &size);
1073
1074 STAFRefPtr<STAFString_t> stringArray = STAFRefPtr<STAFString_t>
1075 (new STAFString_t[size],
1076 STAFRefPtr<STAFString_t>::INIT,
1077 size, STAFObjectFreeSTAFStringTArray);
1078
1079 unsigned int i = 0;
1080
1081 for (STAFObjectMap::iterator iter = object->mapValue->begin();
1082 iter != object->mapValue->end(); ++iter)
1083 {
1084 // First add the key
1085
1086 STAFString entryString = sColon;
1087 entryString += iter->first.length(STAFString::kChar);
1088 entryString += sColon;
1089 entryString += iter->first;
1090
1091 // Next add the value
1092
1093 STAFString_t thisItemStringT = 0;
1094 // XXX: Check RC?
1095 STAFObjectMarshallToString(iter->second, context,
1096 &thisItemStringT, flags);
1097
1098 entryString += STAFString(thisItemStringT, STAFString::kShallow);
1099
1100 stringArray[i++] = entryString.adoptImpl();
1101 }
1102
1103 STAFString_t joinedStringT = 0;
1104 unsigned int osRC;
1105
1106 STAFStringConstructJoin(&joinedStringT, stringArray, size, &osRC);
1107
1108 STAFString dataString = STAFString(joinedStringT, STAFString::kShallow);
1109
1110 outString += "@SDT/{:";
1111 outString += dataString.length(STAFString::kChar);
1112 outString += sColon;
1113 outString += dataString;
1114 }
1115 }
1116 else if (object->type == kSTAFMarshallingContextObject)
1117 {
1118 STAFString dataString;
1119 unsigned int size = 0;
1120 STAFObjectGetSize(object->contextValue->mapClassMap, &size);
1121
1122 if (size != 0)
1123 {
1124 // Get a reference to the context's map class map
1125
1126 STAFObject_t mapClassMap = 0;
1127
1128 STAFObjectConstructReference(&mapClassMap,
1129 object->contextValue->mapClassMap);
1130
1131 // Now create the context map for marshalling and add the context's
1132 // map class map as the "map-class-map" object
1133
1134 STAFObject_t contextMap = 0;
1135
1136 STAFObjectConstructMap(&contextMap);
1137 STAFObjectMapPut(contextMap, STAFString("map-class-map").getImpl(),
1138 mapClassMap);
1139 STAFObjectDestruct(&mapClassMap);
1140
1141 // Marshall the context map itself and then destruct it
1142 //
1143 // Note, the context map is not marshalled within any context. If it
1144 // were, we run the risk of recursive map class definitions, which
1145 // wouldn't work when unmarshalling.
1146
1147 STAFString_t mapClassMapStringT = 0;
1148
1149 STAFObjectMarshallToString(contextMap, 0, &mapClassMapStringT, flags);
1150
1151 STAFObjectDestruct(&contextMap);
1152
1153 // Generate the marshalled string, and destruct the string
1154 // containing the intermediate value
1155
1156 STAFStringConcatenate(dataString.getImpl(), mapClassMapStringT, 0);
1157 STAFStringDestruct(&mapClassMapStringT, 0);
1158 }
1159
1160 // Marshall the root object
1161 //
1162 // Note: We marshall the root object in the context of the context
1163 // we are marshalling (not the context that was passed in, which
1164 // might be different.
1165
1166 STAFString_t rootObjectStringT = 0;
1167
1168 STAFObjectMarshallToString(object->contextValue->rootObject, object,
1169 &rootObjectStringT, flags);
1170
1171 // Finally, generate the marshalled string, and destruct the string
1172 // containing the intermediate value
1173
1174 STAFStringConcatenate(dataString.getImpl(), rootObjectStringT, 0);
1175 STAFStringDestruct(&rootObjectStringT, 0);
1176
1177 if (size != 0)
1178 {
1179 outString += "@SDT/*";
1180 outString += sColon;
1181 outString += dataString.length(STAFString::kChar);
1182 outString += sColon;
1183 }
1184
1185 outString += dataString;
1186 }
1187 else
1188 {
1189 // Do what?
1190 }
1191
1192 *pString = outString.adoptImpl();
1193
1194 return kSTAFOk;
1195 }
1196
1197
STAFObjectUnmarshallFromString(STAFObject_t * newContext,STAFStringConst_t marshalledObject,STAFObject_t context,unsigned int flags)1198 STAFRC_t STAFObjectUnmarshallFromString(STAFObject_t *newContext,
1199 STAFStringConst_t marshalledObject,
1200 STAFObject_t context,
1201 unsigned int flags)
1202 {
1203 if (newContext == 0) return kSTAFInvalidObject;
1204 if (marshalledObject == 0) return kSTAFInvalidParm;
1205
1206 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1207 if ((context != 0) && (context->type != kSTAFMarshallingContextObject))
1208 return kSTAFInvalidParm;
1209
1210 static STAFString marshalledDataMarker("@SDT/");
1211 static STAFString noneMarker("@SDT/$0:0:");
1212 static STAFString scalarMarker("@SDT/$");
1213 static STAFString mapMarker("@SDT/{");
1214 static STAFString mcInstanceMarker("@SDT/%");
1215 static STAFString listMarker("@SDT/[");
1216 static STAFString contextMarker("@SDT/*");
1217 static STAFString sMapClassKey("staf-map-class-name");
1218
1219 STAFObjectConstructMarshallingContext(newContext);
1220
1221 // XXX: Probably shouldn't make a copy of the string like this, but I'm
1222 // going to make sure things work first, and then I'll optimize
1223
1224 STAFString data(marshalledObject);
1225
1226 try
1227 {
1228 if (data.startsWith(noneMarker))
1229 {
1230 // XXX: This is all probably redundant since the marshalling
1231 // context already has a None in it.
1232
1233 STAFObject_t noneObj = 0;
1234
1235 STAFObjectConstructNone(&noneObj);
1236 STAFObjectMarshallingContextSetRootObject(*newContext, noneObj);
1237 STAFObjectDestruct(&noneObj);
1238 }
1239 else if (data.startsWith(scalarMarker))
1240 {
1241 // @SDT/$S:<string-length>:<String>
1242
1243 unsigned int dataIndex = scalarMarker.length(STAFString::kChar);
1244
1245 // Get String length
1246
1247 unsigned int stringLength = getCLCLength(data, dataIndex);
1248
1249 if (stringLength != (data.length(STAFString::kChar) - dataIndex))
1250 throw STAFException("Invalid marshalled scalar data");
1251
1252 STAFObject_t stringObj = 0;
1253 STAFObjectConstructScalarString(
1254 &stringObj, data.subString(dataIndex).getImpl());
1255
1256 // Unless told otherwise we will try to unmarshall a nested object
1257 // reference
1258
1259 if ((flags & kSTAFIgnoreIndirectObjects) ||
1260 !stringObj->scalarStringValue->startsWith(
1261 marshalledDataMarker))
1262 {
1263 STAFObjectMarshallingContextSetRootObject(
1264 *newContext, stringObj);
1265 }
1266 else
1267 {
1268 STAFObject_t nestedContext = 0;
1269
1270 STAFObjectUnmarshallFromString(
1271 &nestedContext, stringObj->scalarStringValue->getImpl(),
1272 context, flags);
1273
1274 STAFObject_t primaryObject = adoptPrimaryObject(
1275 nestedContext);
1276
1277 STAFObjectMarshallingContextSetRootObject(
1278 *newContext, primaryObject);
1279 STAFObjectDestruct(&primaryObject);
1280 }
1281
1282 STAFObjectDestruct(&stringObj);
1283 }
1284 else if (data.startsWith(listMarker))
1285 {
1286 // @SDT/[<number-of-items>:<array-length>:<SDT-Any-1>...<SDT-Any-n>
1287
1288 // Get the number of items in the list
1289
1290 unsigned int colonIndex = data.find(sColon);
1291
1292 if (colonIndex == STAFString::kNPos)
1293 throw STAFException("Invalid marshalled list data");
1294
1295 unsigned int numItems = data.subString(6, colonIndex - 6).asUInt();
1296
1297 unsigned int dataIndex = colonIndex;
1298
1299 // Get the array length
1300
1301 unsigned int arrayLength = getCLCLength(data, dataIndex);
1302
1303 if (arrayLength != (data.length(STAFString::kChar) - dataIndex))
1304 throw STAFException("Invalid marshalled list data");
1305
1306 STAFObject_t listObj = 0;
1307
1308 STAFObjectConstructList(&listObj);
1309
1310 for (unsigned int i = 0; i < numItems; ++i)
1311 {
1312 STAFObject_t obj = unmarshallObject(
1313 data, context, dataIndex, flags);
1314
1315 STAFObjectListAppend(listObj, obj);
1316 STAFObjectDestruct(&obj);
1317 }
1318
1319 STAFObjectMarshallingContextSetRootObject(*newContext, listObj);
1320 STAFObjectDestruct(&listObj);
1321 }
1322 else if (data.startsWith(mapMarker))
1323 {
1324 // @SDT/{:<map-length>::<key-1-length>:<key-1><SDT-Any>
1325 // ...
1326 // :<key-n-length>:<key-1><SDT-Any>
1327
1328 unsigned int dataIndex = mapMarker.length(STAFString::kChar);
1329
1330 // Get the map-length and increment dataIndex
1331
1332 unsigned int mapLength = getCLCLength(data, dataIndex);
1333
1334 if (mapLength != (data.length(STAFString::kChar) - dataIndex))
1335 throw STAFException("Invalid marshalled map data");
1336
1337 STAFObject_t mapObj = 0;
1338
1339 STAFObjectConstructMap(&mapObj);
1340
1341 while (dataIndex < data.length(STAFString::kChar))
1342 {
1343 STAFString key = getCLCString(data, dataIndex);
1344 STAFObject_t obj = unmarshallObject(
1345 data, context, dataIndex, flags);
1346
1347 STAFObjectMapPut(mapObj, key.getImpl(), obj);
1348 STAFObjectDestruct(&obj);
1349 }
1350
1351 STAFObjectMarshallingContextSetRootObject(*newContext, mapObj);
1352 STAFObjectDestruct(&mapObj);
1353 }
1354 else if (data.startsWith(mcInstanceMarker))
1355 {
1356 // @SDT/%:<map-class-instance-length>::<map-class-name-length>:<map-class-name>
1357 // <SDT-Any-value-1>
1358 // ...
1359 // <SDT-Any-value-n>
1360
1361 STAFObject_t mapObj = 0;
1362
1363 STAFObjectConstructMap(&mapObj);
1364
1365 unsigned int dataIndex = mcInstanceMarker.length(
1366 STAFString::kChar);
1367
1368 // Get the map-class-instance-length and increment dataIndex
1369
1370 unsigned int mapClassInstanceLength = getCLCLength(
1371 data, dataIndex);
1372
1373 if (mapClassInstanceLength != (data.length(STAFString::kChar) -
1374 dataIndex))
1375 throw STAFException("Invalid marshalled map data");
1376
1377 // Get the map-class-name
1378
1379 STAFString mapClassName = getCLCString(data, dataIndex);
1380
1381 // Now add the map class name to the map
1382
1383 STAFObject_t mapClassNameObj = 0;
1384
1385 STAFObjectConstructScalarString(&mapClassNameObj,
1386 mapClassName.getImpl());
1387
1388 STAFObjectMapPut(mapObj, sMapClassKey.getImpl(), mapClassNameObj);
1389 STAFObjectDestruct(&mapClassNameObj);
1390
1391 // Now unmarshall all the actual keys
1392
1393 STAFObject_t mapClassObj =
1394 (*context->contextValue->mapClassMap->mapValue)[mapClassName];
1395 STAFObject_t keyList = (*mapClassObj->mapValue)["keys"];
1396 STAFObjectList::iterator iter = keyList->listValue->begin();
1397
1398 while (dataIndex < data.length(STAFString::kChar))
1399 {
1400 STAFObject_t keyStringObj = (*(*iter)->mapValue)["key"];
1401 STAFString_t keyImpl = keyStringObj->scalarStringValue->
1402 getImpl();
1403 STAFObject_t obj = unmarshallObject(
1404 data, context, dataIndex, flags);
1405
1406 STAFObjectMapPut(mapObj, keyImpl, obj);
1407 STAFObjectDestruct(&obj);
1408
1409 ++iter;
1410 }
1411
1412 STAFObjectMarshallingContextSetRootObject(*newContext, mapObj);
1413 STAFObjectDestruct(&mapObj);
1414 }
1415 else if (data.startsWith(contextMarker))
1416 {
1417 // @SDT/*:<context-length>:@SDT/{:<mapClassLength>:<mapClassData>
1418 // <rootObject>
1419
1420 // Get context-length
1421
1422 unsigned int dataIndex = contextMarker.length(STAFString::kChar);
1423
1424 unsigned int contextLength = getCLCLength(data, dataIndex);
1425
1426 if (contextLength != (data.length(STAFString::kChar) - dataIndex))
1427 throw STAFException("Invalid marshalled context");
1428
1429 STAFObject_t contextMap = unmarshallObject(
1430 data, 0, dataIndex, flags);
1431
1432 // Now we need to take ownership of the underlying map class map.
1433 // 1) Destruct the existing map class map in the new context
1434 // 2) "Adopt" the map class map from the context map
1435 // 3) Construct a None in the place of the "adopted" map class map
1436 // in the context map
1437 // 4) Destruct the context map since we don't need it any more
1438
1439 STAFObjectDestruct(&(*newContext)->contextValue->mapClassMap);
1440
1441 (*newContext)->contextValue->mapClassMap =
1442 (*contextMap->mapValue)["map-class-map"];
1443
1444 STAFObjectConstructNone(
1445 &(*contextMap->mapValue)["map-class-map"]);
1446
1447 STAFObjectDestruct(&contextMap);
1448
1449 // Now, get and set the root object
1450
1451 STAFObject_t rootObject = unmarshallObject(
1452 data, *newContext, dataIndex, flags);
1453
1454 STAFObjectMarshallingContextSetRootObject(
1455 *newContext, rootObject);
1456 STAFObjectDestruct(&rootObject);
1457 }
1458 else
1459 {
1460 // We don't know what this data is, so just return a Scalar String
1461 // object containing the whole string
1462
1463 STAFObject_t stringObj = 0;
1464
1465 STAFObjectConstructScalarString(&stringObj, data.getImpl());
1466 STAFObjectMarshallingContextSetRootObject(*newContext, stringObj);
1467 STAFObjectDestruct(&stringObj);
1468 }
1469 }
1470 catch (...)
1471 {
1472 // An exception occurred processing the marshalling data.
1473 // This means its probably invalid marshalled data, so just return
1474 // a Scalar String object containing the invalid marshalled data.
1475
1476 STAFObject_t stringObj = 0;
1477
1478 STAFObjectConstructScalarString(&stringObj, data.getImpl());
1479 STAFObjectMarshallingContextSetRootObject(*newContext, stringObj);
1480 STAFObjectDestruct(&stringObj);
1481 }
1482
1483 return kSTAFOk;
1484 }
1485
1486
STAFObjectListAppend(STAFObject_t list,STAFObject_t obj)1487 STAFRC_t STAFObjectListAppend(STAFObject_t list, STAFObject_t obj)
1488 {
1489 if (list == 0) return kSTAFInvalidObject;
1490 if (obj == 0) return kSTAFInvalidParm;
1491 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1492 if (list->type != kSTAFListObject) return kSTAFInvalidObject;
1493
1494 // Note: The object being passed in gets turned into a reference
1495
1496 STAFObject_t newObj = new STAFObjectImpl(*obj);
1497
1498 obj->isRef = true;
1499
1500 list->listValue->push_back(newObj);
1501
1502 return kSTAFOk;
1503 }
1504
1505
STAFObjectIteratorHasNext(STAFObjectIterator_t iter,unsigned int * hasNext)1506 STAFRC_t STAFObjectIteratorHasNext(STAFObjectIterator_t iter,
1507 unsigned int *hasNext)
1508 {
1509 if (iter == 0) return kSTAFInvalidObject;
1510 if (hasNext == 0) return kSTAFInvalidParm;
1511
1512 if (iter->type == kSTAFObjectListIterator)
1513 {
1514 *hasNext = (iter->listIterator->iter ==
1515 iter->listIterator->listObject->end()) ? 0 : 1;
1516 }
1517 else if ((iter->type == kSTAFObjectMapKeyIterator) ||
1518 (iter->type == kSTAFObjectMapValueIterator))
1519 {
1520 *hasNext = (iter->mapIterator->iter ==
1521 iter->mapIterator->mapObject->end()) ? 0 : 1;
1522 }
1523 else
1524 {
1525 // XXX: Return an error?
1526 *hasNext = 0;
1527 }
1528
1529 return kSTAFOk;
1530 }
1531
1532
STAFObjectIteratorGetNext(STAFObjectIterator_t iter,STAFObject_t * pObject)1533 STAFRC_t STAFObjectIteratorGetNext(STAFObjectIterator_t iter,
1534 STAFObject_t *pObject)
1535 {
1536 if (iter == 0) return kSTAFInvalidObject;
1537 if (pObject == 0) return kSTAFInvalidParm;
1538
1539 if (iter->type == kSTAFObjectListIterator)
1540 {
1541 STAFObjectConstructReference(pObject, *iter->listIterator->iter);
1542 ++iter->listIterator->iter;
1543 }
1544 else if (iter->type == kSTAFObjectMapKeyIterator)
1545 {
1546 STAFObjectConstructScalarString(
1547 pObject, iter->mapIterator->iter->first.getImpl());
1548 ++iter->mapIterator->iter;
1549 }
1550 else if (iter->type == kSTAFObjectMapValueIterator)
1551 {
1552 STAFObjectConstructReference(pObject, iter->mapIterator->iter->second);
1553 ++iter->mapIterator->iter;
1554 }
1555 else return kSTAFInvalidObject;
1556
1557 return kSTAFOk;
1558 }
1559
1560
STAFObjectIteratorDestruct(STAFObjectIterator_t * iter)1561 STAFRC_t STAFObjectIteratorDestruct(STAFObjectIterator_t *iter)
1562 {
1563 if (iter == 0) return kSTAFInvalidObject;
1564 if (*iter == 0) return kSTAFInvalidObject;
1565
1566 if ((*iter)->type == kSTAFObjectListIterator)
1567 delete (*iter)->listIterator;
1568 else
1569 delete (*iter)->mapIterator;
1570
1571 delete *iter;
1572
1573 *iter = 0;
1574
1575 return kSTAFOk;
1576 }
1577
1578
STAFObjectMapHasKey(STAFObject_t map,STAFStringConst_t key,unsigned int * pHasKey)1579 STAFRC_t STAFObjectMapHasKey(STAFObject_t map, STAFStringConst_t key,
1580 unsigned int *pHasKey)
1581 {
1582 if (map == 0) return kSTAFInvalidObject;
1583 if (key == 0) return kSTAFInvalidParm;
1584 if (pHasKey == 0) return kSTAFInvalidParm;
1585 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1586 if (map->type != kSTAFMapObject) return kSTAFInvalidObject;
1587
1588 STAFObjectMap::iterator iter = map->mapValue->find(key);
1589
1590 if (iter == map->mapValue->end())
1591 *pHasKey = 0;
1592 else
1593 *pHasKey = 1;
1594
1595 return kSTAFOk;
1596 }
1597
1598
STAFObjectMapGet(STAFObject_t map,STAFStringConst_t key,STAFObject_t * pObject)1599 STAFRC_t STAFObjectMapGet(STAFObject_t map, STAFStringConst_t key,
1600 STAFObject_t *pObject)
1601 {
1602 if (map == 0) return kSTAFInvalidObject;
1603 if (key == 0) return kSTAFInvalidParm;
1604 if (pObject == 0) return kSTAFInvalidParm;
1605 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1606 if (map->type != kSTAFMapObject) return kSTAFInvalidObject;
1607
1608 STAFObjectMap::iterator iter = map->mapValue->find(key);
1609
1610 if (iter == map->mapValue->end())
1611 STAFObjectConstructNone(pObject);
1612 else
1613 STAFObjectConstructReference(pObject, iter->second);
1614
1615 return kSTAFOk;
1616 }
1617
1618
STAFObjectMapPut(STAFObject_t map,STAFStringConst_t key,STAFObject_t obj)1619 STAFRC_t STAFObjectMapPut(STAFObject_t map, STAFStringConst_t key,
1620 STAFObject_t obj)
1621 {
1622 if (map == 0) return kSTAFInvalidObject;
1623 if (key == 0) return kSTAFInvalidParm;
1624 if (obj == 0) return kSTAFInvalidParm;
1625 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1626 if (map->type != kSTAFMapObject) return kSTAFInvalidObject;
1627
1628 // If there is already something associated with this key, we have to
1629 // get rid of it first
1630
1631 STAFObjectMap::iterator iter = map->mapValue->find(key);
1632
1633 if (iter != map->mapValue->end())
1634 {
1635 STAFObjectDestruct(&iter->second);
1636 }
1637
1638 // Now add the new object
1639 // Note: The object being passed in gets turned into a reference
1640
1641 STAFObject_t newObj = new STAFObjectImpl(*obj);
1642
1643 obj->isRef = true;
1644
1645 (*map->mapValue)[key] = newObj;
1646
1647 return kSTAFOk;
1648 }
1649
1650
STAFObjectMarshallingContextSetMapClassDefinition(STAFObject_t context,STAFStringConst_t name,STAFObject_t obj)1651 STAFRC_t STAFObjectMarshallingContextSetMapClassDefinition(
1652 STAFObject_t context,
1653 STAFStringConst_t name,
1654 STAFObject_t obj)
1655 {
1656 if (context == 0) return kSTAFInvalidObject;
1657 if (name == 0) return kSTAFInvalidParm;
1658 if (obj == 0) return kSTAFInvalidParm;
1659 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1660 if (context->type != kSTAFMarshallingContextObject)
1661 return kSTAFInvalidObject;
1662
1663 // XXX: We need to do a good bit of checking to ensure that the map class
1664 // definition is valid
1665
1666 // If there is already something associated with this key, we have to
1667 // get rid of it first
1668
1669 STAFObjectMap::iterator iter =
1670 context->contextValue->mapClassMap->mapValue->find(name);
1671
1672 if (iter != context->contextValue->mapClassMap->mapValue->end())
1673 {
1674 STAFObjectDestruct(&iter->second);
1675 }
1676
1677 // Now add the new object
1678 // Note: The object being passed in gets turned into a reference
1679
1680 STAFObject_t newObj = new STAFObjectImpl(*obj);
1681
1682 obj->isRef = true;
1683
1684 (*context->contextValue->mapClassMap->mapValue)[name] = newObj;
1685
1686 return kSTAFOk;
1687 }
1688
1689
STAFObjectMarshallingContextGetMapClassDefinition(STAFObject_t context,STAFStringConst_t name,STAFObject_t * pObject)1690 STAFRC_t STAFObjectMarshallingContextGetMapClassDefinition(
1691 STAFObject_t context,
1692 STAFStringConst_t name,
1693 STAFObject_t *pObject)
1694 {
1695 if (context == 0) return kSTAFInvalidObject;
1696 if (name == 0) return kSTAFInvalidParm;
1697 if (pObject == 0) return kSTAFInvalidParm;
1698 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1699 if (context->type != kSTAFMarshallingContextObject)
1700 return kSTAFInvalidObject;
1701
1702 STAFObjectMap::iterator iter =
1703 context->contextValue->mapClassMap->mapValue->find(name);
1704
1705 if (iter == context->contextValue->mapClassMap->mapValue->end())
1706 STAFObjectConstructNone(pObject);
1707 else
1708 STAFObjectConstructReference(pObject, iter->second);
1709
1710 return kSTAFOk;
1711 }
1712
1713
STAFObjectMarshallingContextHasMapClassDefinition(STAFObject_t context,STAFStringConst_t name,unsigned int * pHasMapClassDefinition)1714 STAFRC_t STAFObjectMarshallingContextHasMapClassDefinition(
1715 STAFObject_t context,
1716 STAFStringConst_t name,
1717 unsigned int *pHasMapClassDefinition)
1718 {
1719 if (context == 0) return kSTAFInvalidObject;
1720 if (name == 0) return kSTAFInvalidParm;
1721 if (pHasMapClassDefinition == 0) return kSTAFInvalidParm;
1722 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1723 if (context->type != kSTAFMarshallingContextObject)
1724 return kSTAFInvalidObject;
1725
1726 return STAFObjectMapHasKey(context->contextValue->mapClassMap, name,
1727 pHasMapClassDefinition);
1728 }
1729
1730
STAFObjectMarshallingContextSetRootObject(STAFObject_t context,STAFObject_t obj)1731 STAFRC_t STAFObjectMarshallingContextSetRootObject(STAFObject_t context,
1732 STAFObject_t obj)
1733 {
1734 if (context == 0) return kSTAFInvalidObject;
1735 if (obj == 0) return kSTAFInvalidParm;
1736 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1737 if (context->type != kSTAFMarshallingContextObject)
1738 return kSTAFInvalidObject;
1739
1740 // Get rid of the old root object
1741
1742 STAFObjectDestruct(&context->contextValue->rootObject);
1743
1744 // Now set the new root object
1745 // Note: The object being passed in gets turned into a reference
1746
1747 context->contextValue->rootObject = new STAFObjectImpl(*obj);
1748
1749 obj->isRef = true;
1750
1751 return kSTAFOk;
1752 }
1753
1754
STAFObjectMarshallingContextGetRootObject(STAFObject_t context,STAFObject_t * pObject)1755 STAFRC_t STAFObjectMarshallingContextGetRootObject(STAFObject_t context,
1756 STAFObject_t *pObject)
1757 {
1758 if (context == 0) return kSTAFInvalidObject;
1759 if (pObject == 0) return kSTAFInvalidParm;
1760 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1761 if (context->type != kSTAFMarshallingContextObject)
1762 return kSTAFInvalidObject;
1763
1764 STAFObjectConstructReference(pObject, context->contextValue->rootObject);
1765
1766 return kSTAFOk;
1767 }
1768
1769
STAFObjectMarshallingContextAdoptRootObject(STAFObject_t context,STAFObject_t * pObject)1770 STAFRC_t STAFObjectMarshallingContextAdoptRootObject(STAFObject_t context,
1771 STAFObject_t *pObject)
1772 {
1773 if (context == 0) return kSTAFInvalidObject;
1774 if (pObject == 0) return kSTAFInvalidParm;
1775 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1776 if (context->type != kSTAFMarshallingContextObject)
1777 return kSTAFInvalidObject;
1778
1779 // Copy our root object into the destination
1780 *pObject = new STAFObjectImpl(*context->contextValue->rootObject);
1781
1782 // Note: The marshalling context root object is now a reference
1783 context->contextValue->rootObject->isRef = true;
1784
1785 return kSTAFOk;
1786 }
1787
1788
STAFObjectMarshallingContextGetPrimaryObject(STAFObject_t context,STAFObject_t * pObject)1789 STAFRC_t STAFObjectMarshallingContextGetPrimaryObject(STAFObject_t context,
1790 STAFObject_t *pObject)
1791 {
1792 if (context == 0) return kSTAFInvalidObject;
1793 if (pObject == 0) return kSTAFInvalidParm;
1794 // XXX: Might this want to be a new kSTAFInvalidOperation ?
1795 if (context->type != kSTAFMarshallingContextObject)
1796 return kSTAFInvalidObject;
1797
1798 if (context->contextValue->mapClassMap->mapValue->size() != 0)
1799 STAFObjectConstructReference(pObject, context);
1800 else
1801 STAFObjectConstructReference(pObject, context->contextValue->rootObject);
1802
1803 return kSTAFOk;
1804 }
1805