lib/Stats.cc

Code
Comments
Other
Rev Date Author Line
84 13 Mar 06 jari 1 // $Id$
14 30 Dec 05 peter 2
84 13 Mar 06 jari 3 /*
84 13 Mar 06 jari 4   Copyright (C) 2005 Peter Johansson
978 12 Dec 09 peter 5   Copyright (C) 2006, 2007, 2008, 2009 Jari Häkkinen, Peter Johansson
1635 30 Mar 23 peter 6   Copyright (C) 2010, 2011, 2012, 2023 Peter Johansson
84 13 Mar 06 jari 7
687 04 Aug 08 peter 8   This file is part of svndigest, http://dev.thep.lu.se/svndigest
84 13 Mar 06 jari 9
149 12 Aug 06 jari 10   svndigest is free software; you can redistribute it and/or modify it
84 13 Mar 06 jari 11   under the terms of the GNU General Public License as published by
693 11 Sep 08 jari 12   the Free Software Foundation; either version 3 of the License, or
84 13 Mar 06 jari 13   (at your option) any later version.
84 13 Mar 06 jari 14
149 12 Aug 06 jari 15   svndigest is distributed in the hope that it will be useful, but
84 13 Mar 06 jari 16   WITHOUT ANY WARRANTY; without even the implied warranty of
149 12 Aug 06 jari 17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84 13 Mar 06 jari 18   General Public License for more details.
84 13 Mar 06 jari 19
84 13 Mar 06 jari 20   You should have received a copy of the GNU General Public License
693 11 Sep 08 jari 21   along with svndigest. If not, see <http://www.gnu.org/licenses/>.
84 13 Mar 06 jari 22 */
84 13 Mar 06 jari 23
1619 12 Mar 23 peter 24 #include <config.h>
1619 12 Mar 23 peter 25
14 30 Dec 05 peter 26 #include "Stats.h"
129 02 Aug 06 jari 27
929 02 Dec 09 jari 28 #include "Colors.h"
1007 03 Jan 10 peter 29 #include "Configuration.h"
465 24 Aug 07 peter 30 #include "Functor.h"
138 03 Aug 06 jari 31 #include "SVNblame.h"
129 02 Aug 06 jari 32 #include "SVNinfo.h"
14 30 Dec 05 peter 33 #include "utility.h"
14 30 Dec 05 peter 34
41 13 Jan 06 peter 35 #include <algorithm>
65 20 Jan 06 peter 36 #include <cassert>
63 19 Jan 06 peter 37 #include <cstdlib>
454 18 Aug 07 peter 38 #include <fstream>
1652 14 Jun 23 peter 39 #include <initializer_list>
1003 02 Jan 10 peter 40 #include <iostream>
454 18 Aug 07 peter 41 #include <iterator>
14 30 Dec 05 peter 42 #include <map>
14 30 Dec 05 peter 43 #include <numeric>
14 30 Dec 05 peter 44 #include <string>
138 03 Aug 06 jari 45 #include <sstream>
44 13 Jan 06 jari 46 #include <unistd.h>
23 02 Jan 06 peter 47 #include <utility>
14 30 Dec 05 peter 48 #include <vector>
14 30 Dec 05 peter 49
14 30 Dec 05 peter 50 namespace theplu{
149 12 Aug 06 jari 51 namespace svndigest{
14 30 Dec 05 peter 52
14 30 Dec 05 peter 53
80 10 Mar 06 jari 54   Stats::Stats(const std::string& path)
1478 29 May 12 peter 55     :  stats_(std::vector<Author2Vector>(LineTypeParser::total+1)),
1478 29 May 12 peter 56       ignore_rev_(0)
80 10 Mar 06 jari 57   {
80 10 Mar 06 jari 58     // Make sure latest revision is set properly
129 02 Aug 06 jari 59     SVNinfo svn_info(path);
129 02 Aug 06 jari 60     revision_=svn_info.rev();
129 02 Aug 06 jari 61     last_changed_rev_=svn_info.last_changed_rev();
639 31 May 08 peter 62     reset();
1378 14 Jun 11 peter 63     config_code_ = Configuration::instance().code(path);
80 10 Mar 06 jari 64   }
80 10 Mar 06 jari 65
80 10 Mar 06 jari 66
487 13 Oct 07 peter 67   Stats::~Stats(void)
487 13 Oct 07 peter 68   {
487 13 Oct 07 peter 69   }
14 30 Dec 05 peter 70
1478 29 May 12 peter 71
1194 03 Oct 10 peter 72   void Stats::add(const std::vector<std::map<std::string, SparseVector> >& data)
1194 03 Oct 10 peter 73   {
1194 03 Oct 10 peter 74     // loop over line types
1194 03 Oct 10 peter 75     for (size_t lt = 0; lt<data.size(); ++lt) {
1194 03 Oct 10 peter 76       std::map<std::string, SparseVector>::const_iterator iter=data[lt].begin();
1194 03 Oct 10 peter 77       std::map<std::string, SparseVector>::const_iterator last=data[lt].end();
1194 03 Oct 10 peter 78       // loop over users
1194 03 Oct 10 peter 79       for ( ; iter!=last; ++iter) {
1194 03 Oct 10 peter 80         add_author(iter->first);
1194 03 Oct 10 peter 81         SumVector tmpvec;
1194 03 Oct 10 peter 82         accumulate(iter->second, tmpvec);
1194 03 Oct 10 peter 83         stats_[lt][iter->first] += tmpvec;
1194 03 Oct 10 peter 84       }
1194 03 Oct 10 peter 85     }
1194 03 Oct 10 peter 86   }
14 30 Dec 05 peter 87
1194 03 Oct 10 peter 88
487 13 Oct 07 peter 89   void Stats::add_author(std::string name)
487 13 Oct 07 peter 90   {
487 13 Oct 07 peter 91     authors_.insert(name);
487 13 Oct 07 peter 92   }
14 30 Dec 05 peter 93
118 03 Jul 06 peter 94
1478 29 May 12 peter 95   void Stats::add_authors(std::set<std::string>::const_iterator first,
487 13 Oct 07 peter 96                           std::set<std::string>::const_iterator last)
487 13 Oct 07 peter 97   {
487 13 Oct 07 peter 98     authors_.insert(first, last);
487 13 Oct 07 peter 99   }
118 03 Jul 06 peter 100
118 03 Jul 06 peter 101
487 13 Oct 07 peter 102   const std::set<std::string>& Stats::authors(void) const
487 13 Oct 07 peter 103   {
487 13 Oct 07 peter 104     return authors_;
487 13 Oct 07 peter 105   }
202 10 Sep 06 peter 106
14 30 Dec 05 peter 107
537 27 Dec 07 peter 108   void Stats::calc_all(void)
537 27 Dec 07 peter 109   {
1611 12 Feb 23 peter 110     for (int lt : {LineTypeParser::code, LineTypeParser::comment_or_copy,
1611 12 Feb 23 peter 111                    LineTypeParser::other}) {
803 10 Jul 09 peter 112       stats_[lt]["all"].clear();
1199 04 Oct 10 peter 113       for (std::map<std::string, SumVector>::iterator i = stats_[lt].begin();
1199 04 Oct 10 peter 114            i!=stats_[lt].end(); ++i) {
1199 04 Oct 10 peter 115         stats_[lt]["all"] += i->second;
1199 04 Oct 10 peter 116       }
803 10 Jul 09 peter 117     }
1194 03 Oct 10 peter 118
1199 04 Oct 10 peter 119     total_stats()["all"] = comment_or_copy_stats()["all"];
1199 04 Oct 10 peter 120     total_stats()["all"] += code_stats()["all"];
1199 04 Oct 10 peter 121     total_stats()["all"] +=  other_stats()["all"];
537 27 Dec 07 peter 122   }
537 27 Dec 07 peter 123
537 27 Dec 07 peter 124
537 27 Dec 07 peter 125   void Stats::calc_total(void)
537 27 Dec 07 peter 126   {
537 27 Dec 07 peter 127     for (std::set<std::string>::const_iterator iter(authors().begin());
537 27 Dec 07 peter 128          iter!=authors().end(); ++iter) {
1200 04 Oct 10 peter 129       SumVector& total = total_stats()[*iter];
1200 04 Oct 10 peter 130       total = code_stats()[*iter];
1611 12 Feb 23 peter 131       total += comment_or_copy_stats()[*iter];
1200 04 Oct 10 peter 132       total += other_stats()[*iter];
537 27 Dec 07 peter 133     }
537 27 Dec 07 peter 134   }
537 27 Dec 07 peter 135
537 27 Dec 07 peter 136
589 12 Apr 08 jari 137   unsigned int Stats::code(const std::string& user) const
487 13 Oct 07 peter 138   {
552 08 Jan 08 peter 139     return get_back(code_stats(), user);
487 13 Oct 07 peter 140   }
60 16 Jan 06 peter 141
487 13 Oct 07 peter 142
589 12 Apr 08 jari 143   unsigned int Stats::comments(const std::string& user) const
487 13 Oct 07 peter 144   {
552 08 Jan 08 peter 145     return get_back(comment_or_copy_stats(), user);
487 13 Oct 07 peter 146   }
487 13 Oct 07 peter 147
487 13 Oct 07 peter 148
1478 29 May 12 peter 149   std::string Stats::config_code(void) const
1478 29 May 12 peter 150   {
1478 29 May 12 peter 151     if (ignore_rev_==0)
1478 29 May 12 peter 152       return config_code_;
1478 29 May 12 peter 153     std::stringstream result(config_code_);
1478 29 May 12 peter 154     result << "ir" << ignore_rev_;
1478 29 May 12 peter 155     return result.str();
1478 29 May 12 peter 156   }
1478 29 May 12 peter 157
1478 29 May 12 peter 158
589 12 Apr 08 jari 159   unsigned int Stats::empty(const std::string& user) const
487 13 Oct 07 peter 160   {
552 08 Jan 08 peter 161     return get_back(other_stats(), user);
487 13 Oct 07 peter 162   }
487 13 Oct 07 peter 163
487 13 Oct 07 peter 164
589 12 Apr 08 jari 165   unsigned int Stats::get_back(const Author2Vector& m, std::string user) const
487 13 Oct 07 peter 166   {
528 25 Dec 07 peter 167     A2VConstIter iter(m.find(std::string(user)));
1478 29 May 12 peter 168     if (iter==m.end() || iter->second.empty())
528 25 Dec 07 peter 169       return 0;
1495 27 Aug 12 peter 170     assert(iter->second.size());
528 25 Dec 07 peter 171     return iter->second.back();
487 13 Oct 07 peter 172   }
487 13 Oct 07 peter 173
487 13 Oct 07 peter 174
1478 29 May 12 peter 175   const SumVector& Stats::get_vector(const Author2Vector& m,
1194 03 Oct 10 peter 176                                      const std::string& user) const
487 13 Oct 07 peter 177   {
528 25 Dec 07 peter 178     A2VConstIter iter(m.find(std::string(user)));
1478 29 May 12 peter 179     if (iter==m.end())
487 13 Oct 07 peter 180       throw std::runtime_error(user+std::string(" not found i Stats"));
487 13 Oct 07 peter 181     return iter->second;
487 13 Oct 07 peter 182   }
487 13 Oct 07 peter 183
528 25 Dec 07 peter 184
1478 29 May 12 peter 185   void Stats::ignore_rev(svn_revnum_t rev)
1478 29 May 12 peter 186   {
1478 29 May 12 peter 187     ignore_rev_ = rev;
1478 29 May 12 peter 188   }
1478 29 May 12 peter 189
1478 29 May 12 peter 190
1478 29 May 12 peter 191   const svn_revnum_t& Stats::ignore_rev(void) const
1478 29 May 12 peter 192   {
1478 29 May 12 peter 193     return ignore_rev_;
1478 29 May 12 peter 194   }
1478 29 May 12 peter 195
1478 29 May 12 peter 196
529 25 Dec 07 peter 197   svn_revnum_t Stats::last_changed_rev(void) const
529 25 Dec 07 peter 198   {
529 25 Dec 07 peter 199     return last_changed_rev_;
529 25 Dec 07 peter 200   }
529 25 Dec 07 peter 201
529 25 Dec 07 peter 202
589 12 Apr 08 jari 203   unsigned int Stats::lines(const std::string& user) const
529 25 Dec 07 peter 204   {
552 08 Jan 08 peter 205     return get_back(total_stats(), user);
529 25 Dec 07 peter 206   }
529 25 Dec 07 peter 207
529 25 Dec 07 peter 208
529 25 Dec 07 peter 209   void Stats::load(std::istream& is, Author2Vector& m)
529 25 Dec 07 peter 210   {
529 25 Dec 07 peter 211     while (m.size() < authors().size()+1 && is.good()) {
529 25 Dec 07 peter 212       std::string name;
529 25 Dec 07 peter 213       std::getline(is, name);
1194 03 Oct 10 peter 214       SparseVector vec;
636 24 May 08 peter 215       std::string line;
636 24 May 08 peter 216       std::getline(is, line);
636 24 May 08 peter 217       std::stringstream ss(line);
636 24 May 08 peter 218       while (ss.good()) {
636 24 May 08 peter 219         svn_revnum_t rev=0;
636 24 May 08 peter 220         unsigned int count=0;
636 24 May 08 peter 221         ss >> rev;
636 24 May 08 peter 222         ss >> count;
649 08 Jun 08 peter 223         assert(rev<=revision_);
636 24 May 08 peter 224         if (!count)
636 24 May 08 peter 225           break;
1194 03 Oct 10 peter 226         vec.set(rev, count);
529 25 Dec 07 peter 227       }
1194 03 Oct 10 peter 228       SumVector& sumvec = m[name];
1194 03 Oct 10 peter 229       accumulate(vec, sumvec);
529 25 Dec 07 peter 230     }
529 25 Dec 07 peter 231   }
529 25 Dec 07 peter 232
529 25 Dec 07 peter 233
1124 07 Jul 10 peter 234   svn_revnum_t Stats::load_cache(std::istream& is, bool& latest_ver)
468 30 Aug 07 peter 235   {
552 08 Jan 08 peter 236     std::string str;
552 08 Jan 08 peter 237     getline(is, str);
1611 12 Feb 23 peter 238     if (str == "CACHE FILE VERSION 9") {
1611 12 Feb 23 peter 239       latest_ver = true;
1611 12 Feb 23 peter 240       return load_cache9(is);
1611 12 Feb 23 peter 241     }
1124 07 Jul 10 peter 242     if (str == "CACHE FILE VERSION 8") {
1611 12 Feb 23 peter 243       latest_ver = false;
1122 07 Jul 10 peter 244       return load_cache8(is);
1124 07 Jul 10 peter 245     }
1124 07 Jul 10 peter 246     latest_ver = false;
1122 07 Jul 10 peter 247     if (str == "CACHE FILE VERSION 7")
1122 07 Jul 10 peter 248       return load_cache7(is);
1122 07 Jul 10 peter 249
1122 07 Jul 10 peter 250     if (str == "CACHE FILE VERSION 6")
1122 07 Jul 10 peter 251       std::cout << "cache file is obsolete; "
1122 07 Jul 10 peter 252                 << "retrieving statistics from repository.\n";
1122 07 Jul 10 peter 253     return 0;
1122 07 Jul 10 peter 254   }
1122 07 Jul 10 peter 255
1122 07 Jul 10 peter 256
1611 12 Feb 23 peter 257   svn_revnum_t Stats::load_cache9(std::istream& is)
1611 12 Feb 23 peter 258   {
1611 12 Feb 23 peter 259     std::string line;
1611 12 Feb 23 peter 260     getline(is, line);
1611 12 Feb 23 peter 261     if (line!=config_code()) {
1611 12 Feb 23 peter 262       std::cout << "cache file is for different configuration.\n"
1611 12 Feb 23 peter 263                 << "config code: '" << config_code() << "'\n"
1611 12 Feb 23 peter 264                 << "config code in cache file: '" << line << "'\n"
1611 12 Feb 23 peter 265                 << "retrieving statistics from repository.\n";
1611 12 Feb 23 peter 266       return 0;
1611 12 Feb 23 peter 267     }
1611 12 Feb 23 peter 268     svn_revnum_t rev;
1611 12 Feb 23 peter 269     is >> rev;
1611 12 Feb 23 peter 270     reset();
1611 12 Feb 23 peter 271     size_t a_size=0;
1611 12 Feb 23 peter 272     is >> a_size;
1611 12 Feb 23 peter 273     std::string str;
1611 12 Feb 23 peter 274     while (authors().size()<a_size && is.good()){
1611 12 Feb 23 peter 275       getline(is, str);
1611 12 Feb 23 peter 276       if (str.size())
1611 12 Feb 23 peter 277         add_author(str);
1611 12 Feb 23 peter 278     }
1611 12 Feb 23 peter 279     getline(is, str);
1611 12 Feb 23 peter 280     if (str!=cache_check_str()) {
1611 12 Feb 23 peter 281       return 0;
1611 12 Feb 23 peter 282     }
1611 12 Feb 23 peter 283     for (int lt : {LineTypeParser::code, LineTypeParser::comment_or_copy,
1611 12 Feb 23 peter 284                    LineTypeParser::other, LineTypeParser::total}) {
1611 12 Feb 23 peter 285       assert(static_cast<size_t>(lt) < stats_.size());
1611 12 Feb 23 peter 286       load(is, stats_[lt]);
1611 12 Feb 23 peter 287       getline(is, str);
1611 12 Feb 23 peter 288       if (str!=cache_check_str()) {
1611 12 Feb 23 peter 289         return 0;
1611 12 Feb 23 peter 290       }
1611 12 Feb 23 peter 291     }
1611 12 Feb 23 peter 292     return rev;
1611 12 Feb 23 peter 293   }
1611 12 Feb 23 peter 294
1611 12 Feb 23 peter 295
1122 07 Jul 10 peter 296   svn_revnum_t Stats::load_cache8(std::istream& is)
1122 07 Jul 10 peter 297   {
1122 07 Jul 10 peter 298     std::string line;
1122 07 Jul 10 peter 299     getline(is, line);
1478 29 May 12 peter 300     if (line!=config_code()) {
1122 07 Jul 10 peter 301       std::cout << "cache file is for different configuration.\n"
1478 29 May 12 peter 302                 << "config code: '" << config_code() << "'\n"
1122 07 Jul 10 peter 303                 << "config code in cache file: '" << line << "'\n"
1122 07 Jul 10 peter 304                 << "retrieving statistics from repository.\n";
664 13 Jun 08 peter 305       return 0;
1003 02 Jan 10 peter 306     }
1122 07 Jul 10 peter 307     return load_cache7(is);
1122 07 Jul 10 peter 308   }
1122 07 Jul 10 peter 309
1122 07 Jul 10 peter 310
1122 07 Jul 10 peter 311   svn_revnum_t Stats::load_cache7(std::istream& is)
1122 07 Jul 10 peter 312   {
482 13 Oct 07 peter 313     svn_revnum_t rev;
482 13 Oct 07 peter 314     is >> rev;
529 25 Dec 07 peter 315     reset();
468 30 Aug 07 peter 316     size_t a_size=0;
468 30 Aug 07 peter 317     is >> a_size;
1122 07 Jul 10 peter 318     std::string str;
529 25 Dec 07 peter 319     while (authors().size()<a_size && is.good()){
468 30 Aug 07 peter 320       getline(is, str);
529 25 Dec 07 peter 321       if (str.size())
529 25 Dec 07 peter 322         add_author(str);
468 30 Aug 07 peter 323     }
529 25 Dec 07 peter 324     getline(is, str);
1611 12 Feb 23 peter 325     if (str!=cache_check_str7()) {
664 13 Jun 08 peter 326       return 0;
649 08 Jun 08 peter 327     }
552 08 Jan 08 peter 328     for (size_t i=0; i<stats_.size(); ++i){
552 08 Jan 08 peter 329       load(is, stats_[i]);
552 08 Jan 08 peter 330       getline(is, str);
1611 12 Feb 23 peter 331       if (str!=cache_check_str7()) {
664 13 Jun 08 peter 332         return 0;
649 08 Jun 08 peter 333       }
529 25 Dec 07 peter 334     }
664 13 Jun 08 peter 335     return rev;
468 30 Aug 07 peter 336   }
468 30 Aug 07 peter 337
468 30 Aug 07 peter 338
1478 29 May 12 peter 339   void Stats::map_add(A2VConstIter first1, A2VConstIter last1,
528 25 Dec 07 peter 340                       Author2Vector& map)
528 25 Dec 07 peter 341   {
528 25 Dec 07 peter 342     A2VIter first2(map.begin());
528 25 Dec 07 peter 343     Author2Vector::key_compare compare;
1478 29 May 12 peter 344     while ( first1 != last1) {
528 25 Dec 07 peter 345       // key of first1 less than key of first2
528 25 Dec 07 peter 346       if (first2==map.end() || compare(first1->first,first2->first)) {
528 25 Dec 07 peter 347         first2 = map.insert(first2, *first1);
528 25 Dec 07 peter 348         ++first1;
528 25 Dec 07 peter 349       }
528 25 Dec 07 peter 350       // key of first2 less than key of first1
528 25 Dec 07 peter 351       else if ( compare(first2->first, first1->first)) {
528 25 Dec 07 peter 352         ++first2;
528 25 Dec 07 peter 353       }
528 25 Dec 07 peter 354       // keys are equivalent
528 25 Dec 07 peter 355       else {
1203 05 Oct 10 peter 356         first2->second += first1->second;
528 25 Dec 07 peter 357         ++first1;
528 25 Dec 07 peter 358         ++first2;
528 25 Dec 07 peter 359       }
528 25 Dec 07 peter 360     }
528 25 Dec 07 peter 361   }
528 25 Dec 07 peter 362
528 25 Dec 07 peter 363
1194 03 Oct 10 peter 364   unsigned int Stats::max_element(const SumVector& vec) const
1003 02 Jan 10 peter 365   {
1478 29 May 12 peter 366     return std::max_element(vec.begin(), vec.end(),
1194 03 Oct 10 peter 367        pair_value_compare<const svn_revnum_t, unsigned int>())->second;
1003 02 Jan 10 peter 368   }
1003 02 Jan 10 peter 369
1003 02 Jan 10 peter 370
664 13 Jun 08 peter 371   void Stats::parse(const std::string& path, svn_revnum_t rev)
60 16 Jan 06 peter 372   {
664 13 Jun 08 peter 373     do_parse(path, rev);
537 27 Dec 07 peter 374     calc_total();
537 27 Dec 07 peter 375     calc_all();
1478 29 May 12 peter 376
639 31 May 08 peter 377     assert(total_stats().size());
639 31 May 08 peter 378     assert(code_stats().size());
639 31 May 08 peter 379     assert(comment_or_copy_stats().size());
639 31 May 08 peter 380     assert(other_stats().size());
60 16 Jan 06 peter 381   }
60 16 Jan 06 peter 382
1026 11 Jan 10 peter 383
454 18 Aug 07 peter 384   void Stats::print(std::ostream& os) const
454 18 Aug 07 peter 385   {
1611 12 Feb 23 peter 386     os << cache_check_str() << "\n";
1478 29 May 12 peter 387     os << config_code() << "\n";
529 25 Dec 07 peter 388     os << last_changed_rev() << " ";
636 24 May 08 peter 389     os << authors().size() << "\n";
482 13 Oct 07 peter 390
1478 29 May 12 peter 391     std::copy(authors().begin(), authors().end(),
454 18 Aug 07 peter 392               std::ostream_iterator<std::string>(os, "\n"));
552 08 Jan 08 peter 393     os << cache_check_str() << "\n";
1611 12 Feb 23 peter 394     for (int lt : {LineTypeParser::code, LineTypeParser::comment_or_copy,
1611 12 Feb 23 peter 395                    LineTypeParser::other, LineTypeParser::total}) {
1611 12 Feb 23 peter 396       assert(static_cast<size_t>(lt) < stats_.size());
1611 12 Feb 23 peter 397       print(os, stats_[lt]);
552 08 Jan 08 peter 398       os << cache_check_str() << "\n";
552 08 Jan 08 peter 399     }
454 18 Aug 07 peter 400   }
454 18 Aug 07 peter 401
454 18 Aug 07 peter 402
529 25 Dec 07 peter 403   void Stats::print(std::ostream& os, const Author2Vector& m) const
529 25 Dec 07 peter 404   {
529 25 Dec 07 peter 405     for (A2VConstIter i(m.begin()); i!=m.end(); ++i){
529 25 Dec 07 peter 406       os << i->first << "\n";
1208 07 Oct 10 peter 407       const SumVector& vec = i->second;
1208 07 Oct 10 peter 408       if (vec.size()) {
1208 07 Oct 10 peter 409         SumVector::const_iterator v = vec.begin();
1208 07 Oct 10 peter 410         if (v->second)
1208 07 Oct 10 peter 411           os << v->first << " " << v->second << " ";
1208 07 Oct 10 peter 412         ++v;
1208 07 Oct 10 peter 413         SumVector::const_iterator prev = vec.begin();
1208 07 Oct 10 peter 414         while (v != vec.end()) {
1208 07 Oct 10 peter 415           assert(vec[v->first - 1] == prev->second);
1208 07 Oct 10 peter 416           // FIXME: this if should not be needed if SumVector was
1208 07 Oct 10 peter 417           // truly sparse and collapsed when possible.
1208 07 Oct 10 peter 418           if (v->second != prev->second)
1208 07 Oct 10 peter 419             os << v->first << " " << v->second - prev->second << " ";
1208 07 Oct 10 peter 420           ++v;
1208 07 Oct 10 peter 421           ++prev;
636 24 May 08 peter 422         }
636 24 May 08 peter 423       }
636 24 May 08 peter 424       os << "\n";
529 25 Dec 07 peter 425     }
529 25 Dec 07 peter 426   }
529 25 Dec 07 peter 427
487 13 Oct 07 peter 428   void Stats::reset(void)
454 18 Aug 07 peter 429   {
552 08 Jan 08 peter 430     for (size_t i=0; i<stats_.size(); ++i){
552 08 Jan 08 peter 431       stats_[i].clear();
1194 03 Oct 10 peter 432       stats_[i]["all"].resize(revision()+1);
552 08 Jan 08 peter 433     }
529 25 Dec 07 peter 434     authors_.clear();
487 13 Oct 07 peter 435   }
487 13 Oct 07 peter 436
487 13 Oct 07 peter 437
1194 03 Oct 10 peter 438   void Stats::resize(svn_revnum_t rev)
1194 03 Oct 10 peter 439   {
1194 03 Oct 10 peter 440     // set size on vectors
1194 03 Oct 10 peter 441     for (size_t i=0; i<stats_.size(); ++i) {
1194 03 Oct 10 peter 442       for (A2VIter iter=stats_[i].begin(); iter!=stats_[i].end(); ++iter) {
1194 03 Oct 10 peter 443         iter->second.resize(rev);
1194 03 Oct 10 peter 444       }
1194 03 Oct 10 peter 445     }
1194 03 Oct 10 peter 446   }
1194 03 Oct 10 peter 447
1194 03 Oct 10 peter 448
1478 29 May 12 peter 449   svn_revnum_t Stats::revision(void) const
1478 29 May 12 peter 450   {
1478 29 May 12 peter 451     return revision_;
1194 03 Oct 10 peter 452   }
1194 03 Oct 10 peter 453
1194 03 Oct 10 peter 454
528 25 Dec 07 peter 455   Stats& Stats::operator+=(const Stats& rhs)
528 25 Dec 07 peter 456   {
528 25 Dec 07 peter 457     revision_ = std::max(revision_, rhs.revision_);
528 25 Dec 07 peter 458     last_changed_rev_ = std::max(last_changed_rev_, rhs.last_changed_rev_);
528 25 Dec 07 peter 459     add_authors(rhs.authors().begin(), rhs.authors().end());
552 08 Jan 08 peter 460     assert(stats_.size()==rhs.stats_.size());
552 08 Jan 08 peter 461     for (size_t i=0; i<stats_.size(); ++i)
552 08 Jan 08 peter 462       map_add(rhs.stats_[i].begin(), rhs.stats_[i].end(), stats_[i]);
1478 29 May 12 peter 463
528 25 Dec 07 peter 464     return *this;
528 25 Dec 07 peter 465   }
454 18 Aug 07 peter 466
1478 29 May 12 peter 467
1478 29 May 12 peter 468   size_t Stats::operator()(int linetype, std::string author,
642 31 May 08 peter 469                            svn_revnum_t rev) const
552 08 Jan 08 peter 470   {
1611 12 Feb 23 peter 471     assert(linetype == LineTypeParser::code ||
1611 12 Feb 23 peter 472            linetype == LineTypeParser::comment_or_copy ||
1611 12 Feb 23 peter 473            linetype == LineTypeParser::other ||
1611 12 Feb 23 peter 474            linetype == LineTypeParser::total);
1611 12 Feb 23 peter 475
552 08 Jan 08 peter 476     assert(linetype<=LineTypeParser::total);
636 24 May 08 peter 477     assert(static_cast<size_t>(linetype) < stats_.size());
642 31 May 08 peter 478     assert(rev>=0);
552 08 Jan 08 peter 479     A2VConstIter i = stats_[linetype].find(author);
637 24 May 08 peter 480     if (i==stats_[linetype].end()){
637 24 May 08 peter 481       std::stringstream msg;
1478 29 May 12 peter 482       msg << __FILE__ << ": author: " << author << " does not exist";
637 24 May 08 peter 483       throw std::runtime_error(msg.str());
637 24 May 08 peter 484     }
1194 03 Oct 10 peter 485     assert(rev <= revision());
1194 03 Oct 10 peter 486     //    assert(rev < static_cast<svn_revnum_t>(i->second.size()));
552 08 Jan 08 peter 487     return i->second[rev];
552 08 Jan 08 peter 488   }
454 18 Aug 07 peter 489
149 12 Aug 06 jari 490 }} // end of namespace svndigest and namespace theplu