3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
15 #include "support/convert.h"
16 #include "support/lassert.h"
17 #include "support/lstrings.h"
23 using namespace lyx::support;
27 static int computeHash(docstring const & name,
28 docstring const & email)
30 string const full_author_string = to_utf8(name + email);
31 // Bernstein's hash function
32 unsigned int hash = 5381;
33 for (unsigned int i = 0; i < full_author_string.length(); ++i)
34 hash = ((hash << 5) + hash) + (unsigned int)(full_author_string[i]);
39 Author::Author(docstring const & name, docstring const & email)
40 : name_(name), email_(email), used_(true),
41 buffer_id_(computeHash(name, email))
45 Author::Author(int buffer_id)
46 : name_(convert<docstring>(buffer_id)), email_(docstring()), used_(false),
51 bool Author::valid() const
53 //this cannot be equal if the buffer_id was produced by the hash function.
54 return name_ != convert<docstring>(buffer_id_);
58 bool operator==(Author const & l, Author const & r)
60 return l.name() == r.name() && l.email() == r.email();
64 ostream & operator<<(ostream & os, Author const & a)
67 os << a.buffer_id_ << " \"" << to_utf8(a.name_) << "\"";
68 if (!a.email_.empty())
69 os << " " << to_utf8(a.email_);
75 istream & operator>>(istream & is, Author & a)
81 a.name_ = from_utf8(trim(token(s, '\"', 1)));
82 a.email_ = from_utf8(trim(token(s, '\"', 2)));
87 bool author_smaller(Author const & lhs, Author const & rhs)
89 return lhs.bufferId() < rhs.bufferId();
93 AuthorList::AuthorList()
97 int AuthorList::record(Author const & a)
99 bool const valid = a.valid();
100 // If we record an author which equals the current
101 // author, we copy the buffer_id, so that it will
102 // keep the same id in the file.
103 if (valid && !authors_.empty() && a == authors_[0])
104 authors_[0].setBufferId(a.bufferId());
106 Authors::const_iterator it = authors_.begin();
107 Authors::const_iterator const beg = it;
108 Authors::const_iterator const end = authors_.end();
109 for (; it != end; ++it) {
110 if (valid && *it == a)
112 if (it->bufferId() == a.bufferId()) {
115 // we need to handle the case of a valid author being registred
116 // after an invalid one. For instance, because "buffer-reload"
117 // does not clear the buffer's author list.
122 authors_.push_back(a);
123 return authors_.size() - 1;
127 void AuthorList::record(int id, Author const & a)
129 LBUFERR(unsigned(id) < authors_.size());
134 void AuthorList::recordCurrentAuthor(Author const & a)
136 // current author has id 0
141 Author const & AuthorList::get(int id) const
143 LASSERT(id < (int)authors_.size() , return authors_[0]);
148 AuthorList::Authors::const_iterator AuthorList::begin() const
150 return authors_.begin();
154 AuthorList::Authors::const_iterator AuthorList::end() const
156 return authors_.end();
160 void AuthorList::sort()
162 std::sort(authors_.begin(), authors_.end(), author_smaller);
166 ostream & operator<<(ostream & os, AuthorList const & a)
168 // Copy the authorlist, because we don't want to sort the original
169 AuthorList sorted = a;
172 AuthorList::Authors::const_iterator a_it = sorted.begin();
173 AuthorList::Authors::const_iterator const a_end = sorted.end();
175 for (; a_it != a_end; ++a_it) {
176 if (a_it->used() && a_it->valid())
177 os << "\\author " << *a_it << "\n";