PageRenderTime 30ms CodeModel.GetById 10ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/win32/shellext/Directory.cpp

https://bitbucket.org/tortoisehg/hgtk/
C++ | 240 lines | 181 code | 44 blank | 15 comment | 45 complexity | c04dff22443d36d0de4b4fdc7863397c MD5 | raw file
  1
  2// Copyright (C) 2009 Benjamin Pollack
  3// Copyright (C) 2009 Adrian Buehlmann
  4//
  5// This program is free software: you can redistribute it and/or modify
  6// it under the terms of the GNU General Public License as published by
  7// the Free Software Foundation, either version 2 of the License, or
  8// (at your option) any later version.
  9//
 10// This program is distributed in the hope that it will be useful,
 11// but WITHOUT ANY WARRANTY; without even the implied warranty of
 12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13// GNU General Public License for more details.
 14//
 15// You should have received a copy of the GNU General Public License
 16// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 17
 18#include <time.h>
 19
 20#include "stdafx.h"
 21
 22#include "Directory.h"
 23#include "Winstat.h"
 24
 25
 26Directory::Directory(
 27    Directory* p, const std::string& n, const std::string& basepath
 28):
 29    parent_(p), name_(n)
 30{
 31    if (n.empty())
 32        path_ = basepath;
 33    else if (basepath.empty())
 34        path_ = n;
 35    else
 36        path_ = basepath + '/' + n;
 37}
 38
 39
 40Directory::~Directory()
 41{
 42    for (DirsT::iterator i = subdirs_.begin(); i != subdirs_.end(); ++i)
 43    {
 44        delete *i;
 45    }
 46}
 47
 48
 49int splitbase(const std::string& n, std::string& base, std::string& rest)
 50{
 51    if (n.empty())
 52        return 0;
 53
 54    size_t x = n.find_first_of ('/');
 55    if (x == std::string::npos)
 56    {
 57        base.clear();
 58        rest = n;
 59        return 1;
 60    }
 61
 62    if (x == 0 || x == n.length()-1)
 63        return 0;
 64
 65    base = n.substr(0, x);
 66    rest = n.substr(x+1);
 67
 68    return 1;
 69}
 70
 71
 72int Directory::add(const std::string& n_in, Direntry& e)
 73{
 74    std::string base;
 75    std::string rest;
 76    
 77    std::string n = n_in;
 78    Directory* cur = this;
 79    
 80    for (;;)
 81    {
 82
 83        if (!splitbase(n, base, rest)) {
 84            TDEBUG_TRACE("Directory(" << path() << ")::add(" << n_in 
 85                << "): splitbase returned 0");
 86            return 0;
 87        }
 88
 89        if (base.empty())
 90        {
 91            e.name = n;
 92            cur->files_.push_back(e);
 93            return 1;
 94        }
 95
 96        Directory* d = 0;
 97        for (DirsT::iterator i = cur->subdirs_.begin(); 
 98                i != cur->subdirs_.end(); ++i)
 99        {
100            if ((*i)->name_ == base) {
101                d = *i;
102                break;
103            }
104        }
105
106        if (!d)
107        {
108            d = new Directory(cur, base, cur->path());
109            cur->subdirs_.push_back(d);
110        }
111
112        n = rest;
113        cur = d;
114    }
115}
116
117
118const Direntry* Directory::get(const std::string& n_in) const
119{
120    std::string base;
121    std::string rest;
122
123    std::string n = n_in;
124    const Directory* cur = this;
125
126    for (;;)
127    {
128        loopstart:
129
130        if (!splitbase(n, base, rest))
131        {
132            TDEBUG_TRACE("Directory(" << path() << ")::get(" 
133                << n_in << "): splitbase returned 0");
134            return 0;
135        }
136
137        if (base.empty())
138        {
139            for (FilesT::const_iterator i = cur->files_.begin();
140                    i != cur->files_.end(); ++i)
141            {
142                if (i->name == n)
143                    return &(*i);
144            }
145            return 0;
146        }
147
148        for (DirsT::const_iterator i = cur->subdirs_.begin();
149                i != cur->subdirs_.end(); ++i)
150        {
151            if ((*i)->name_ == base)
152            {
153                cur = *i;
154                n = rest;
155                goto loopstart;
156            }
157        }
158
159        return 0;
160    }
161}
162
163
164Directory* Directory::getdir(const std::string& n_in)
165{
166    std::string base;
167    std::string rest;
168
169    std::string n = n_in;
170    const Directory* cur = this;
171
172    for (;;)
173    {
174        loopstart:
175
176        if (!splitbase(n, base, rest))
177        {
178            TDEBUG_TRACE("Directory(" << path() << ")::getdir("
179                << n_in << "): splitbase returned 0");
180            return 0;
181        }
182
183        const bool leaf = base.empty();
184        const std::string& searchstr = (leaf ? n : base);
185
186        for (DirsT::const_iterator i = cur->subdirs_.begin();
187                i != cur->subdirs_.end(); ++i)
188        {
189            if ((*i)->name_ == searchstr)
190            {
191                if (leaf)
192                    return *i;
193                cur = *i;
194                n = rest;
195                goto loopstart;
196            }
197        }
198
199        return 0;
200    }
201}
202
203
204void Directory::print() const
205{
206    for (DirsT::const_iterator i = subdirs_.begin(); i != subdirs_.end(); ++i)
207    {
208        const Directory* d = *i;
209        if (!d)
210        {
211            TDEBUG_TRACE("Directory(" << path() << ")::print: error: d is 0");
212            return;
213        }
214        d->print();
215    }
216
217    std::string base = path();
218
219    time_t t;
220    std::string s;
221    char* ctime_res = 0;
222
223    for (FilesT::const_iterator i = files_.begin(); i != files_.end(); ++i)
224    {
225        std::string p = (!base.empty() ? base + "/" + i->name : i->name);
226        t = i->mtime;
227        ctime_res = ctime(&t);
228        if (ctime_res) {
229            s = ctime_res;
230            s.resize(s.size() - 1); // strip ending '\n'
231        }
232        else {
233            s = "unset";
234        }
235        printf(
236            "%c %6o %10u %-24s %s\n", 
237            i->state, i->mode, i->size, s.c_str(), p.c_str()
238        );
239    }
240}