29 mike 1.1 //
30 //END_HISTORY
31
32 #include <cctype>
33 #include <fstream>
34 #include <Pegasus/Common/Pair.h>
35 #include <Pegasus/Common/Destroyer.h>
36 #include <Pegasus/Common/FileSystem.h>
37 #include <Pegasus/Common/Exception.h>
38 #include <Pegasus/Common/XmlReader.h>
39 #include <Pegasus/Common/XmlWriter.h>
40 #include <Pegasus/Common/DeclContext.h>
41 #include "Repository.h"
42
43 #define INDENT_XML_FILES
44
45 PEGASUS_NAMESPACE_BEGIN
46
47 ////////////////////////////////////////////////////////////////////////////////
48 //
49 // Local functions
50 mike 1.1 //
51 ////////////////////////////////////////////////////////////////////////////////
52
53 //------------------------------------------------------------------------------
54 //
55 // This routine matches files in the classes directory (given by path)
56 // that match the second and third arguments, which are eight class names
57 // or asterisks (which are wild cards). All the files in the ./classes
58 // directory are of the form <className.superClassName>. For classes
59 // with no superClass, the superClassName is "#". We consider a couple of
60 // examples. To find all direct subclasses of "MyClass", we invoke it
61 // as follows:
62 //
63 // _GlobClassesDir(path, "*", "MyClass");
64 //
65 // To find the file which contains the class called "MyClass", we invoke
66 // it like this.
67 //
68 // _GlobClassesDir(path, "MyClass", "*");
69 //
70 // Since base classes are of the form "<ClassName>.#", all baseclasses may
71 mike 1.1 // be found with:
72 //
73 // _GlobClassesDir(path, "*", "#");
74 //
75 // Note that the results (the array of filenames which are returned) must
76 // be processed further to get the actual class names. The name of the
77 // class is the filename less the extension. Or this:
78 //
79 // String className = fileName.subString(fileName.find(0, '.'));
80 //
81 //------------------------------------------------------------------------------
82
83 Array<String> _GlobClassesDir(
84 const String& path,
85 const String& className,
86 const String& superClassName)
87 {
88 Array<String> fileNames;
89
90 if (!FileSystem::getDirectoryContents(path, fileNames))
91 throw NoSuchDirectory(path);
92 mike 1.1
93 Array<String> result;
94
95 for (Uint32 i = 0; i < fileNames.getSize(); i++)
96 {
97 const String& tmp = fileNames[i];
98
99 Uint32 dot = tmp.find('.');
100
101 // Ignore files that do not contain a dot:
102
103 if (dot == Uint32(-1))
104 continue;
105
106 String first = tmp.subString(0, dot);
107 String second = tmp.subString(dot + 1);
108
109 if ((className == "*" || first == className) &&
110 (superClassName == "*" || second == superClassName))
111 {
112 result.append(tmp);
113 mike 1.1 }
114 }
115
116 return result;
117 }
118
119 static Boolean _SkipIdentifier(Char16*& p)
120 {
121 if (!*p || !(isalpha(*p) || *p == '_'))
122 return false;
123
124 for (p++; *p; p++)
125 {
126 if (!(isalnum(*p) || *p == '_'))
127 return true;
128 }
129
130 return true;
131 }
132
133 static void _MakeNameSpacePath(
134 mike 1.1 const String& root,
135 const String& nameSpace,
136 String& path)
137 {
138 path = root;
139 path.append('/');
140
141 path.append(nameSpace);
142
143 Char16* p = (Char16*)(path.getData() + root.getLength() + 1);
144
145 while (*p)
146 {
147 // Either we will encounter a slash or an identifier:
148
149 if (*p == '/')
150 {
151 if (p[1] == '/')
152 throw CimException(CimException::INVALID_NAMESPACE);
153
154 *p++ = '#';
155 mike 1.1 }
156 else if (!_SkipIdentifier(p))
157 throw CimException(CimException::INVALID_NAMESPACE);
158 }
159
160 // The last element may NOT be a slash (slashes are translated to
161 // #'s above).
162
163 if (p[-1] == '#')
164 throw CimException(CimException::INVALID_NAMESPACE);
165 }
166
167 void _FindClass(
168 const String& root,
169 const String& nameSpace,
170 const String& className,
171 String& path)
172 {
173 const char CLASSES[] = "/classes/";
174 _MakeNameSpacePath(root, nameSpace, path);
175
176 mike 1.1 if (!FileSystem::isDirectory(path))
177 throw CimException(CimException::INVALID_NAMESPACE);
178
179 path.append(CLASSES);
180
181 Array<String> fileNames = _GlobClassesDir(path, className, "*");
182
183 Uint32 size = fileNames.getSize();
184
185 if (size == 0)
186 throw CimException(CimException::INVALID_CLASS);
187
188 PEGASUS_ASSERT(size == 1);
189 path.append(fileNames[0]);
190 }
191
192 inline Uint32 _min(Uint32 x, Uint32 y)
193 {
194 return x < y ? x : y;
195 }
196
197 mike 1.1 static void _MakeNewClassPath(
198 const String& root,
199 const String& nameSpace,
200 const String& className,
201 const String& superClassName,
202 String& path)
203 {
204 const char CLASSES[] = "/classes/";
205 _MakeNameSpacePath(root, nameSpace, path);
206
207 if (!FileSystem::isDirectory(path))
208 throw CimException(CimException::INVALID_NAMESPACE);
209
210 path.append(CLASSES);
211 path.append(className);
212 path.append('.');
213
214 if (superClassName.getLength() == 0)
215 path.append("#");
216 else
217 path.append(superClassName);
218 mike 1.1 }
219
220 static void _MakeQualfierPath(
221 const String& root,
222 const String& nameSpace,
223 const String& qualifierName,
224 String& path)
225 {
226 const char QUALIFIERS[] = "/qualifiers/";
227 _MakeNameSpacePath(root, nameSpace, path);
228
229 if (!FileSystem::isDirectory(path))
230 throw CimException(CimException::INVALID_NAMESPACE);
231
232 path.append('/');
233 path.append(QUALIFIERS);
234 path.append(qualifierName);
235 }
236
237 template<class Object>
238 void _LoadObject(
239 mike 1.1 const String& path,
240 Object& object)
241 {
242 // Open the file:
243
244 Destroyer<char> destroyer(path.allocateCString());
245 std::ifstream is(destroyer.getPointer());
246
247 if (!is)
248 throw CannotOpenFile(path);
249
250 // Load file into memory:
251
252 Array<Sint8> data;
253 FileSystem::loadFileToMemory(data, path);
254 data.append('\0');
255
256 XmlParser parser((char*)data.getData());
257
258 XmlReader::getObject(parser, object);
259 }
260 mike 1.1
261 template<class Object>
262 void _SaveObject(const String& path, Object& object)
263 {
264 Array<Sint8> out;
265 object.toXml(out);
266 out.append('\0');
267
268 Destroyer<char> destroyer(path.allocateCString());
269
270 #ifdef PEGASUS_OS_TYPE_WINDOWS
271 std::ofstream os(destroyer.getPointer(), std::ios::binary);
272 #else
273 std::ofstream os(destroyer.getPointer());
274 #endif
275
276 if (!os)
277 throw CannotOpenFile(path);
278
279 #ifdef INDENT_XML_FILES
280 XmlWriter::indentedPrint(os, out.getData(), 2);
281 mike 1.1 #else
282 os.write((char*)out.getData(), out.getSize());
283 #endif
284 }
285
286 static void _AppendClassNames(
287 const String& path,
288 const String& className,
289 const String& superClassName,
290 Array<String>& classNames)
291 {
292 Array<String> allFiles;
293
294 if (!FileSystem::getDirectoryContents(path, allFiles))
295 throw NoSuchDirectory(path);
296
297 // Append all the direct sublclasses of the class to the output argument:
298
299 Array<String> fileNames =
300 _GlobClassesDir(path, className, superClassName);
301
302 mike 1.1 for (Uint32 i = 0, n = fileNames.getSize(); i < n; i++)
303 {
304 String& tmp = fileNames[i];
305 Uint32 pos = tmp.find('.');
306
307 PEGASUS_ASSERT(pos != Uint32(-1));
308
309 if (pos != Uint32(-1))
310 tmp.remove(pos);
311
312 classNames.append(tmp);
313 }
314 }
315
316 typedef Pair<String,String> Node;
317
318 static void _AppendSubclassesDeepAux(
319 const Array<Node>& table,
320 const String& className,
321 Array<String>& classNames)
322 {
323 mike 1.1 for (Uint32 i = 0, n = table.getSize(); i < n; i++)
324 {
325 if (className == table[i].second)
326 {
327 classNames.append(table[i].first);
328 _AppendSubclassesDeepAux(table, table[i].first, classNames);
329 }
330 }
331 }
332
333 static void _AppendSubclassesDeep(
334 const String& path,
335 const String& className,
336 Array<String>& classNames)
337 {
338 Array<String> allFiles;
339
340 if (!FileSystem::getDirectoryContents(path, allFiles))
341 throw NoSuchDirectory(path);
342
343 Array<Node> table;
344 mike 1.1 table.reserve(allFiles.getSize());
345
346 for (Uint32 i = 0, n = allFiles.getSize(); i < n; i++)
347 {
348 const String& fileName = allFiles[i];
349
350 Uint32 dot = fileName.find('.');
351
352 if (dot == Uint32(-1))
353 continue;
354
355 String first = fileName.subString(0, dot);
356 String second = fileName.subString(dot + 1);
357
358 if (second == "#")
359 table.append(Node(first, String()));
360 else
361 table.append(Node(first, second));
362 }
363
364 _AppendSubclassesDeepAux(table, className, classNames);
365 mike 1.1 }
366
367 static Boolean _HasSubclasses(
368 const String& root,
369 const String& nameSpace,
370 const String& className)
371 {
372 const char CLASSES[] = "/classes";
373 String path;
374 _MakeNameSpacePath(root, nameSpace, path);
375 path.append(CLASSES);
376
377 Array<String> fileNames = _GlobClassesDir(path, "*", className);
378
379 return fileNames.getSize() != 0;
380 }
381
382 ////////////////////////////////////////////////////////////////////////////////
383 //
384 // RepositoryDeclContext
385 //
386 mike 1.1 ////////////////////////////////////////////////////////////////////////////////
387
388 class RepositoryDeclContext : public DeclContext
389 {
390 public:
391
392 RepositoryDeclContext(Repository* repository);
393
394 virtual ~RepositoryDeclContext();
395
396 virtual QualifierDecl lookupQualifierDecl(
397 const String& nameSpace,
398 const String& qualifierName) const;
399
400 virtual ClassDecl lookupClassDecl(
401 const String& nameSpace,
402 const String& className) const;
403
404 private:
405
406 Repository* _repository;
407 mike 1.1 };
408
409 RepositoryDeclContext::RepositoryDeclContext(Repository* repository)
410 : _repository(repository)
411 {
412
413 }
414
415 RepositoryDeclContext::~RepositoryDeclContext()
416 {
417
418 }
419
420 QualifierDecl RepositoryDeclContext::lookupQualifierDecl(
421 const String& nameSpace,
422 const String& qualifierName) const
423 {
424 // Ignore the exception since this routine is only supposed report
425 // whether it can be found:
426
427 try
428 mike 1.1 {
429 return _repository->getQualifier(nameSpace, qualifierName);
430 }
431 catch (Exception&)
432 {
433 return QualifierDecl();
434 }
435 }
436
437 ClassDecl RepositoryDeclContext::lookupClassDecl(
438 const String& nameSpace,
439 const String& className) const
440 {
441 // Ignore the exception since this routine is only supposed report
442 // whether it can be found:
443
444 try
445 {
446 return _repository->getClass(nameSpace, className, false, true, true);
447 }
448 catch (Exception&)
449 mike 1.1 {
450 return ClassDecl();
451 }
452 }
453
454 ////////////////////////////////////////////////////////////////////////////////
455 //
456 // Repository
457 //
458 ////////////////////////////////////////////////////////////////////////////////
459
460 Repository::Repository(const String& path)
461 {
462 const char REPOSITORY[] = "/repository";
463 _root = path;
464 _root.append(REPOSITORY);
465
466 if (!FileSystem::isDirectory(_root))
467 {
468 if (!FileSystem::makeDirectory(_root))
469 throw CannotCreateDirectory(_root);
470 mike 1.1 }
471
472 _context = new RepositoryDeclContext(this);
473 }
474
475 Repository::~Repository()
476 {
477
478 }
479
480 ClassDecl Repository::getClass(
481 const String& nameSpace,
482 const String& className,
483 Boolean localOnly,
484 Boolean includeQualifiers,
485 Boolean includeClassOrigin,
486 const Array<String>& propertyList)
487 {
488 // Form the path to the class:
489
490 String path;
491 mike 1.1 _FindClass(_root, nameSpace, className, path);
492
493 // Load the class:
494
495 ClassDecl classDecl;
496 _LoadObject(path, classDecl);
497
498 return ClassDecl(classDecl);
499 }
500
501 InstanceDecl Repository::getInstance(
502 const String& nameSpace,
503 const Reference& instanceName,
504 Boolean localOnly,
505 Boolean includeQualifiers,
506 Boolean includeClassOrigin,
507 const Array<String>& propertyList)
508 {
509 throw CimException(CimException::NOT_SUPPORTED);
510 return InstanceDecl();
511 }
512 mike 1.1
513 void Repository::deleteClass(
514 const String& nameSpace,
515 const String& className)
516 {
517 // Get path of class file:
518
519 String path;
520 _FindClass(_root, nameSpace, className, path);
521
522 // Disallow if the class has subclasses:
523
524 if (_HasSubclasses(_root, nameSpace, className))
525 throw CimException(CimException::CLASS_HAS_CHILDREN);
526
527 // ATTN-C: check to see if the class has instances:
528
529 // Remove the class:
530
531 if (!FileSystem::removeFile(path))
532 throw FailedToRemoveFile(path);
533 mike 1.1 }
534
535 void Repository::deleteInstance(
536 const String& nameSpace,
537 const Reference& instanceName)
538 {
539 throw CimException(CimException::NOT_SUPPORTED);
540 }
541
542 void Repository::createClass(
543 const String& nameSpace,
544 ClassDecl& newClass)
545 {
546 // Form the path to the class:
547
548 String path;
549 const String& className = newClass.getClassName();
550 const String& superClassName = newClass.getSuperClassName();
551 _MakeNewClassPath(_root, nameSpace, className, superClassName, path);
552
553 if (FileSystem::exists(path))
554 mike 1.1 throw CimException(CimException::ALREADY_EXISTS);
555
556 // Validate the new class:
557
558 newClass.resolve(_context, nameSpace);
559
560 // Save the class:
561
562 _SaveObject(path, newClass);
563 }
564
565 void Repository::createInstance(
566 const String& nameSpace,
567 const InstanceDecl& newInstance)
568 {
569 throw CimException(CimException::NOT_SUPPORTED);
570 }
571
572 void Repository::modifyClass(
573 const String& nameSpace,
574 ClassDecl& modifiedClass)
575 mike 1.1 {
576 // ATTN: need lots of semantic checking here:
577
578 // Get the old class:
579
580 ClassDecl oldClass = getClass(
581 nameSpace, modifiedClass.getClassName(), false, true, true);
582
583 // Disallow changing the name of the super-class:
584
585 if (modifiedClass.getSuperClassName() != oldClass.getSuperClassName())
586 throw CimException(CimException::INVALID_SUPERCLASS);
587
588 // Delete the old class:
589
590 deleteClass(nameSpace, modifiedClass.getClassName());
591
592 // Create the class again:
593
594 createClass(nameSpace, modifiedClass);
595 }
596 mike 1.1
597 void Repository::modifyInstance(
598 const String& nameSpace,
599 const InstanceDecl& modifiedInstance)
600 {
601 throw CimException(CimException::NOT_SUPPORTED);
602 }
603
604 Array<ClassDecl> Repository::enumerateClasses(
605 const String& nameSpace,
606 const String& className,
607 Boolean deepInheritance,
608 Boolean localOnly,
609 Boolean includeQualifiers,
610 Boolean includeClassOrigin)
611 {
612 Array<String> classNames =
613 enumerateClassNames(nameSpace, className, deepInheritance);
614
615 Array<ClassDecl> result;
616
617 mike 1.1 for (Uint32 i = 0; i < classNames.getSize(); i++)
618 {
619 result.append(getClass(nameSpace, classNames[i], localOnly,
620 includeQualifiers, includeClassOrigin));
621 }
622
623 return result;
624 }
625
626 Array<String> Repository::enumerateClassNames(
627 const String& nameSpace,
628 const String& className,
629 Boolean deepInheritance)
630 {
631 // Build the path to the classes directory:
632
633 const char CLASSES[] = "/classes/";
634 String path;
635 _MakeNameSpacePath(_root, nameSpace, path);
636 path.append(CLASSES);
637
638 mike 1.1 if (!FileSystem::isDirectory(path))
639 throw CimException(CimException::INVALID_NAMESPACE);
640
641 if (deepInheritance)
642 {
643 if (className == String::EMPTY)
644 {
645 Array<String> classNames;
646 _AppendSubclassesDeep(path, String(), classNames);
647 return classNames;
648 }
649 else
650 {
651 Array<String> classNames;
652 _AppendSubclassesDeep(path, className, classNames);
653 return classNames;
654 }
655 }
656 else
657 {
658 if (className == String::EMPTY)
659 mike 1.1 {
660 Array<String> classNames;
661 _AppendClassNames(path, "*", "#", classNames);
662 return classNames;
663 }
664 else
665 {
666 Array<String> classNames;
667 _AppendClassNames(path, "*", className, classNames);
668 return classNames;
669 }
670 }
671
672 // Unreachable:
673 return Array<String>();
674 }
675
676 Array<InstanceDecl> Repository::enumerateInstances(
677 const String& nameSpace,
678 const String& className,
679 Boolean deepInheritance,
680 mike 1.1 Boolean localOnly,
681 Boolean includeQualifiers,
682 Boolean includeClassOrigin,
683 const Array<String>& propertyList)
684 {
685 throw CimException(CimException::NOT_SUPPORTED);
686 return Array<InstanceDecl>();
687 }
688
689 Array<String> Repository::enumerateInstanceNames(
690 const String& nameSpace,
691 const String& className)
692 {
693 throw CimException(CimException::NOT_SUPPORTED);
694 return Array<String>();
695 }
696
697 Array<InstanceDecl> Repository::execQuery(
698 const String& queryLanguage,
699 const String& query)
700 {
701 mike 1.1 throw CimException(CimException::NOT_SUPPORTED);
702 return Array<InstanceDecl>();
703 }
704
705 Array<InstanceDecl> Repository::associators(
706 const String& nameSpace,
707 const Reference& objectName,
708 const String& assocClass,
709 const String& resultClass,
710 const String& role,
711 const String& resultRole,
712 Boolean includeQualifiers,
713 Boolean includeClassOrigin,
714 const Array<String>& propertyList)
715 {
716 throw CimException(CimException::NOT_SUPPORTED);
717 return Array<InstanceDecl>();
718 }
719
720 Array<Reference> Repository::associatorNames(
721 const String& nameSpace,
722 mike 1.1 const Reference& objectName,
723 const String& assocClass,
724 const String& resultClass,
725 const String& role,
726 const String& resultRole)
727 {
728 throw CimException(CimException::NOT_SUPPORTED);
729 return Array<Reference>();
730 }
731
732 Array<InstanceDecl> Repository::references(
733 const String& nameSpace,
734 const Reference& objectName,
735 const String& resultClass,
736 const String& role,
737 Boolean includeQualifiers,
738 Boolean includeClassOrigin,
739 const Array<String>& propertyList)
740 {
741 throw CimException(CimException::NOT_SUPPORTED);
742 return Array<InstanceDecl>();
743 mike 1.1 }
744
745 Array<Reference> Repository::referenceNames(
746 const String& nameSpace,
747 const Reference& objectName,
748 const String& resultClass,
749 const String& role)
750 {
751 throw CimException(CimException::NOT_SUPPORTED);
752 return Array<Reference>();
753 }
754
755 Value Repository::getProperty(
756 const String& nameSpace,
757 const Reference& instanceName,
758 const String& propertyName)
759 {
760 throw CimException(CimException::NOT_SUPPORTED);
761 return Value();
762 }
763
764 mike 1.1 void Repository::setProperty(
765 const String& nameSpace,
766 const Reference& instanceName,
767 const String& propertyName,
768 const Value& newValue)
769 {
770 throw CimException(CimException::NOT_SUPPORTED);
771 }
772
773 QualifierDecl Repository::getQualifier(
774 const String& nameSpace,
775 const String& qualifierName)
776 {
777 // Form the path of the qualifier file:
778
779 String path;
780 _MakeQualfierPath(_root, nameSpace, qualifierName, path);
781
782 // If it does not exist:
783
784 if (!FileSystem::exists(path))
785 mike 1.1 throw CimException(CimException::NOT_FOUND);
786
787 // Load the qualifier:
788
789 QualifierDecl qualifierDecl;
790 _LoadObject(path, qualifierDecl);
791
792 return QualifierDecl(qualifierDecl);
793 }
794
795 void Repository::setQualifier(
796 const String& nameSpace,
797 const QualifierDecl& qualifierDecl)
798 {
799 // Form the path of the qualifier:
800
801 String path;
802 _MakeQualfierPath(_root, nameSpace, qualifierDecl.getName(), path);
803
804 // If the qualifier already exists, delete it:
805
806 mike 1.1 if (FileSystem::exists(path))
807 {
808 if (!FileSystem::removeFile(path))
809 throw FailedToRemoveDirectory(path);
810 }
811
812 // Write the qualifier to file:
813
814 _SaveObject(path, qualifierDecl);
815 }
816
817 void Repository::deleteQualifier(
818 const String& nameSpace,
819 const String& qualifierName)
820 {
821 String path;
822 _MakeQualfierPath(_root, nameSpace, qualifierName, path);
823
824 if (!FileSystem::exists(path))
825 throw CimException(CimException::NOT_FOUND);
826
827 mike 1.1 if (!FileSystem::removeFile(path))
828 throw FailedToRemoveFile(path);
829 }
830
831 Array<QualifierDecl> Repository::enumerateQualifiers(
832 const String& nameSpace)
833 {
834 // Build the path to the qualifiers directory:
835
836 const char QUALIFIERS[] = "/qualifiers/";
837 String path;
838 _MakeNameSpacePath(_root, nameSpace, path);
839 path.append(QUALIFIERS);
840
841 if (!FileSystem::isDirectory(path))
842 throw CimException(CimException::INVALID_NAMESPACE);
843
844 // Get the names of the qualifiers:
845
846 Array<String> qualifierNames;
847
848 mike 1.1 if (!FileSystem::getDirectoryContents(path, qualifierNames))
849 throw NoSuchDirectory(path);
850
851 // Load each qualifier into the result array:
852
853 Array<QualifierDecl> result;
854
855 for (Uint32 i = 0, n = qualifierNames.getSize(); i < n; i++)
856 {
857 QualifierDecl tmp = getQualifier(nameSpace, qualifierNames[i]);
858 result.append(tmp);
859 }
860
861 return result;
862 }
863
864 Value Repository::invokeMethod(
865 const String& nameSpace,
866 const Reference& instanceName,
867 const String& methodName,
868 const Array<Value>& inParameters,
869 mike 1.1 Array<Value>& outParameters)
870 {
871 throw CimException(CimException::NOT_SUPPORTED);
872 return Value();
873 }
874
875 ////////////////////////////////////////////////////////////////////////////////
876 //
877 // New methods
878 //
879 ////////////////////////////////////////////////////////////////////////////////
880
881 void Repository::createNameSpace(const String& nameSpace)
882 {
883 String path;
884 _MakeNameSpacePath(_root, nameSpace, path);
885
886 if (FileSystem::exists(path))
887 throw AlreadyExists(nameSpace);
888
889 if (!FileSystem::makeDirectory(path))
890 mike 1.1 throw CannotCreateDirectory(path);
891
892 // Create "./qualifiers" directory:
893
894 String qualifiersDir = path;
895 qualifiersDir.append("/qualifiers");
896
897 if (!FileSystem::makeDirectory(qualifiersDir))
898 throw CannotCreateDirectory(qualifiersDir);
899
900 // Create "./classes" directory:
901
902 String classesDir = path;
903 classesDir.append("/classes");
904
905 if (!FileSystem::makeDirectory(classesDir))
906 throw CannotCreateDirectory(classesDir);
907
908 // Create "./instances" directory:
909
910 String instancesDir = path;
911 mike 1.1 instancesDir.append("/instances");
912
913 if (!FileSystem::makeDirectory(instancesDir))
914 throw CannotCreateDirectory(instancesDir);
915 }
916
917 Array<String> Repository::enumerateNameSpaces() const
918 {
919 Array<String> result;
920
921 if (!FileSystem::getDirectoryContents(_root, result))
922 throw NoSuchDirectory(_root);
923
924 for (Uint32 i = 0, n = result.getSize(); i < n; i++)
925 {
926 const String& tmp = result[i];
927
928 for (Char16* p = (Char16*)tmp.getData(); *p; p++)
929 {
930 if (*p == '#')
931 *p = '/';
932 mike 1.1 }
933 }
934
935 return result;
936 }
937
938 PEGASUS_NAMESPACE_END
|