nis-util  1.0.D108
lib/path_join.cc
Go to the documentation of this file.
00001 //
00002 // nis-util - NIS Administration Utilities
00003 // Copyright (C) 2012 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or (at
00008 // your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program. If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <lib/ac/string.h>
00020 #include <list>
00021 
00022 #include <lib/path_join.h>
00023 
00024 typedef std::list<rcstring> string_list_t;
00025 
00026 
00027 static void
00028 split(const rcstring &text, string_list_t &parts)
00029 {
00030     if (text.empty())
00031     {
00032         parts.push_back(".");
00033         return;
00034     }
00035     const char *cp = text.c_str();
00036     for (;;)
00037     {
00038         const char *slash = strchr(cp, '/');
00039         if (!slash)
00040         {
00041             parts.push_back(cp);
00042             return;
00043         }
00044         parts.push_back(rcstring(cp, slash - cp));
00045         cp = slash + 1;
00046     }
00047 }
00048 
00049 
00050 static rcstring
00051 unsplit(string_list_t &parts)
00052 {
00053     // toss empty parts, except at the start
00054     {
00055         string_list_t fixed;
00056         for
00057         (
00058             string_list_t::const_iterator it = parts.begin();
00059             it != parts.end();
00060             ++it
00061         )
00062         {
00063             rcstring part = *it;
00064             if (!part.empty() || it == parts.begin())
00065                 fixed.push_back(part);
00066         }
00067         parts = fixed;
00068     }
00069 
00070     // toss redundant dots
00071     {
00072         string_list_t fixed;
00073         for
00074         (
00075             string_list_t::const_iterator it = parts.begin();
00076             it != parts.end();
00077             ++it
00078         )
00079         {
00080             rcstring part = *it;
00081             if (part != ".")
00082                 fixed.push_back(part);
00083         }
00084         parts = fixed;
00085     }
00086 
00087     if (parts.size() == 1 && parts.front().empty())
00088         return "/";
00089     if (parts.empty())
00090         return ".";
00091 
00092     // glue the parts together again
00093     rcstring result;
00094     for
00095     (
00096         string_list_t::const_iterator it = parts.begin();
00097         it != parts.end();
00098         ++it
00099     )
00100     {
00101         rcstring part = *it;
00102         if (it != parts.begin())
00103             result += "/";
00104         result += part;
00105     }
00106     return result;
00107 }
00108 
00109 
00110 rcstring
00111 path_join(const rcstring &lhs, const rcstring &rhs)
00112 {
00113     string_list_t parts;
00114     split(lhs, parts);
00115     split(rhs, parts);
00116     return unsplit(parts);
00117 }
00118 
00119 
00120 rcstring
00121 path_join(const rcstring &p1, const rcstring &p2, const rcstring &p3)
00122 {
00123     string_list_t parts;
00124     split(p1, parts);
00125     split(p2, parts);
00126     split(p3, parts);
00127     return unsplit(parts);
00128 }
00129 
00130 
00131 rcstring
00132 path_join(const rcstring &p1, const rcstring &p2, const rcstring &p3,
00133     const rcstring &p4)
00134 {
00135     string_list_t parts;
00136     split(p1, parts);
00137     split(p2, parts);
00138     split(p3, parts);
00139     split(p4, parts);
00140     return unsplit(parts);
00141 }
00142 
00143 
00144 // vim: set ts=8 sw=4 et :