* Made torrent::Piece part of the api.

* Made libtorrent locale agnostic.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@664 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2006-04-05 21:09:15 +00:00
parent 3fa08503bb
commit 8a8cfe5e3d
8 changed files with 263 additions and 94 deletions
+5 -2
View File
@@ -44,11 +44,12 @@ namespace rak {
class error_number {
public:
static const int e_access = EACCES;
static const int e_again = EAGAIN;
static const int e_intr = EINTR;
static const int e_deadlk = EDEADLK;
static const int e_connreset = ECONNRESET;
static const int e_connaborted = ECONNABORTED;
static const int e_deadlk = EDEADLK;
static const int e_intr = EINTR;
error_number() : m_errno(0) {}
error_number(int e) : m_errno(e) {}
@@ -66,6 +67,8 @@ public:
static error_number current() { return errno; }
static void clear_global() { errno = 0; }
bool operator == (const error_number& e) const { return m_errno == e.m_errno; }
private:
int m_errno;
};
-74
View File
@@ -72,77 +72,3 @@ private:
}
#endif
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2006, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_FILE_STAT_H
#define RAK_FILE_STAT_H
#include <string>
#include <inttypes.h>
#include <sys/stat.h>
namespace rak {
class file_stat {
public:
// Consider storing rak::error_number.
bool update(int fd) { return fstat(fd, &m_stat) == 0; }
bool update(const char* filename) { return stat(filename, &m_stat) == 0; }
bool update(const std::string& filename) { return update(filename.c_str()); }
bool is_regular() const { return S_ISREG(m_stat.st_mode); }
bool is_directory() const { return S_ISDIR(m_stat.st_mode); }
bool is_character() const { return S_ISCHR(m_stat.st_mode); }
bool is_block() const { return S_ISBLK(m_stat.st_mode); }
bool is_fifo() const { return S_ISFIFO(m_stat.st_mode); }
bool is_link() const { return S_ISLNK(m_stat.st_mode); }
bool is_socket() const { return S_ISSOCK(m_stat.st_mode); }
off_t size() const { return m_stat.st_size; }
time_t access_time() const { return m_stat.st_atime; }
time_t change_time() const { return m_stat.st_ctime; }
time_t modified_time() const { return m_stat.st_mtime; }
private:
struct stat m_stat;
};
}
#endif
+198
View File
@@ -0,0 +1,198 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2006, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_PARTIAL_QUEUE_H
#define RAK_PARTIAL_QUEUE_H
#include <cstring>
#include <stdexcept>
#include <inttypes.h>
namespace rak {
// First step, don't allow overflowing to the next layer. Only disable
// the above layers for now.
// We also include 0 in a single layer as some chunk may be available
// only through seeders.
class partial_queue {
public:
typedef uint8_t key_type;
typedef uint32_t mapped_type;
typedef uint16_t size_type;
typedef std::pair<size_type, size_type> size_pair_type;
static const size_type num_layers = 8;
partial_queue() : m_data(NULL), m_maxLayerSize(0) {}
~partial_queue() { disable(); }
bool is_full() const { return m_ceiling == 0; }
bool is_layer_full(size_type l) const { return m_layers[l].second >= m_maxLayerSize; }
bool is_enabled() const { return m_data != NULL; }
// Add check to see if we can add more. Also make it possible to
// check how full we are in the lower parts so the caller knows when
// he can stop searching.
//
// Though propably not needed, as we must continue til the first
// layer is full.
size_type max_size() const { return m_maxLayerSize * num_layers; }
size_type max_layer_size() const { return m_maxLayerSize; }
// Must be less that or equal to (max size_type) / num_layers.
void enable(size_type ls);
void disable();
void clear();
// Safe to call while pop'ing and it will not reuse pop'ed indices
// so it is guaranteed to reach max_size at some point. This will
// ensure that the user needs to refill with new data at regular
// intervals.
bool insert(key_type key, mapped_type value);
// Only call this when pop'ing as it moves the index.
bool prepare_pop();
mapped_type pop();
private:
partial_queue(const partial_queue&);
void operator = (const partial_queue&);
static size_type ceiling(size_type layer) { return (2 << layer) - 1; }
void find_non_empty();
mapped_type* m_data;
size_type m_maxLayerSize;
size_type m_index;
size_type m_ceiling;
size_pair_type m_layers[num_layers];
};
inline void
partial_queue::enable(size_type ls) {
if (ls == 0)
throw std::logic_error("partial_queue::enable(...) ls == 0.");
delete [] m_data;
m_data = new mapped_type[ls * num_layers];
m_maxLayerSize = ls;
}
inline void
partial_queue::disable() {
delete [] m_data;
m_data = NULL;
m_maxLayerSize = 0;
}
inline void
partial_queue::clear() {
if (m_data == NULL)
return;
m_index = 0;
m_ceiling = ceiling(num_layers - 1);
std::memset(m_layers, 0, num_layers * sizeof(size_pair_type));
}
inline bool
partial_queue::insert(key_type key, mapped_type value) {
if (key >= m_ceiling)
return false;
size_type idx = 0;
// Hmm... since we already check the 'm_ceiling' above, we only need
// to find the target layer. Could this be calculated directly?
while (key >= ceiling(idx))
++idx;
m_index = std::min(m_index, idx);
// Currently don't allow overflow.
if (is_layer_full(idx))
throw std::logic_error("partial_queue::insert(...) layer already full.");
//return false;
m_data[m_maxLayerSize * idx + m_layers[idx].second] = value;
m_layers[idx].second++;
if (is_layer_full(idx))
// Set the ceiling to 0 when layer 0 is full so no more values can
// be inserted.
m_ceiling = idx > 0 ? ceiling(idx - 1) : 0;
return true;
}
// is_empty() will iterate to the first layer with un-popped elements
// and return true, else return false when it reaches a overflowed or
// the last layer.
inline bool
partial_queue::prepare_pop() {
while (m_layers[m_index].first == m_layers[m_index].second) {
if (is_layer_full(m_index) || m_index + 1 == num_layers)
return false;
m_index++;
}
return true;
}
inline partial_queue::mapped_type
partial_queue::pop() {
if (m_index >= num_layers || m_layers[m_index].first >= m_layers[m_index].second)
throw std::logic_error("partial_queue::pop() bad state.");
return m_data[m_index * m_maxLayerSize + m_layers[m_index].first++];
}
}
#endif
+33 -2
View File
@@ -78,6 +78,37 @@ Sequence trim(const Sequence& seq) {
return trim_begin(trim_end(seq));
}
template <typename Sequence>
Sequence trim_begin_classic(const Sequence& seq) {
if (seq.empty() || !std::isspace(*seq.begin(), std::locale::classic()))
return seq;
typename Sequence::size_type pos = 0;
while (pos != seq.length() && std::isspace(seq[pos], std::locale::classic()))
pos++;
return seq.substr(pos, seq.length() - pos);
}
template <typename Sequence>
Sequence trim_end_classic(const Sequence& seq) {
if (seq.empty() || !std::isspace(*(--seq.end()), std::locale::classic()))
return seq;
typename Sequence::size_type pos = seq.size();
while (pos != 0 && std::isspace(seq[pos - 1], std::locale::classic()))
pos--;
return seq.substr(0, pos);
}
template <typename Sequence>
Sequence trim_classic(const Sequence& seq) {
return trim_begin_classic(trim_end_classic(seq));
}
// Consider rewritting such that m_seq is replaced by first/last.
template <typename Sequence>
class split_iterator_t {
@@ -159,8 +190,8 @@ template <typename InputIterator, typename OutputIterator>
OutputIterator
copy_escape_html(InputIterator first, InputIterator last, OutputIterator dest) {
while (first != last) {
if (std::isalpha(*first) ||
std::isdigit(*first) ||
if (std::isalpha(*first, std::locale::classic()) ||
std::isdigit(*first, std::locale::classic()) ||
*first == '-') {
*(dest++) = *first;
+4
View File
@@ -111,6 +111,10 @@ public:
void print(int x, int y, char* str,
A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { mvwprintw(m_window, y, x, str, a1, a2, a3, a4, a5, a6, a7, a8); }
void print_char(const chtype ch) { waddch(m_window, ch); }
void print_char(int x, int y, const chtype ch) { mvwaddch(m_window, y, x, ch); }
void set_attr(int x, int y, int n, int attr, int color) { mvwchgat(m_window, y, x, n, attr, color, NULL); }
// Initialize stdscr.
+3 -2
View File
@@ -62,7 +62,7 @@ struct client_info_equal {
};
ClientInfo::ClientInfo() {
m_containers[TYPE_AZUREUS].reserve(28);
m_containers[TYPE_AZUREUS].reserve(30);
insert(TYPE_AZUREUS, "AZ", "Azureus");
insert(TYPE_AZUREUS, "BC", "BitComet");
@@ -85,6 +85,7 @@ ClientInfo::ClientInfo() {
insert(TYPE_AZUREUS, "QT", "Qt 4 Torrent example");
insert(TYPE_AZUREUS, "SZ", "Shareaza");
insert(TYPE_AZUREUS, "RT", "Retriever");
insert(TYPE_AZUREUS, "CD", "Enhanced CTorrent");
m_containers[TYPE_COMPACT].reserve(10);
@@ -94,7 +95,7 @@ ClientInfo::ClientInfo() {
insert(TYPE_COMPACT, "U", "UPnP NAT Bit Torrent");
insert(TYPE_COMPACT, "O", "Osprey Permaseed");
m_containers[TYPE_MAINLINE].reserve(4);
m_containers[TYPE_MAINLINE].reserve(5);
insert(TYPE_MAINLINE, "M", "Mainline");
}
+18 -13
View File
@@ -39,6 +39,7 @@
#include <cmath>
#include <stdexcept>
#include <rak/string_manip.h>
#include <torrent/bitfield.h>
#include "core/download.h"
@@ -72,30 +73,34 @@ WindowDownloadChunksSeen::redraw() {
return;
}
char buffer[m_canvas->get_width()];
char* position;
char* end = buffer + m_canvas->get_width() - 2;
const uint8_t* chunk = seen;
const uint8_t* last = seen + m_download->download()->chunks_total();
const torrent::Bitfield* bitfield = m_download->download()->bitfield();
for (int y = 1; y < m_canvas->get_height() && chunk < last; ++y) {
position = buffer + std::max(snprintf(buffer, end - buffer, "%5d", (int)(chunk - seen)), 0);
m_canvas->print(0, y, "%5d ", (int)(chunk - seen));
while (chunk < last) {
chtype attr;
if (bitfield->get(chunk - seen))
attr = A_NORMAL;
// else if (foo->is_downloading(chunk - seen))
// attr = A_UNDERLINE;
else
attr = A_BOLD;
m_canvas->print_char(attr | rak::value_to_hexchar<0>(std::min<uint8_t>(*chunk, 0xF)));
chunk++;
if ((chunk - seen) % 10 == 0) {
if (end - position < 11)
if (m_canvas->get_x() + 12 > m_canvas->get_width())
break;
*position++ = ' ';
m_canvas->print_char(' ');
}
*position++ = rak::value_to_hexchar<0>(std::min<uint8_t>(*chunk, 0xF));
chunk++;
}
*position = 0;
m_canvas->print(0, y, "%s", buffer);
}
}
+2 -1
View File
@@ -39,6 +39,7 @@
#include <stdexcept>
#include <rak/socket_address.h>
#include <torrent/rate.h>
#include <torrent/piece.h>
#include "core/download.h"
#include "rak/algorithm.h"
@@ -120,7 +121,7 @@ WindowPeerList::redraw() {
x += 6;
if (p.incoming_queue_size())
m_canvas->print(x, y, "%i", p.incoming_index(0));
m_canvas->print(x, y, "%i", p.incoming_queue(0)->index());
x += 6;