1 //
2 // Path.cpp
3 //
4 // Library: Foundation
5 // Package: Filesystem
6 // Module: Path
7 //
8 // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9 // and Contributors.
10 //
11 // SPDX-License-Identifier: BSL-1.0
12 //
13
14
15 #include "Poco/Path.h"
16 #include "Poco/File.h"
17 #include "Poco/Exception.h"
18 #include "Poco/StringTokenizer.h"
19 #if defined(_WIN32)
20 #include "Poco/UnicodeConverter.h"
21 #include "Poco/Buffer.h"
22 #endif
23 #include <algorithm>
24
25
26 #if defined(POCO_OS_FAMILY_UNIX)
27 #include "Path_UNIX.cpp"
28 #elif defined(POCO_OS_FAMILY_WINDOWS)
29 #if defined(_WIN32_WCE)
30 #include "Path_WINCE.cpp"
31 #else
32 #include "Path_WIN32U.cpp"
33 #endif
34 #endif
35
36
37 namespace Poco {
38
39
Path()40 Path::Path(): _absolute(false)
41 {
42 }
43
44
Path(bool absolute)45 Path::Path(bool absolute): _absolute(absolute)
46 {
47 }
48
49
Path(const std::string & path)50 Path::Path(const std::string& path)
51 {
52 assign(path);
53 }
54
55
Path(const std::string & path,Style style)56 Path::Path(const std::string& path, Style style)
57 {
58 assign(path, style);
59 }
60
61
Path(const char * path)62 Path::Path(const char* path)
63 {
64 poco_check_ptr(path);
65 assign(path);
66 }
67
68
Path(const char * path,Style style)69 Path::Path(const char* path, Style style)
70 {
71 poco_check_ptr(path);
72 assign(path, style);
73 }
74
75
Path(const Path & path)76 Path::Path(const Path& path):
77 _node(path._node),
78 _device(path._device),
79 _name(path._name),
80 _version(path._version),
81 _dirs(path._dirs),
82 _absolute(path._absolute)
83 {
84 }
85
86
Path(Path && path)87 Path::Path(Path&& path) noexcept:
88 _node(std::move(path._node)),
89 _device(std::move(path._device)),
90 _name(std::move(path._name)),
91 _version(std::move(path._version)),
92 _dirs(std::move(path._dirs)),
93 _absolute(std::move(path._absolute))
94 {
95 }
96
97
Path(const Path & parent,const std::string & fileName)98 Path::Path(const Path& parent, const std::string& fileName):
99 _node(parent._node),
100 _device(parent._device),
101 _name(parent._name),
102 _version(parent._version),
103 _dirs(parent._dirs),
104 _absolute(parent._absolute)
105 {
106 makeDirectory();
107 _name = fileName;
108 }
109
110
Path(const Path & parent,const char * fileName)111 Path::Path(const Path& parent, const char* fileName):
112 _node(parent._node),
113 _device(parent._device),
114 _name(parent._name),
115 _version(parent._version),
116 _dirs(parent._dirs),
117 _absolute(parent._absolute)
118 {
119 makeDirectory();
120 _name = fileName;
121 }
122
123
Path(const Path & parent,const Path & relative)124 Path::Path(const Path& parent, const Path& relative):
125 _node(parent._node),
126 _device(parent._device),
127 _name(parent._name),
128 _version(parent._version),
129 _dirs(parent._dirs),
130 _absolute(parent._absolute)
131 {
132 resolve(relative);
133 }
134
135
~Path()136 Path::~Path()
137 {
138 }
139
140
operator =(const Path & path)141 Path& Path::operator = (const Path& path)
142 {
143 return assign(path);
144 }
145
146
operator =(Path && path)147 Path& Path::operator = (Path&& path) noexcept
148 {
149 _node = std::move(path._node);
150 _device = std::move(path._device);
151 _name = std::move(path._name);
152 _version = std::move(path._version);
153 _dirs = std::move(path._dirs);
154 _absolute = std::move(path._absolute);
155 return *this;
156 }
157
158
operator =(const std::string & path)159 Path& Path::operator = (const std::string& path)
160 {
161 return assign(path);
162 }
163
164
operator =(const char * path)165 Path& Path::operator = (const char* path)
166 {
167 poco_check_ptr(path);
168 return assign(path);
169 }
170
171
swap(Path & path)172 void Path::swap(Path& path)
173 {
174 std::swap(_node, path._node);
175 std::swap(_device, path._device);
176 std::swap(_name, path._name);
177 std::swap(_version, path._version);
178 std::swap(_dirs, path._dirs);
179 std::swap(_absolute, path._absolute);
180 }
181
182
assign(const Path & path)183 Path& Path::assign(const Path& path)
184 {
185 if (&path != this)
186 {
187 _node = path._node;
188 _device = path._device;
189 _name = path._name;
190 _version = path._version;
191 _dirs = path._dirs;
192 _absolute = path._absolute;
193 }
194 return *this;
195 }
196
197
assign(const std::string & path)198 Path& Path::assign(const std::string& path)
199 {
200 #if defined(POCO_OS_FAMILY_WINDOWS)
201 parseWindows(path);
202 #else
203 parseUnix(path);
204 #endif
205 return *this;
206 }
207
208
assign(const std::string & path,Style style)209 Path& Path::assign(const std::string& path, Style style)
210 {
211 switch (style)
212 {
213 case PATH_UNIX:
214 parseUnix(path);
215 break;
216 case PATH_WINDOWS:
217 parseWindows(path);
218 break;
219 case PATH_VMS:
220 parseVMS(path);
221 break;
222 case PATH_NATIVE:
223 assign(path);
224 break;
225 case PATH_GUESS:
226 parseGuess(path);
227 break;
228 default:
229 poco_bugcheck();
230 }
231 return *this;
232 }
233
234
assign(const char * path)235 Path& Path::assign(const char* path)
236 {
237 return assign(std::string(path));
238 }
239
240
toString() const241 std::string Path::toString() const
242 {
243 #if defined(POCO_OS_FAMILY_WINDOWS)
244 return buildWindows();
245 #else
246 return buildUnix();
247 #endif
248 }
249
250
toString(Style style) const251 std::string Path::toString(Style style) const
252 {
253 switch (style)
254 {
255 case PATH_UNIX:
256 return buildUnix();
257 case PATH_WINDOWS:
258 return buildWindows();
259 case PATH_VMS:
260 return buildVMS();
261 case PATH_NATIVE:
262 case PATH_GUESS:
263 return toString();
264 default:
265 poco_bugcheck();
266 }
267 return std::string();
268 }
269
270
tryParse(const std::string & path)271 bool Path::tryParse(const std::string& path)
272 {
273 try
274 {
275 Path p;
276 p.parse(path);
277 assign(p);
278 return true;
279 }
280 catch (...)
281 {
282 return false;
283 }
284 }
285
286
tryParse(const std::string & path,Style style)287 bool Path::tryParse(const std::string& path, Style style)
288 {
289 try
290 {
291 Path p;
292 p.parse(path, style);
293 assign(p);
294 return true;
295 }
296 catch (...)
297 {
298 return false;
299 }
300 }
301
302
parseDirectory(const std::string & path)303 Path& Path::parseDirectory(const std::string& path)
304 {
305 assign(path);
306 return makeDirectory();
307 }
308
309
parseDirectory(const std::string & path,Style style)310 Path& Path::parseDirectory(const std::string& path, Style style)
311 {
312 assign(path, style);
313 return makeDirectory();
314 }
315
316
makeDirectory()317 Path& Path::makeDirectory()
318 {
319 pushDirectory(_name);
320 _name.clear();
321 _version.clear();
322 return *this;
323 }
324
325
makeFile()326 Path& Path::makeFile()
327 {
328 if (!_dirs.empty() && _name.empty())
329 {
330 _name = _dirs.back();
331 _dirs.pop_back();
332 }
333 return *this;
334 }
335
336
makeAbsolute()337 Path& Path::makeAbsolute()
338 {
339 return makeAbsolute(current());
340 }
341
342
makeAbsolute(const Path & base)343 Path& Path::makeAbsolute(const Path& base)
344 {
345 if (!_absolute)
346 {
347 Path tmp = base;
348 tmp.makeDirectory();
349 for (const auto& d: _dirs)
350 {
351 tmp.pushDirectory(d);
352 }
353 _node = tmp._node;
354 _device = tmp._device;
355 _dirs = tmp._dirs;
356 _absolute = base._absolute;
357 }
358 return *this;
359 }
360
361
absolute() const362 Path Path::absolute() const
363 {
364 Path result(*this);
365 if (!result._absolute)
366 {
367 result.makeAbsolute();
368 }
369 return result;
370 }
371
372
absolute(const Path & base) const373 Path Path::absolute(const Path& base) const
374 {
375 Path result(*this);
376 if (!result._absolute)
377 {
378 result.makeAbsolute(base);
379 }
380 return result;
381 }
382
383
parent() const384 Path Path::parent() const
385 {
386 Path p(*this);
387 return p.makeParent();
388 }
389
390
makeParent()391 Path& Path::makeParent()
392 {
393 if (_name.empty())
394 {
395 if (_dirs.empty())
396 {
397 if (!_absolute)
398 _dirs.push_back("..");
399 }
400 else
401 {
402 if (_dirs.back() == "..")
403 _dirs.push_back("..");
404 else
405 _dirs.pop_back();
406 }
407 }
408 else
409 {
410 _name.clear();
411 _version.clear();
412 }
413 return *this;
414 }
415
416
append(const Path & path)417 Path& Path::append(const Path& path)
418 {
419 makeDirectory();
420 _dirs.insert(_dirs.end(), path._dirs.begin(), path._dirs.end());
421 _name = path._name;
422 _version = path._version;
423 return *this;
424 }
425
426
resolve(const Path & path)427 Path& Path::resolve(const Path& path)
428 {
429 if (path.isAbsolute())
430 {
431 assign(path);
432 }
433 else
434 {
435 for (int i = 0; i < path.depth(); ++i)
436 pushDirectory(path[i]);
437 _name = path._name;
438 }
439 return *this;
440 }
441
442
setNode(const std::string & node)443 Path& Path::setNode(const std::string& node)
444 {
445 _node = node;
446 _absolute = _absolute || !node.empty();
447 return *this;
448 }
449
450
setDevice(const std::string & device)451 Path& Path::setDevice(const std::string& device)
452 {
453 _device = device;
454 _absolute = _absolute || !device.empty();
455 return *this;
456 }
457
458
directory(int n) const459 const std::string& Path::directory(int n) const
460 {
461 poco_assert (0 <= n && n <= _dirs.size());
462
463 if (n < _dirs.size())
464 return _dirs[n];
465 else
466 return _name;
467 }
468
469
operator [](int n) const470 const std::string& Path::operator [] (int n) const
471 {
472 poco_assert (0 <= n && n <= _dirs.size());
473
474 if (n < _dirs.size())
475 return _dirs[n];
476 else
477 return _name;
478 }
479
480
pushDirectory(const std::string & dir)481 Path& Path::pushDirectory(const std::string& dir)
482 {
483 if (!dir.empty() && dir != ".")
484 {
485 if (dir == "..")
486 {
487 if (!_dirs.empty() && _dirs.back() != "..")
488 _dirs.pop_back();
489 else if (!_absolute)
490 _dirs.push_back(dir);
491 }
492 else _dirs.push_back(dir);
493 }
494 return *this;
495 }
496
497
popDirectory()498 Path& Path::popDirectory()
499 {
500 poco_assert (!_dirs.empty());
501
502 _dirs.pop_back();
503 return *this;
504 }
505
506
popFrontDirectory()507 Path& Path::popFrontDirectory()
508 {
509 poco_assert (!_dirs.empty());
510
511 StringVec::iterator it = _dirs.begin();
512 _dirs.erase(it);
513 return *this;
514 }
515
516
setFileName(const std::string & name)517 Path& Path::setFileName(const std::string& name)
518 {
519 _name = name;
520 return *this;
521 }
522
523
setBaseName(const std::string & name)524 Path& Path::setBaseName(const std::string& name)
525 {
526 std::string ext = getExtension();
527 _name = name;
528 if (!ext.empty())
529 {
530 _name.append(".");
531 _name.append(ext);
532 }
533 return *this;
534 }
535
536
getBaseName() const537 std::string Path::getBaseName() const
538 {
539 std::string::size_type pos = _name.rfind('.');
540 if (pos != std::string::npos)
541 return _name.substr(0, pos);
542 else
543 return _name;
544 }
545
546
setExtension(const std::string & extension)547 Path& Path::setExtension(const std::string& extension)
548 {
549 _name = getBaseName();
550 if (!extension.empty())
551 {
552 _name.append(".");
553 _name.append(extension);
554 }
555 return *this;
556 }
557
558
getExtension() const559 std::string Path::getExtension() const
560 {
561 std::string::size_type pos = _name.rfind('.');
562 if (pos != std::string::npos)
563 return _name.substr(pos + 1);
564 else
565 return std::string();
566 }
567
568
clear()569 Path& Path::clear()
570 {
571 _node.clear();
572 _device.clear();
573 _name.clear();
574 _dirs.clear();
575 _version.clear();
576 _absolute = false;
577 return *this;
578 }
579
580
current()581 std::string Path::current()
582 {
583 return PathImpl::currentImpl();
584 }
585
586
home()587 std::string Path::home()
588 {
589 return PathImpl::homeImpl();
590 }
591
592
configHome()593 std::string Path::configHome()
594 {
595 #if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
596 return PathImpl::configHomeImpl();
597 #else
598 return PathImpl::homeImpl();
599 #endif
600 }
601
602
dataHome()603 std::string Path::dataHome()
604 {
605 #if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
606 return PathImpl::dataHomeImpl();
607 #else
608 return PathImpl::homeImpl();
609 #endif
610 }
611
612
tempHome()613 std::string Path::tempHome()
614 {
615 #if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
616 return PathImpl::tempHomeImpl();
617 #else
618 return PathImpl::tempImpl();
619 #endif
620 }
621
622
cacheHome()623 std::string Path::cacheHome()
624 {
625 #if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
626 return PathImpl::cacheHomeImpl();
627 #else
628 return PathImpl::homeImpl();
629 #endif
630 }
631
632
temp()633 std::string Path::temp()
634 {
635 return PathImpl::tempImpl();
636 }
637
638
config()639 std::string Path::config()
640 {
641 #if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
642 return PathImpl::configImpl();
643 #else
644 return PathImpl::currentImpl();
645 #endif
646 }
647
648
null()649 std::string Path::null()
650 {
651 return PathImpl::nullImpl();
652 }
653
654
expand(const std::string & path)655 std::string Path::expand(const std::string& path)
656 {
657 return PathImpl::expandImpl(path);
658 }
659
660
listRoots(std::vector<std::string> & roots)661 void Path::listRoots(std::vector<std::string>& roots)
662 {
663 PathImpl::listRootsImpl(roots);
664 }
665
666
find(StringVec::const_iterator it,StringVec::const_iterator end,const std::string & name,Path & path)667 bool Path::find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path)
668 {
669 while (it != end)
670 {
671 #if defined(WIN32)
672 std::string cleanPath(*it);
673 if (cleanPath.size() > 1 && cleanPath[0] == '"' && cleanPath[cleanPath.size() - 1] == '"')
674 {
675 cleanPath = cleanPath.substr(1, cleanPath.size() - 2);
676 }
677 Path p(cleanPath);
678 #else
679 Path p(*it);
680 #endif
681 p.makeDirectory();
682 p.resolve(Path(name));
683 File f(p);
684 if (f.exists())
685 {
686 path = p;
687 return true;
688 }
689 ++it;
690 }
691 return false;
692 }
693
694
find(const std::string & pathList,const std::string & name,Path & path)695 bool Path::find(const std::string& pathList, const std::string& name, Path& path)
696 {
697 StringTokenizer st(pathList, std::string(1, pathSeparator()), StringTokenizer::TOK_IGNORE_EMPTY + StringTokenizer::TOK_TRIM);
698 return find(st.begin(), st.end(), name, path);
699 }
700
701
parseUnix(const std::string & path)702 void Path::parseUnix(const std::string& path)
703 {
704 clear();
705
706 std::string::const_iterator it = path.begin();
707 std::string::const_iterator end = path.end();
708
709 if (it != end)
710 {
711 if (*it == '/')
712 {
713 _absolute = true; ++it;
714 }
715 else if (*it == '~')
716 {
717 ++it;
718 if (it == end || *it == '/')
719 {
720 Path cwd(home());
721 _dirs = cwd._dirs;
722 _absolute = true;
723 }
724 else --it;
725 }
726
727 while (it != end)
728 {
729 std::string name;
730 while (it != end && *it != '/') name += *it++;
731 if (it != end)
732 {
733 if (_dirs.empty())
734 {
735 if (!name.empty() && *(name.rbegin()) == ':')
736 {
737 _absolute = true;
738 _device.assign(name, 0, name.length() - 1);
739 }
740 else
741 {
742 pushDirectory(name);
743 }
744 }
745 else pushDirectory(name);
746 }
747 else _name = name;
748 if (it != end) ++it;
749 }
750 }
751 }
752
753
parseWindows(const std::string & path)754 void Path::parseWindows(const std::string& path)
755 {
756 clear();
757
758 std::string::const_iterator it = path.begin();
759 std::string::const_iterator end = path.end();
760
761 if (it != end)
762 {
763 if (*it == '\\' || *it == '/') { _absolute = true; ++it; }
764 if (_absolute && it != end && (*it == '\\' || *it == '/')) // UNC
765 {
766 ++it;
767 while (it != end && *it != '\\' && *it != '/') _node += *it++;
768 if (it != end) ++it;
769 }
770 else if (it != end)
771 {
772 char d = *it++;
773 if (it != end && *it == ':') // drive letter
774 {
775 if (_absolute || !((d >= 'a' && d <= 'z') || (d >= 'A' && d <= 'Z'))) throw PathSyntaxException(path);
776 _absolute = true;
777 _device += d;
778 ++it;
779 if (it == end || (*it != '\\' && *it != '/')) throw PathSyntaxException(path);
780 ++it;
781 }
782 else --it;
783 }
784 while (it != end)
785 {
786 std::string name;
787 while (it != end && *it != '\\' && *it != '/') name += *it++;
788 if (it != end)
789 pushDirectory(name);
790 else
791 _name = name;
792 if (it != end) ++it;
793 }
794 }
795 if (!_node.empty() && _dirs.empty() && !_name.empty())
796 makeDirectory();
797 }
798
799
parseVMS(const std::string & path)800 void Path::parseVMS(const std::string& path)
801 {
802 clear();
803
804 std::string::const_iterator it = path.begin();
805 std::string::const_iterator end = path.end();
806
807 if (it != end)
808 {
809 std::string name;
810 while (it != end && *it != ':' && *it != '[' && *it != ';') name += *it++;
811 if (it != end)
812 {
813 if (*it == ':')
814 {
815 ++it;
816 if (it != end && *it == ':')
817 {
818 _node = name;
819 ++it;
820 }
821 else _device = name;
822 _absolute = true;
823 name.clear();
824 }
825 if (it != end)
826 {
827 if (_device.empty() && *it != '[')
828 {
829 while (it != end && *it != ':' && *it != ';') name += *it++;
830 if (it != end)
831 {
832 if (*it == ':')
833 {
834 _device = name;
835 _absolute = true;
836 name.clear();
837 ++it;
838 }
839 }
840 }
841 }
842 if (name.empty())
843 {
844 if (it != end && *it == '[')
845 {
846 ++it;
847 if (it != end)
848 {
849 _absolute = true;
850 if (*it == '.')
851 { _absolute = false; ++it; }
852 else if (*it == ']' || *it == '-')
853 _absolute = false;
854 while (it != end && *it != ']')
855 {
856 name.clear();
857 if (*it == '-')
858 name = "-";
859 else
860 while (it != end && *it != '.' && *it != ']') name += *it++;
861 if (!name.empty())
862 {
863 if (name == "-")
864 {
865 if (_dirs.empty() || _dirs.back() == "..")
866 _dirs.push_back("..");
867 else
868 _dirs.pop_back();
869 }
870 else _dirs.push_back(name);
871 }
872 if (it != end && *it != ']') ++it;
873 }
874 if (it == end) throw PathSyntaxException(path);
875 ++it;
876 if (it != end && *it == '[')
877 {
878 if (!_absolute) throw PathSyntaxException(path);
879 ++it;
880 if (it != end && *it == '.') throw PathSyntaxException(path);
881 int d = int(_dirs.size());
882 while (it != end && *it != ']')
883 {
884 name.clear();
885 if (*it == '-')
886 name = "-";
887 else
888 while (it != end && *it != '.' && *it != ']') name += *it++;
889 if (!name.empty())
890 {
891 if (name == "-")
892 {
893 if (_dirs.size() > d)
894 _dirs.pop_back();
895 }
896 else _dirs.push_back(name);
897 }
898 if (it != end && *it != ']') ++it;
899 }
900 if (it == end) throw PathSyntaxException(path);
901 ++it;
902 }
903 }
904 _name.clear();
905 }
906 while (it != end && *it != ';') _name += *it++;
907 }
908 else _name = name;
909 if (it != end && *it == ';')
910 {
911 ++it;
912 while (it != end) _version += *it++;
913 }
914 }
915 else _name = name;
916 }
917 }
918
919
parseGuess(const std::string & path)920 void Path::parseGuess(const std::string& path)
921 {
922 bool hasBackslash = false;
923 bool hasSlash = false;
924 bool hasOpenBracket = false;
925 bool hasClosBracket = false;
926 bool isWindows = path.length() > 2 && path[1] == ':' && (path[2] == '/' || path[2] == '\\');
927 std::string::const_iterator end = path.end();
928 std::string::const_iterator semiIt = end;
929 if (!isWindows)
930 {
931 for (std::string::const_iterator it = path.begin(); it != end; ++it)
932 {
933 switch (*it)
934 {
935 case '\\': hasBackslash = true; break;
936 case '/': hasSlash = true; break;
937 case '[': hasOpenBracket = true;
938 case ']': hasClosBracket = hasOpenBracket;
939 case ';': semiIt = it; break;
940 }
941 }
942 }
943 if (hasBackslash || isWindows)
944 {
945 parseWindows(path);
946 }
947 else if (hasSlash)
948 {
949 parseUnix(path);
950 }
951 else
952 {
953 bool isVMS = hasClosBracket;
954 if (!isVMS && semiIt != end)
955 {
956 isVMS = true;
957 ++semiIt;
958 while (semiIt != end)
959 {
960 if (*semiIt < '0' || *semiIt > '9')
961 {
962 isVMS = false; break;
963 }
964 ++semiIt;
965 }
966 }
967 if (isVMS)
968 parseVMS(path);
969 else
970 parseUnix(path);
971 }
972 }
973
974
buildUnix() const975 std::string Path::buildUnix() const
976 {
977 std::string result;
978 if (!_device.empty())
979 {
980 result.append("/");
981 result.append(_device);
982 result.append(":/");
983 }
984 else if (_absolute)
985 {
986 result.append("/");
987 }
988 for (const auto& d: _dirs)
989 {
990 result.append(d);
991 result.append("/");
992 }
993 result.append(_name);
994 return result;
995 }
996
997
buildWindows() const998 std::string Path::buildWindows() const
999 {
1000 std::string result;
1001 if (!_node.empty())
1002 {
1003 result.append("\\\\");
1004 result.append(_node);
1005 result.append("\\");
1006 }
1007 else if (!_device.empty())
1008 {
1009 result.append(_device);
1010 result.append(":\\");
1011 }
1012 else if (_absolute)
1013 {
1014 result.append("\\");
1015 }
1016 for (const auto& d: _dirs)
1017 {
1018 result.append(d);
1019 result.append("\\");
1020 }
1021 result.append(_name);
1022 return result;
1023 }
1024
1025
buildVMS() const1026 std::string Path::buildVMS() const
1027 {
1028 std::string result;
1029 if (!_node.empty())
1030 {
1031 result.append(_node);
1032 result.append("::");
1033 }
1034 if (!_device.empty())
1035 {
1036 result.append(_device);
1037 result.append(":");
1038 }
1039 if (!_dirs.empty())
1040 {
1041 result.append("[");
1042 if (!_absolute && _dirs[0] != "..")
1043 result.append(".");
1044 for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it)
1045 {
1046 if (it != _dirs.begin() && *it != "..")
1047 result.append(".");
1048 if (*it == "..")
1049 result.append("-");
1050 else
1051 result.append(*it);
1052 }
1053 result.append("]");
1054 }
1055 result.append(_name);
1056 if (!_version.empty())
1057 {
1058 result.append(";");
1059 result.append(_version);
1060 }
1061 return result;
1062 }
1063
1064
transcode(const std::string & path)1065 std::string Path::transcode(const std::string& path)
1066 {
1067 #if defined(_WIN32)
1068 std::wstring uniPath;
1069 UnicodeConverter::toUTF16(path, uniPath);
1070 DWORD len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, uniPath.c_str(), static_cast<int>(uniPath.length()), NULL, 0, NULL, NULL);
1071 if (len > 0)
1072 {
1073 Buffer<char> buffer(len);
1074 DWORD rc = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, uniPath.c_str(), static_cast<int>(uniPath.length()), buffer.begin(), static_cast<int>(buffer.size()), NULL, NULL);
1075 if (rc)
1076 {
1077 return std::string(buffer.begin(), buffer.size());
1078 }
1079 }
1080 #endif
1081 return path;
1082 }
1083
1084
1085 } // namespace Poco
1086