2.2. doc.cc
#include "doc.hh"
#include <cstring>
#include <errno.h>
#include <netdb.h>
namespace libdoc {
A constructor for the ExceptionSystemError class. As well as the message
given explicitly it also stores the error code in errno.
ExceptionSystemError::ExceptionSystemError (const string &msg)
: Exception (msg)
{
err = errno;
}
Return an explanation of the error which caused the exception.
string
ExceptionSystemError::explain () const
{
string s = what();
if (err ≠ 0)
{
s += '\n';
s += strerror (err);
}
return s;
}
A constructor for the ExceptionGDBMError class. As well as the message
given explicitly it also stores the error code in gdbm_errno.
ExceptionGDBMError::ExceptionGDBMError (const string &msg)
: Exception (msg)
{
err = gdbm_errno;
}
Return an explanation of the error which caused the exception.
string
ExceptionGDBMError::explain () const
{
string s = what();
if (err ≠ 0)
{
s += '\n';
s += gdbm_strerror (err);
}
return s;
}
An equivalent of the Perl `chomp' function.
void
chomp (string &s)
{
if (not s.empty() and s[s.size() - 1] == '\n')
s.resize (s.size() - 1);
}
void
split (vector <string> &results, const string &s, char delim)
{
if (not s.empty())
{
string::size_type pos = 0, oldpos = 0;
while ((pos = s.find (delim, oldpos)) ≠ string::npos)
{
results.push_back (s.substr (oldpos, pos - oldpos));
oldpos = pos + 1;
}
results.push_back (s.substr (oldpos));
}
}
bool
check_extension (const string &s, const string &ext)
{
if (ext.size() > s.size())
return false;
return s.substr (s.size() - ext.size()) == ext;
}
void
perform_search (int s, const string &query, vector <SearchResult> &sr)
{
sock_send_char (s, 'c');
sock_send_str_nl (s, query);
string numstr;
sock_read_string (s, numstr);
unsigned int n = 0;
sscanf (numstr.c_str(), "%u", &n);
sr.clear();
sr.resize (n);
for (size_t i = 0; i < n; ++i)
{
sock_read_string (s, sr[i].document_filename);
sock_read_string (s, sr[i].document_title);
sock_read_string (s, sr[i].section_title);
sock_read_string (s, sr[i].section_ref);
sock_read_string (s, sr[i].format_icon);
sock_read_string (s, sr[i].format_name);
sock_read_string (s, sr[i].format_viewers);
}
}
Work out our host's IP address.
in_addr
find_hostip ()
{
char hostname[MAXHOSTNAMELEN + 1];
gethostname (hostname, sizeof (hostname));
struct hostent *hp = gethostbyname (hostname);
if (hp == 0)
throw ExceptionSystemError ("couldn't work out my hostname");
return *(struct in_addr *) hp->h_addr_list[0];
}
Copy a string into dynamically allocated memory (allocated with new).
char *
x_strdup (const char *s)
{
char *new_s = new char[strlen (s) + 1];
strcpy (new_s, s);
return new_s;
}
int
open_connection_to_docd (const char *hostname, int port)
{
int s = socket (PF_INET, SOCK_STREAM, 0);
if (s == -1)
throw ExceptionSystemError ("can't open socket to talk to docd");
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = inet_addr (hostname);
if (connect (s, (sockaddr *) &addr, sizeof (addr)))
throw ExceptionSystemError ("can't connect to socket to talk to docd");
return s;
}
void
sock_read_string (int sock, string &s)
{
int rc;
char c;
rc = recv (sock, &c, 1, 0);
while (rc == 1 && c ≠ '\n')
{
s += c;
rc = recv (sock, &c, 1, 0);
}
if (!s.empty() && s[s.size() - 1] == '\r')
s.resize (s.size() - 1);
}
void
sock_send_str (int s, const string &str)
{
const char *cs = str.c_str();
if (send (s, cs, str.size(), 0) ≠ int (str.size()))
throw Exception ("Error sending string to client");
}
void
sock_send_str_nl (int s, const string &str)
{
sock_send_str (s, str);
sock_send_char (s, '\n');
}
void
sock_send_char (int s, char c)
{
if (send (s, &c, 1, 0) ≠ 1)
throw Exception ("Error sending character to client");
}
}