00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00015 #include <ders/path.hpp>
00016
00017 namespace {
00018
00019 using namespace ders;
00020
00021 inline bool sepr(char ch)
00022 {
00023 return ch=='\\' || ch=='/';
00024 }
00025
00026 ch_rng fname(const char* beg, const char* end)
00027 {
00028 const char* ptr=beg;
00029 for ( ; ptr<end && !sepr(*ptr); ptr++)
00030 ;
00031
00032 return ch_rng(beg, ptr);
00033 }
00034
00035 ch_rng fsepr(const char* beg, const char* end)
00036 {
00037 const char* ptr=beg;
00038 for ( ; ptr<end && sepr(*ptr); ptr++)
00039 ;
00040
00041 return ch_rng(beg, ptr);
00042 }
00043
00044 }
00045
00046 namespace ders {
00047
00048 void parse_path(mem_pool&, const ch_rng& path, std::vector<path_elmt>& ret)
00049 {
00050 ret.clear();
00051
00052 const char* ptr=path.beg;
00053
00054 if (path.end-ptr>=5) {
00055 ch_rng spr=fsepr(ptr, path.end);
00056 if (spr.size()==2) {
00057 ch_rng srv=fname(spr.end, path.end);
00058 if (srv.size()>0) {
00059 ch_rng spr2=fsepr(srv.end, path.end);
00060 if (spr2.size()==1) {
00061 ch_rng shr=fname(spr2.end, path.end);
00062 if (shr.size()>0) {
00063 ret.push_back(path_elmt(path_elmt::share, ch_rng(ptr,
00064 shr.end)));
00065 ptr=fsepr(shr.end, path.end).end;
00066 }
00067 }
00068 }
00069 }
00070 }
00071
00072 if (path.end-ptr>=2) {
00073 ch_rng nm=fname(ptr, path.end);
00074 if (nm.size()>=2 && nm.beg[1]==':') {
00075 nm.end=nm.beg+2;
00076 ret.push_back(path_elmt(path_elmt::drive, nm));
00077 ptr=nm.end;
00078 }
00079 }
00080
00081 ch_rng spr=fsepr(ptr, path.end);
00082 if (spr.size()>0) {
00083 ret.push_back(path_elmt(path_elmt::root, ch_rng(ptr, ptr+1)));
00084 ptr=spr.end;
00085 }
00086
00087 for (;;) {
00088 ch_rng nm=fname(ptr, path.end);
00089 if (nm.size()<=0) break;
00090
00091 ret.push_back(path_elmt(path_elmt::name, nm));
00092 ptr=fsepr(nm.end, path.end).end;
00093 }
00094 }
00095
00096 sh_text make_path(mem_pool& mp, const path_elmt* beg, const path_elmt* end, char
00097 spr)
00098 {
00099 sh_text ret(nt(mp));
00100 ret->reserve(512);
00101
00102 for (const path_elmt* ptr=beg; ptr<end; ptr++) {
00103 switch (ptr->tp) {
00104 case path_elmt::drive: {
00105 assert(ptr==beg);
00106
00107 ret->append(ptr->nm);
00108 break;
00109 }
00110 case path_elmt::name: {
00111 if (ptr>beg && (ptr[-1].tp==path_elmt::name ||
00112 ptr[-1].tp==path_elmt::share))
00113 ret->append(spr);
00114
00115 ret->append(ptr->nm);
00116 break;
00117 }
00118 case path_elmt::root: {
00119 assert(ptr==beg || ptr==beg+1&&beg->tp==path_elmt::drive);
00120 assert(ptr->nm.size()==1);
00121
00122 ret->append(spr);
00123 break;
00124 }
00125 case path_elmt::share: {
00126 assert(ptr==beg);
00127
00128 ret->append(ptr->nm);
00129 break;
00130 }
00131 default: assert(false);
00132 }
00133 }
00134
00135 return ret;
00136 }
00137
00138 sh_text normalize_path(mem_pool& mp, const ch_rng& path)
00139 {
00140 std::vector<path_elmt> vpe;
00141 parse_path(mp, path, vpe);
00142 return make_path(mp, &*vpe.begin(), &*vpe.end());
00143 }
00144
00145 sh_text get_path(mem_pool& mp, const ch_rng& path)
00146 {
00147 std::vector<path_elmt> vpe;
00148 parse_path(mp, path, vpe);
00149
00150 const path_elmt *beg=&*vpe.begin(), *end=&*vpe.end();
00151 if (end>beg && (end-1)->tp==path_elmt::name) end--;
00152
00153 return make_path(mp, beg, end);
00154 }
00155
00156 sh_text get_name(mem_pool& mp, const ch_rng& path)
00157 {
00158 std::vector<path_elmt> vpe;
00159 parse_path(mp, path, vpe);
00160
00161 if (vpe.size() && vpe.back().tp==path_elmt::name) return nt(mp, vpe.back().nm);
00162 return nt(mp);
00163 }
00164
00165 }
00166