Commit 754da0ef authored by Davis King's avatar Davis King
Browse files

Properly organized the svn repository. Finally.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402199
parent 49388714
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CPP_PRETTY_PRINTEr_
#define DLIB_CPP_PRETTY_PRINTEr_
#include "cpp_pretty_printer/cpp_pretty_printer_kernel_1.h"
#include "cpp_pretty_printer/cpp_pretty_printer_kernel_2.h"
#include "cpp_tokenizer.h"
#include "stack.h"
namespace dlib
{
class cpp_pretty_printer
{
cpp_pretty_printer() {}
typedef stack<unsigned long>::kernel_1a stack;
typedef cpp_tokenizer::kernel_1a tok;
public:
//----------- kernels ---------------
// kernel_1a
typedef cpp_pretty_printer_kernel_1<stack,tok>
kernel_1a;
// kernel_2a
typedef cpp_pretty_printer_kernel_2<stack,tok>
kernel_2a;
};
}
#endif // DLIB_CPP_PRETTY_PRINTEr_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CPP_PRETTY_PRINTER_KERNEl_1_
#define DLIB_CPP_PRETTY_PRINTER_KERNEl_1_
#include <string>
#include <iostream>
#include <sstream>
#include "cpp_pretty_printer_kernel_abstract.h"
#include "../algs.h"
namespace dlib
{
template <
typename stack,
typename tok
>
class cpp_pretty_printer_kernel_1
{
/*!
REQUIREMENTS ON stack
must be an implementation of stack/stack_kernel_abstract.h and
stack::type == unsigned long
REQUIREMENTS ON tok
must be an implementation of tokenizer/tokenizer_kernel_abstract.h
INFO
This implementation applies a color scheme, turns include directives
such as #include "file.h" into links to file.h.html, and it also puts
HTML anchor points on function and class declarations.
!*/
public:
cpp_pretty_printer_kernel_1 (
);
virtual ~cpp_pretty_printer_kernel_1 (
);
void print (
std::istream& in,
std::ostream& out,
const std::string& title
) const;
void print_and_number (
std::istream& in,
std::ostream& out,
const std::string& title
) const;
private:
const std::string htmlify (
const std::string& str
) const;
/*!
ensures
- str == str but with any '<' replaced with '&lt;', any '>' replaced
with '&gt;', and any '&' replaced with '&amp;'
!*/
// data members
mutable tok t;
void number (
std::istream& in,
std::ostream& out
) const;
/*!
ensures
- prints in to out and adds line numbers
!*/
// restricted functions
cpp_pretty_printer_kernel_1(const cpp_pretty_printer_kernel_1&); // copy constructor
cpp_pretty_printer_kernel_1& operator=(const cpp_pretty_printer_kernel_1&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
cpp_pretty_printer_kernel_1<stack,tok>::
cpp_pretty_printer_kernel_1 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
cpp_pretty_printer_kernel_1<stack,tok>::
~cpp_pretty_printer_kernel_1 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
void cpp_pretty_printer_kernel_1<stack,tok>::
print (
std::istream& in,
std::ostream& out,
const std::string& title
) const
{
using namespace std;
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_1::print");
t.set_stream(in);
out << "<html><!-- "
<< "Created using the cpp_pretty_printer from the dlib C++ library. See http://dclib.sf.net for updates."
<< " --><head><title>" << title << "</title></head><body bgcolor='white'><pre>\n";
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_1::print");
unsigned long scope = 0; // counts the number of new scopes we have entered
// since we were at a scope where functions can be declared
bool recently_seen_class_keyword = false;
// true if we have seen the keywords class, struct, or enum and
// we have not seen any identifiers or { characters
bool recently_seen_include = false;
// true if we have seen the #include keyword and have not seen double
// quoted text or >
bool recently_seen_new_scope = false;
// true if we have seen the keywords class, namespace, or struct and
// we have not seen the characters {, ), or ; since then
bool recently_seen_paren = false;
// true if we have seen a ) and we have only seen white_space or comments since
bool in_initialization_list = false;
// true if we have seen a ) followed by any white space or comments and then
// followed by a : (in scope==0 with recently_seen_preprocessor==false) and we
// have not yet seen the character { or ;
bool recently_seen_preprocessor = false;
// true if we have seen the #pragma or #if or #define or #elif keywords and have
// not seen an end of line.
bool recently_seen_extern = false;
// true if we have seen the extern keyword and haven't seen a ; or { yet.
unsigned long paren_count = 0;
// this is the number of ( we have seen minus the number of ) we have
// seen.
int type;
stack scopes; // a stack to hold old scopes
string token, temp;
t.get_token(type,token);
while (type != tok::END_OF_FILE)
{
switch (type)
{
case tok::IDENTIFIER: // ------------------------------------------
if ( recently_seen_class_keyword)
{
// this might be a class name so check if there is a
// ; or identifier or * or & coming up.
type = t.peek_type();
temp.clear();
if (type == tok::WHITE_SPACE)
{
t.get_token(type,temp);
if (temp.find_first_of("\n\r") != string::npos)
recently_seen_preprocessor = false;
}
if (t.peek_token() != ";" && t.peek_type() != tok::IDENTIFIER &&
t.peek_token() != "*" && t.peek_token() != "&")
{
// this is the name of a class or struct in a class or
// struct declaration.
out << "<b><a name='" << token << "'></a>" << token << "</b>" << temp;
}
else
{
out << token << temp;
}
}
else if ( !in_initialization_list &&
!recently_seen_preprocessor )
{
// this might be a function name so check if there is a
// ( coming up.
type = t.peek_type();
temp.clear();
if (type == tok::WHITE_SPACE)
{
t.get_token(type,temp);
type = t.peek_type();
}
if (type == tok::OTHER && t.peek_token() == "(")
{
if (scope == 0 && paren_count == 0)
{
// this is a function definition or prototype
out << "<b><a name='" << token << "'></a>" << token << "</b>" << temp;
}
else
{
// this is a function call (probably)
out << "<font color='#BB00BB'>" << token << "</font>" << temp;
}
}
else
{
out << token << temp;
}
}
else
{
out << token;
}
recently_seen_class_keyword = false;
recently_seen_paren = false;
break;
case tok::KEYWORD: // ---------------------------------------------
if (scope == 0 && token == "operator")
{
// Doing this is sort of weird since operator is really a keyword
// but I just like how this looks.
out << "<b><a name='" << token << "'></a>" << token << "</b>";
}
// this isn't a keyword if it is something like #include <new>
else if ( token == "true" || token == "false")
{
// color 'true' and 'false' the same way we color numbers
out << "<font color='#979000'>" << token << "</font>";
}
else if (!recently_seen_include)
{
// This is a normal keyword
if (token == "char" || token == "unsigned" || token == "signed" ||
token == "short" || token == "int" || token == "long" ||
token == "float" || token == "double" || token == "bool" ||
token == "void" || token == "size_t" || token == "wchar_t")
{
out << "<font color='#0000FF'><u>" << token << "</u></font>";
}
else
{
out << "<font color='#0000FF'>" << token << "</font>";
}
}
else
{
out << token;
}
if (token == "#include")
{
recently_seen_include = true;
}
else if (token == "class")
{
recently_seen_new_scope = true;
recently_seen_class_keyword = true;
}
else if (token == "namespace")
{
recently_seen_new_scope = true;
}
else if (token == "enum")
{
recently_seen_class_keyword = true;
}
else if (token == "struct")
{
recently_seen_new_scope = true;
recently_seen_class_keyword = true;
}
else if (token == "#pragma" || token == "#if" || token == "#define" || token == "#elif")
{
recently_seen_preprocessor = true;
}
else if (token == "extern")
{
recently_seen_extern = true;
}
recently_seen_paren = false;
break;
case tok::COMMENT: // ---------------------------------------------
{
// if this is a special anchor comment
if (token.size() > 4 &&
token[0] == '/' &&
token[1] == '*' &&
token[2] == '!' &&
token[3] == 'A' &&
token[4] == ' '
)
{
temp = token;
istringstream sin(token);
sin >> temp;
sin >> temp;
sin.get();
// if there was still more stuff in the token then we are ok.
if (sin)
out << "<a name='" << temp << "'/>";
}
out << "<font color='#009900'>" << htmlify(token) << "</font>";
}
break;
case tok::SINGLE_QUOTED_TEXT: // ----------------------------------
{
out << "<font color='#FF0000'>" << htmlify(token) << "</font>";
recently_seen_paren = false;
}
break;
case tok::NUMBER: // -----------------------------------------
{
out << "<font color='#979000'>" << token << "</font>";
recently_seen_include = false;
}
break;
case tok::WHITE_SPACE: // -----------------------------------------
{
out << token;
if (token.find_first_of("\n\r") != string::npos)
recently_seen_preprocessor = false;
}
break;
case tok::DOUBLE_QUOTED_TEXT: // ----------------------------------
{
if (recently_seen_include)
{
// this is the name of an included file
recently_seen_include = false;
out << "<a style='text-decoration:none' href='" << htmlify(token) << ".html'>" << htmlify(token) << "</a>";
}
else
{
// this is just a normal quoted string
out << "<font color='#CC0000'>" << htmlify(token) << "</font>";
}
recently_seen_paren = false;
}
break;
case tok::OTHER: // -----------------------------------------------
switch (token[0])
{
case '{':
out << "<b>{</b>";
// if we are entering a new scope
if (recently_seen_new_scope || recently_seen_extern)
{
recently_seen_new_scope = false;
scopes.push(scope);
scope = 0;
}
else
{
++scope;
}
in_initialization_list = false;
recently_seen_paren = false;
recently_seen_class_keyword = false;
recently_seen_extern = false;
break;
case '}':
out << "<b>}</b>";
if (scope > 0)
{
--scope;
}
else if (scopes.size())
{
scopes.pop(scope);
}
recently_seen_paren = false;
break;
case ':':
out << ':';
if (recently_seen_paren && scope == 0 &&
recently_seen_preprocessor == false)
{
in_initialization_list = true;
}
recently_seen_paren = false;
break;
case ';':
out << ';';
recently_seen_new_scope = false;
recently_seen_paren = false;
recently_seen_extern = false;
break;
case ')':
out << "<font face='Lucida Console'>)</font>";
recently_seen_paren = true;
recently_seen_new_scope = false;
--paren_count;
break;
case '(':
out << "<font face='Lucida Console'>(</font>";
recently_seen_paren = false;
++paren_count;
break;
case '>':
recently_seen_include = false;
out << "<font color='#5555FF'>&gt;</font>";
recently_seen_paren = false;
break;
case '<':
out << "<font color='#5555FF'>&lt;</font>";
recently_seen_paren = false;
break;
case '&':
out << "<font color='#5555FF'>&amp;</font>";
recently_seen_paren = false;
break;
case '=':
case '+':
case '-':
case '/':
case '*':
case '!':
case '|':
case '%':
out << "<font color='#5555FF'>" << token << "</font>";
recently_seen_paren = false;
break;
default:
out << token;
recently_seen_paren = false;
break;
} // switch (token[0])
break;
} // switch (type)
t.get_token(type,token);
} // while (type != tok::END_OF_FILE)
out << "\n</pre></body></html>";
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_1::print");
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
void cpp_pretty_printer_kernel_1<stack,tok>::
print_and_number (
std::istream& in,
std::ostream& out,
const std::string& title
) const
{
using namespace std;
ostringstream sout;
print(in,sout,title);
istringstream sin(sout.str());
number(sin,out);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
void cpp_pretty_printer_kernel_1<stack,tok>::
number (
std::istream& in,
std::ostream& out
) const
{
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_1::number");
std::string space = "&nbsp;&nbsp;&nbsp;";
std::ios::int_type ch;
unsigned long count = 1;
while ((ch=in.get()) != EOF)
{
if (ch != '\n')
{
out << (char)ch;
}
else
{
out << "\n<font color='555555'>" << count << " </font> " + space;
++count;
if (count == 10)
space = "&nbsp;&nbsp;";
if (count == 100)
space = "&nbsp;";
if (count == 1000)
space = "";
}
}
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_1::number");
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
const std::string cpp_pretty_printer_kernel_1<stack,tok>::
htmlify (
const std::string& str
) const
{
std::string::size_type i;
std::string temp;
for (i = 0; i < str.size(); ++i)
{
if (str[i] == '<')
temp += "&lt;";
else if (str[i] == '>')
temp += "&gt;";
else if (str[i] == '&')
temp += "&amp;";
else
temp += str[i];
}
return temp;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CPP_PRETTY_PRINTER_KERNEl_1_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CPP_PRETTY_PRINTER_KERNEl_2_
#define DLIB_CPP_PRETTY_PRINTER_KERNEl_2_
#include <string>
#include <iostream>
#include <sstream>
#include "cpp_pretty_printer_kernel_abstract.h"
#include "../algs.h"
namespace dlib
{
template <
typename stack,
typename tok
>
class cpp_pretty_printer_kernel_2
{
/*!
REQUIREMENTS ON stack
must be an implementation of stack/stack_kernel_abstract.h and
stack::type == unsigned long
REQUIREMENTS ON tok
must be an implementation of tokenizer/tokenizer_kernel_abstract.h
INFO
This implementation applies a black and white color scheme suitable
for printing on a black and white printer. It also places the document
title prominently at the top of the pretty printed source file.
!*/
public:
cpp_pretty_printer_kernel_2 (
);
virtual ~cpp_pretty_printer_kernel_2 (
);
void print (
std::istream& in,
std::ostream& out,
const std::string& title
) const;
void print_and_number (
std::istream& in,
std::ostream& out,
const std::string& title
) const;
private:
// data members
mutable tok t;
const std::string htmlify (
const std::string& str
) const;
/*!
ensures
- str == str but with any '<' replaced with '&lt;', any '>' replaced
with '&gt;', and any '&' replaced with '&amp;'
!*/
void number (
std::istream& in,
std::ostream& out
) const;
/*!
ensures
- prints in to out and adds line numbers
!*/
// restricted functions
cpp_pretty_printer_kernel_2(const cpp_pretty_printer_kernel_2&); // copy constructor
cpp_pretty_printer_kernel_2& operator=(const cpp_pretty_printer_kernel_2&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
cpp_pretty_printer_kernel_2<stack,tok>::
cpp_pretty_printer_kernel_2 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
cpp_pretty_printer_kernel_2<stack,tok>::
~cpp_pretty_printer_kernel_2 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
void cpp_pretty_printer_kernel_2<stack,tok>::
print (
std::istream& in,
std::ostream& out,
const std::string& title
) const
{
using namespace std;
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_2::print");
t.set_stream(in);
out << "<html><!-- "
<< "Created using the cpp_pretty_printer from the dlib C++ library. See http://dclib.sf.net for updates."
<< " --><head>"
<< "<title>" << title << "</title></head><body bgcolor='white'>"
<< "<h1><center>" << title << "</center></h1><pre>\n"
<< "<font style='font-size:9pt' face='Lucida Console'>\n";
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_2::print");
unsigned long scope = 0; // counts the number of new scopes we have entered
// since we were at a scope where functions can be declared
bool recently_seen_class_keyword = false;
// true if we have seen the keywords class or struct and
// we have not seen any identifiers or { characters
bool recently_seen_include = false;
// true if we have seen the #include keyword and have not seen double
// quoted text or >
bool recently_seen_new_scope = false;
// true if we have seen the keywords class, namespace, or struct and
// we have not seen the characters {, ), or ; since then
bool recently_seen_paren = false;
// true if we have seen a ) and we have only seen white_space or comments since
bool in_initialization_list = false;
// true if we have seen a ) followed by any white space or comments and then
// followed by a : (in scope==0 with recently_seen_preprocessor==false) and we
// have not yet seen the character { or ;
bool recently_seen_preprocessor = false;
// true if we have seen the #pragma or #if or #define or #elif keyword and
// have not seen an identifier.
bool recently_seen_extern = false;
// true if we have seen the extern keyword and haven't yet seen a
// { or ; character.
unsigned long paren_count = 0;
// this is the number of ( we have seen minus the number of ) we have
// seen.
int type;
stack scopes; // a stack to hold old scopes
string token, temp;
t.get_token(type,token);
while (type != tok::END_OF_FILE)
{
switch (type)
{
case tok::IDENTIFIER: // ------------------------------------------
if ( recently_seen_class_keyword)
{
// this might be a class name so check if there is a
// ; or identifier or * or &amp; coming up.
type = t.peek_type();
temp.clear();
if (type == tok::WHITE_SPACE)
{
t.get_token(type,temp);
if (temp.find_first_of("\n\r") != string::npos)
recently_seen_preprocessor = false;
}
if (t.peek_token() != ";" && t.peek_type() != tok::IDENTIFIER &&
t.peek_token() != "*" && t.peek_token() != "&amp;")
{
// this is the name of a class or struct in a class or
// struct declaration.
out << "<b><i>" << token << "</i></b>" << temp;
}
else
{
out << token << temp;
}
}
else if ( !in_initialization_list &&
!recently_seen_preprocessor &&
scope == 0 &&
paren_count == 0)
{
// this might be a function name so check if there is a
// ( coming up.
type = t.peek_type();
temp.clear();
if (type == tok::WHITE_SPACE)
{
t.get_token(type,temp);
type = t.peek_type();
}
if (type == tok::OTHER && t.peek_token() == "(")
{
// this is a function definition or prototype
out << "<b><i>" << token << "</i></b>" << temp;
}
else
{
out << token << temp;
}
}
else
{
out << token;
}
recently_seen_class_keyword = false;
recently_seen_paren = false;
break;
case tok::KEYWORD: // ---------------------------------------------
if (scope == 0 && token == "operator")
{
// Doing this is sort of weird since operator is really a keyword
// but I just like how this looks.
out << "<b><i>" << token << "</i></b>";
}
// this isn't a keyword if it is something like #include <new>
else if (!recently_seen_include)
{
// This is a normal keyword
out << "<u><font face='Fixedsys'>" << token << "</font></u>";
}
else
{
out << token;
}
if (token == "#include")
{
recently_seen_include = true;
}
else if (token == "class")
{
recently_seen_new_scope = true;
recently_seen_class_keyword = true;
}
else if (token == "namespace")
{
recently_seen_new_scope = true;
}
else if (token == "struct")
{
recently_seen_new_scope = true;
recently_seen_class_keyword = true;
}
else if (token == "#pragma" || token == "#define" || token == "#elif" || token == "#if")
{
recently_seen_preprocessor = true;
}
else if (token == "extern")
{
recently_seen_extern = true;
}
recently_seen_paren = false;
break;
case tok::COMMENT: // ---------------------------------------------
{
out << "<font face='Courier New'>" << htmlify(token) << "</font>";
}
break;
case tok::SINGLE_QUOTED_TEXT: // ----------------------------------
{
out << htmlify(token);
recently_seen_paren = false;
}
break;
case tok::WHITE_SPACE: // -----------------------------------------
{
out << token;
if (token.find_first_of("\n\r") != string::npos)
recently_seen_preprocessor = false;
}
break;
case tok::DOUBLE_QUOTED_TEXT: // ----------------------------------
{
out << htmlify(token);
recently_seen_paren = false;
recently_seen_include = false;
}
break;
case tok::NUMBER:
case tok::OTHER: // -----------------------------------------------
switch (token[0])
{
case '{':
out << "<b>{</b>";
// if we are entering a new scope
if (recently_seen_new_scope || recently_seen_extern)
{
recently_seen_new_scope = false;
scopes.push(scope);
scope = 0;
}
else
{
++scope;
}
in_initialization_list = false;
recently_seen_paren = false;
recently_seen_class_keyword = false;
recently_seen_extern = false;
break;
case '}':
out << "<b>}</b>";
if (scope > 0)
{
--scope;
}
else if (scopes.size())
{
scopes.pop(scope);
}
recently_seen_paren = false;
break;
case ':':
out << ':';
if (recently_seen_paren && scope == 0 &&
recently_seen_preprocessor == false)
{
in_initialization_list = true;
}
recently_seen_paren = false;
break;
case ';':
out << ';';
recently_seen_new_scope = false;
recently_seen_paren = false;
recently_seen_extern = false;
break;
case ')':
out << ')';
recently_seen_paren = true;
recently_seen_new_scope = false;
--paren_count;
break;
case '(':
out << '(';
recently_seen_paren = false;
++paren_count;
break;
case '>':
recently_seen_include = false;
out << "&gt;";
recently_seen_paren = true;
break;
case '<':
out << "&lt;";
recently_seen_paren = true;
break;
case '&':
out << "&amp;";
recently_seen_paren = true;
break;
default:
out << token;
recently_seen_paren = false;
if (token == "&gt;")
recently_seen_include = false;
break;
} // switch (token[0])
break;
} // switch (type)
t.get_token(type,token);
} // while (type != tok::END_OF_FILE)
out << "</font></pre></body></html>";
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_2::print");
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
void cpp_pretty_printer_kernel_2<stack,tok>::
print_and_number (
std::istream& in,
std::ostream& out,
const std::string& title
) const
{
using namespace std;
ostringstream sout;
print(in,sout,title);
istringstream sin(sout.str());
number(sin,out);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
void cpp_pretty_printer_kernel_2<stack,tok>::
number (
std::istream& in,
std::ostream& out
) const
{
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_2::number");
std::string space = "&nbsp;&nbsp;&nbsp;";
std::ios::int_type ch;
unsigned long count = 1;
while ((ch=in.get()) != EOF)
{
if (ch != '\n')
{
out << (char)ch;
}
else
{
out << "\n<i><font face='Courier New'>" << count << " </font></i> " + space;
++count;
if (count == 10)
space = "&nbsp;&nbsp;";
if (count == 100)
space = "&nbsp;";
if (count == 1000)
space = "";
}
}
if (!out)
throw std::ios::failure("error occurred in cpp_pretty_printer_kernel_2::number");
}
// ----------------------------------------------------------------------------------------
template <
typename stack,
typename tok
>
const std::string cpp_pretty_printer_kernel_2<stack,tok>::
htmlify (
const std::string& str
) const
{
std::string::size_type i;
std::string temp;
for (i = 0; i < str.size(); ++i)
{
if (str[i] == '<')
temp += "&lt;";
else if (str[i] == '>')
temp += "&gt;";
else if (str[i] == '&')
temp += "&amp;";
else
temp += str[i];
}
return temp;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CPP_PRETTY_PRINTER_KERNEl_2_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_CPP_PRETTY_PRINTER_KERNEl_ABSTRACT_
#ifdef DLIB_CPP_PRETTY_PRINTER_KERNEl_ABSTRACT_
#include <string>
#include <ioswfd>
namespace dlib
{
class cpp_pretty_printer
{
/*!
INITIAL VALUE
This object does not have any state associated with it.
WHAT THIS OBJECT REPRESENTS
This object represents an HTML pretty printer for C++ source code.
!*/
public:
cpp_pretty_printer (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~cpp_pretty_printer (
);
/*!
ensures
- any resources associated with *this have been released
!*/
void print (
std::istream& in,
std::ostream& out,
const std::string& title
) const;
/*!
ensures
- treats data from in as C++ source code and pretty prints it in
HTML and writes it to out.
- The title of the HTML document writen to out will be title
throws
- std::ios_base::failure
If there was a problem writing to out then this exception will
be thrown.
- any other exception
This exception may be thrown if there is any other problem.
!*/
void print_and_number (
std::istream& in,
std::ostream& out,
const std::string& title
) const;
/*!
ensures
- treats data from in as C++ source code and pretty prints it in
HTML with line numbers and writes it to out.
- The title of the HTML document writen to out will be title
throws
- std::ios_base::failure
If there was a problem writing to out then this exception will
be thrown.
- any other exception
This exception may be thrown if there is any other problem.
!*/
private:
// restricted functions
cpp_pretty_printer(const cpp_pretty_printer&); // copy constructor
cpp_pretty_printer& operator=(const cpp_pretty_printer&); // assignment operator
};
}
#endif // DLIB_CPP_PRETTY_PRINTER_KERNEl_ABSTRACT_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CPP_TOKENIZEr_
#define DLIB_CPP_TOKENIZEr_
#include <string>
#include "cpp_tokenizer/cpp_tokenizer_kernel_1.h"
#include "cpp_tokenizer/cpp_tokenizer_kernel_c.h"
#include "tokenizer.h"
#include "queue.h"
#include "set.h"
namespace dlib
{
class cpp_tokenizer
{
cpp_tokenizer() {}
typedef set<std::string>::kernel_1a set;
typedef queue<cpp_tok_kernel_1_helper::token_text_pair>::kernel_2a queue;
typedef tokenizer::kernel_1a tok;
public:
//----------- kernels ---------------
// kernel_1a
typedef cpp_tokenizer_kernel_1<tok,queue,set>
kernel_1a;
typedef cpp_tokenizer_kernel_c<kernel_1a>
kernel_1a_c;
};
}
#endif // DLIB_CPP_TOKENIZEr_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CPP_TOKENIZER_KERNEl_1_
#define DLIB_CPP_TOKENIZER_KERNEl_1_
#include <string>
#include <iostream>
#include "cpp_tokenizer_kernel_abstract.h"
#include "../algs.h"
namespace dlib
{
namespace cpp_tok_kernel_1_helper
{
struct token_text_pair
{
std::string token;
int type;
};
}
template <
typename tok,
typename queue,
typename set
>
class cpp_tokenizer_kernel_1
{
/*!
REQUIREMENTS ON tok
tok must be an implementation of tokenizer/tokenizer_kernel_abstract.h
REQUIREMENTS ON queue
queue must be an implementation of queue/queue_kernel_abstract.h
and must have T==cpp_tok_kernel_1_helper::token_text_pair
REQUIREMENTS ON set
set must be an implemention of set/set_kernel_abstract.h or
hash_set/hash_set_kernel_abstract.h and must have T==std::string.
INITIAL VALUE
- keywords == a set of all the C++ keywords
- tokenizer.stream_is_set() == false
- buffer.size() == 0
- tokenizer.get_identifier_head() == "$_" + tokenizer.lowercase_letters() +
tokenizer.uppercase_letters()
- tokenizer.get_identifier_body() == "$_" + tokenizer.lowercase_letters() +
tokenizer.uppercase_letters() + tokenizer.numbers()
- have_peeked == false
CONVENTION
- tokenizer.stream_is_set() == stream_is_set()
- tokenizer.get_stream() == get_stream()
- keywords == a set of all the C++ keywords
- tokenizer.get_identifier_head() == "$_" + tokenizer.lowercase_letters() +
tokenizer.uppercase_letters()
- tokenizer.get_identifier_body() == "$_" + tokenizer.lowercase_letters() +
tokenizer.uppercase_letters() + tokenizer.numbers()
- buffer == a queue of tokens. This is where we put tokens
we gathered early due to looking ahead.
- if (have_peeked) then
- next_token == the next token to be returned from get_token()
- next_type == the type of token in peek_token
!*/
typedef cpp_tok_kernel_1_helper::token_text_pair token_text_pair;
public:
enum
{
END_OF_FILE,
KEYWORD,
COMMENT,
SINGLE_QUOTED_TEXT,
DOUBLE_QUOTED_TEXT,
IDENTIFIER,
OTHER,
NUMBER,
WHITE_SPACE
};
cpp_tokenizer_kernel_1 (
);
virtual ~cpp_tokenizer_kernel_1 (
);
void clear(
);
void set_stream (
std::istream& in
);
bool stream_is_set (
) const;
std::istream& get_stream (
) const;
void get_token (
int& type,
std::string& token
);
int peek_type (
) const;
const std::string& peek_token (
) const;
void swap (
cpp_tokenizer_kernel_1<tok,queue,set>& item
);
private:
void buffer_token(
int type,
const std::string& token
)
/*!
ensures
- stores the token and its type into buffer
!*/
{
token_text_pair temp;
temp.token = token;
temp.type = type;
buffer.enqueue(temp);
}
void buffer_token(
int type,
char token
)
/*!
ensures
- stores the token and its type into buffer
!*/
{
token_text_pair temp;
temp.token = token;
temp.type = type;
buffer.enqueue(temp);
}
// restricted functions
cpp_tokenizer_kernel_1(const cpp_tokenizer_kernel_1<tok,queue,set>&); // copy constructor
cpp_tokenizer_kernel_1<tok,queue,set>& operator=(const cpp_tokenizer_kernel_1<tok,queue,set>&); // assignment operator
// data members
set keywords;
queue buffer;
tok tokenizer;
mutable std::string next_token;
mutable int next_type;
mutable bool have_peeked;
};
template <
typename tok,
typename queue,
typename set
>
inline void swap (
cpp_tokenizer_kernel_1<tok,queue,set>& a,
cpp_tokenizer_kernel_1<tok,queue,set>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
cpp_tokenizer_kernel_1<tok,queue,set>::
cpp_tokenizer_kernel_1(
) :
have_peeked(false)
{
// add C++ keywords to keywords
std::string temp;
temp = "#include"; keywords.add(temp);
temp = "__asm"; keywords.add(temp);
temp = "_asm"; keywords.add(temp);
temp = "if"; keywords.add(temp);
temp = "int"; keywords.add(temp);
temp = "else"; keywords.add(temp);
temp = "template"; keywords.add(temp);
temp = "void"; keywords.add(temp);
temp = "false"; keywords.add(temp);
temp = "class"; keywords.add(temp);
temp = "public"; keywords.add(temp);
temp = "while"; keywords.add(temp);
temp = "bool"; keywords.add(temp);
temp = "new"; keywords.add(temp);
temp = "delete"; keywords.add(temp);
temp = "true"; keywords.add(temp);
temp = "typedef"; keywords.add(temp);
temp = "const"; keywords.add(temp);
temp = "virtual"; keywords.add(temp);
temp = "inline"; keywords.add(temp);
temp = "for"; keywords.add(temp);
temp = "break"; keywords.add(temp);
temp = "struct"; keywords.add(temp);
temp = "float"; keywords.add(temp);
temp = "case"; keywords.add(temp);
temp = "enum"; keywords.add(temp);
temp = "this"; keywords.add(temp);
temp = "typeid"; keywords.add(temp);
temp = "double"; keywords.add(temp);
temp = "char"; keywords.add(temp);
temp = "typename"; keywords.add(temp);
temp = "signed"; keywords.add(temp);
temp = "friend"; keywords.add(temp);
temp = "wint_t"; keywords.add(temp);
temp = "default"; keywords.add(temp);
temp = "asm"; keywords.add(temp);
temp = "reinterpret_cast"; keywords.add(temp);
temp = "#define"; keywords.add(temp);
temp = "do"; keywords.add(temp);
temp = "continue"; keywords.add(temp);
temp = "auto"; keywords.add(temp);
temp = "unsigned"; keywords.add(temp);
temp = "size_t"; keywords.add(temp);
temp = "#undef"; keywords.add(temp);
temp = "#pragma"; keywords.add(temp);
temp = "namespace"; keywords.add(temp);
temp = "private"; keywords.add(temp);
temp = "#endif"; keywords.add(temp);
temp = "catch"; keywords.add(temp);
temp = "#else"; keywords.add(temp);
temp = "register"; keywords.add(temp);
temp = "volatile"; keywords.add(temp);
temp = "const_cast"; keywords.add(temp);
temp = "#end"; keywords.add(temp);
temp = "mutable"; keywords.add(temp);
temp = "static_cast"; keywords.add(temp);
temp = "wchar_t"; keywords.add(temp);
temp = "#if"; keywords.add(temp);
temp = "protected"; keywords.add(temp);
temp = "throw"; keywords.add(temp);
temp = "using"; keywords.add(temp);
temp = "dynamic_cast"; keywords.add(temp);
temp = "#ifdef"; keywords.add(temp);
temp = "return"; keywords.add(temp);
temp = "short"; keywords.add(temp);
temp = "#error"; keywords.add(temp);
temp = "#line"; keywords.add(temp);
temp = "explicit"; keywords.add(temp);
temp = "union"; keywords.add(temp);
temp = "#ifndef"; keywords.add(temp);
temp = "try"; keywords.add(temp);
temp = "sizeof"; keywords.add(temp);
temp = "goto"; keywords.add(temp);
temp = "long"; keywords.add(temp);
temp = "#elif"; keywords.add(temp);
temp = "static"; keywords.add(temp);
temp = "operator"; keywords.add(temp);
temp = "switch"; keywords.add(temp);
temp = "extern"; keywords.add(temp);
// set the tokenizer's IDENTIFIER token for C++ identifiers
tokenizer.set_identifier_token(
"$_" + tokenizer.lowercase_letters() + tokenizer.uppercase_letters(),
"$_" + tokenizer.lowercase_letters() + tokenizer.uppercase_letters() +
tokenizer.numbers()
);
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
cpp_tokenizer_kernel_1<tok,queue,set>::
~cpp_tokenizer_kernel_1 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
void cpp_tokenizer_kernel_1<tok,queue,set>::
clear(
)
{
tokenizer.clear();
buffer.clear();
have_peeked = false;
// set the tokenizer's IDENTIFIER token for C++ identifiers
tokenizer.set_identifier_token(
"$_" + tokenizer.lowercase_letters() + tokenizer.uppercase_letters(),
"$_" + tokenizer.lowercase_letters() + tokenizer.uppercase_letters() +
tokenizer.numbers()
);
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
void cpp_tokenizer_kernel_1<tok,queue,set>::
set_stream (
std::istream& in
)
{
tokenizer.set_stream(in);
buffer.clear();
have_peeked = false;
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
bool cpp_tokenizer_kernel_1<tok,queue,set>::
stream_is_set (
) const
{
return tokenizer.stream_is_set();
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
std::istream& cpp_tokenizer_kernel_1<tok,queue,set>::
get_stream (
) const
{
return tokenizer.get_stream();
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
void cpp_tokenizer_kernel_1<tok,queue,set>::
get_token (
int& type,
std::string& token
)
{
using namespace std;
if (!have_peeked)
{
if (buffer.size() > 0)
{
// just return what is in the buffer
token_text_pair temp;
buffer.dequeue(temp);
type = temp.type;
token = temp.token;
return;
}
tokenizer.get_token(type,token);
switch (type)
{
case tok::END_OF_FILE:
{
type = END_OF_FILE;
} break;
case tok::END_OF_LINE:
case tok::WHITE_SPACE:
{
type = tokenizer.peek_type();
if (type == tok::END_OF_LINE || type == tok::WHITE_SPACE)
{
std::string temp;
do
{
tokenizer.get_token(type,temp);
token += temp;
type = tokenizer.peek_type();
}while (type == tok::END_OF_LINE || type == tok::WHITE_SPACE);
}
type = WHITE_SPACE;
} break;
case tok::NUMBER:
{
// this could be a hex number such as 0xa33. we should check for this.
if (tokenizer.peek_type() == tok::IDENTIFIER && token == "0" &&
(tokenizer.peek_token()[0] == 'x' || tokenizer.peek_token()[0] == 'X'))
{
// this is a hex number so accumulate all the numbers and identifiers that follow
// because they have to be part of the number
std::string temp;
tokenizer.get_token(type,temp);
token = "0" + temp;
// get the rest of the hex number
while (tokenizer.peek_type() == tok::IDENTIFIER ||
tokenizer.peek_type() == tok::NUMBER
)
{
tokenizer.get_token(type,temp);
token += temp;
}
}
// or this could be a floating point value
else if (tokenizer.peek_type() == tok::CHAR && tokenizer.peek_token()[0] == '.')
{
std::string temp;
tokenizer.get_token(type,temp);
token += '.';
// now get the rest of the floating point value
while (tokenizer.peek_type() == tok::IDENTIFIER ||
tokenizer.peek_type() == tok::NUMBER
)
{
tokenizer.get_token(type,temp);
token += temp;
}
}
type = NUMBER;
} break;
case tok::IDENTIFIER:
{
if (keywords.is_member(token))
{
type = KEYWORD;
}
else
{
type = IDENTIFIER;
}
} break;
case tok::CHAR:
type = OTHER;
switch (token[0])
{
case '#':
{
// this might be a preprocessor keyword so we should check the
// next token
if (tokenizer.peek_type() == tok::IDENTIFIER &&
keywords.is_member('#'+tokenizer.peek_token()))
{
tokenizer.get_token(type,token);
token = '#' + token;
type = KEYWORD;
}
else
{
token = '#';
type = OTHER;
}
}
break;
case '"':
{
string temp;
tokenizer.get_token(type,token);
while (type != tok::END_OF_FILE)
{
// if this is the end of the quoted string
if (type == tok::CHAR && token[0] == '"' &&
(temp.size() == 0 || temp[temp.size()-1] != '\\' ||
(temp.size() > 1 && temp[temp.size()-2] == '\\') ))
{
buffer_token(DOUBLE_QUOTED_TEXT,temp);
buffer_token(OTHER,'"');
break;
}
else
{
temp += token;
}
tokenizer.get_token(type,token);
}
type = OTHER;
token = '"';
} break;
case '\'':
{
string temp;
tokenizer.get_token(type,token);
if (type == tok::CHAR && token[0] == '\\')
{
temp += '\\';
tokenizer.get_token(type,token);
}
temp += token;
buffer_token(SINGLE_QUOTED_TEXT,temp);
// The next character should be a ' so take it out and put it in
// the buffer.
tokenizer.get_token(type,token);
buffer_token(OTHER,token);
type = OTHER;
token = '\'';
} break;
case '/':
{
// look ahead to see if this is the start of a comment
if (tokenizer.peek_type() == tok::CHAR)
{
if (tokenizer.peek_token()[0] == '/')
{
tokenizer.get_token(type,token);
// this is the start of a line comment
token = "//";
string temp;
tokenizer.get_token(type,temp);
while (type != tok::END_OF_FILE)
{
// if this is the end of the comment
if (type == tok::END_OF_LINE &&
token[token.size()-1] != '\\' )
{
token += '\n';
break;
}
else
{
token += temp;
}
tokenizer.get_token(type,temp);
}
type = COMMENT;
}
else if (tokenizer.peek_token()[0] == '*')
{
tokenizer.get_token(type,token);
// this is the start of a block comment
token = "/*";
string temp;
tokenizer.get_token(type,temp);
while (type != tok::END_OF_FILE)
{
// if this is the end of the comment
if (type == tok::CHAR && temp[0] == '/' &&
token[token.size()-1] == '*')
{
token += '/';
break;
}
else
{
token += temp;
}
tokenizer.get_token(type,temp);
}
type = COMMENT;
}
}
} break;
default:
break;
} // switch (token[0])
} // switch (type)
}
else
{
// if we get this far it means we have peeked so we should
// return the peek data.
type = next_type;
token = next_token;
have_peeked = false;
}
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
int cpp_tokenizer_kernel_1<tok,queue,set>::
peek_type (
) const
{
const_cast<cpp_tokenizer_kernel_1<tok,queue,set>*>(this)->get_token(next_type,next_token);
have_peeked = true;
return next_type;
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
const std::string& cpp_tokenizer_kernel_1<tok,queue,set>::
peek_token (
) const
{
const_cast<cpp_tokenizer_kernel_1<tok,queue,set>*>(this)->get_token(next_type,next_token);
have_peeked = true;
return next_token;
}
// ----------------------------------------------------------------------------------------
template <
typename tok,
typename queue,
typename set
>
void cpp_tokenizer_kernel_1<tok,queue,set>::
swap (
cpp_tokenizer_kernel_1& item
)
{
tokenizer.swap(item.tokenizer);
buffer.swap(item.buffer);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CPP_TOKENIZER_KERNEl_1_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_CPP_TOKENIZER_KERNEl_ABSTRACT_
#ifdef DLIB_CPP_TOKENIZER_KERNEl_ABSTRACT_
#include <string>
#include <ioswfd>
namespace dlib
{
class cpp_tokenizer
{
/*!
INITIAL VALUE
stream_is_set() == false
WHAT THIS OBJECT REPRESENTS
This object represents a simple tokenizer for C++ source code.
BUFFERING
This object is allowed to buffer data from the input stream.
Thus if you clear it or switch streams (via calling set_stream())
any buffered data will be lost.
TOKENS
When picking out tokens the cpp_tokenizer will always extract the
longest token it can. For example, if faced with the string
"AAA" it will consider the three As to be a single IDENTIFIER
token not three smaller IDENTIFIER tokens.
Also note that no characters in the input stream are discarded.
They will all be returned in the text of some token.
Additionally, each character will never be returned more than once.
This means that if you concatenated all returned tokens it would exactly
reproduce the contents of the input stream.
The tokens are defined as follows:
END_OF_FILE
This token represents the end of file. It doesn't have any
actual characters associated with it.
KEYWORD
This token matches a C++ keyword. (This includes the preprocessor
directives).
COMMENT
This token matches a C++ comment.
SINGLE_QUOTED_TEXT
This token matches the text of any single quoted literal.
For example, 'a' would be a match and the text of this token
would be the single character a.
DOUBLE_QUOTED_TEXT
This token matches the text of any double quoted string.
For example, "C++" would be a match and the text of this token
would be the three character string C++.
WHITE_SPACE
This is a multi character token. It is defined as a sequence of
one or more spaces, carrage returns, newlines, and tabs. I.e. It
is composed of characters from the following string " \r\n\t".
IDENTIFIER
This token matches any C++ identifier that isn't matched by any
of the above tokens. (A C++ identifier being a string matching
the regular expression [_$a-zA-Z][_$a-zA-Z0-9]*).
NUMBER
This token matches any C++ numerical constant.
OTHER
This matches anything that isn't part of one of the above tokens.
It is always a single character.
!*/
public:
enum
{
END_OF_FILE,
KEYWORD,
COMMENT,
SINGLE_QUOTED_TEXT,
DOUBLE_QUOTED_TEXT,
IDENTIFIER,
OTHER,
NUMBER,
WHITE_SPACE
};
cpp_tokenizer (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~cpp_tokenizer (
);
/*!
ensures
- any resources associated with *this have been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc
If this exception is thrown then #*this is unusable
until clear() is called and succeeds.
!*/
void set_stream (
std::istream& in
);
/*!
ensures
- #*this will read data from in and tokenize it
- #stream_is_set() == true
- #get_stream() == in
!*/
bool stream_is_set (
) const;
/*!
ensures
- returns true if a stream has been associated with *this by calling
set_stream()
!*/
std::istream& get_stream (
) const;
/*!
requires
- stream_is_set() == true
ensures
- returns a reference to the istream object that *this is reading
from.
!*/
void get_token (
int& type,
std::string& token
);
/*!
requires
- stream_is_set() == true
ensures
- #token == the next token from the input stream get_stream()
- #type == the type of the token in #token
throws
- bad_alloc
If this exception is thrown then the call to this function will
have no effect on *this but the values of #type and #token will be
undefined. Additionally, some characters may have been read
from the stream get_stream() and lost.
!*/
int peek_type (
) const;
/*!
requires
- stream_is_set() == true
ensures
- returns the type of the token that will be returned from
the next call to get_token()
throws
- bad_alloc
If this exception is thrown then the call to this function will
have no effect on *this. However, some characters may have been
read from the stream get_stream() and lost.
!*/
const std::string& peek_token (
) const;
/*!
requires
- stream_is_set() == true
ensures
- returns the text of the token that will be returned from
the next call to get_token()
throws
- bad_alloc
If this exception is thrown then the call to this function will
have no effect on *this. However, some characters may have been
read from the stream get_stream() and lost.
!*/
void swap (
cpp_tokenizer& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
cpp_tokenizer(const cpp_tokenizer&); // copy constructor
cpp_tokenizer& operator=(const cpp_tokenizer&); // assignment operator
};
inline void swap (
cpp_tokenizer& a,
cpp_tokenizer& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_CPP_TOKENIZER_KERNEl_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CPP_TOKENIZER_KERNEl_C_
#define DLIB_CPP_TOKENIZER_KERNEl_C_
#include "cpp_tokenizer_kernel_abstract.h"
#include "../assert.h"
#include <string>
#include <iostream>
namespace dlib
{
template <
typename tokenizer
>
class cpp_tokenizer_kernel_c : public tokenizer
{
public:
std::istream& get_stream (
) const;
void get_token (
int& type,
std::string& token
);
int peek_type (
) const;
const std::string& peek_token (
) const;
};
template <
typename tokenizer
>
inline void swap (
cpp_tokenizer_kernel_c<tokenizer>& a,
cpp_tokenizer_kernel_c<tokenizer>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename tokenizer
>
std::istream& cpp_tokenizer_kernel_c<tokenizer>::
get_stream (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( this->stream_is_set() == true,
"\tstd::istream& cpp_tokenizer::get_stream()"
<< "\n\tyou must set a stream for this object before you can get it"
<< "\n\tthis: " << this
);
// call the real function
return tokenizer::get_stream();
}
// ----------------------------------------------------------------------------------------
template <
typename tokenizer
>
const std::string& cpp_tokenizer_kernel_c<tokenizer>::
peek_token (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( this->stream_is_set() == true,
"\tconst std::string& cpp_tokenizer::peek_token()"
<< "\n\tyou must set a stream for this object before you can peek at what it contains"
<< "\n\tthis: " << this
);
// call the real function
return tokenizer::peek_token();
}
// ----------------------------------------------------------------------------------------
template <
typename tokenizer
>
int cpp_tokenizer_kernel_c<tokenizer>::
peek_type (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( this->stream_is_set() == true,
"\tint cpp_tokenizer::peek_type()"
<< "\n\tyou must set a stream for this object before you can peek at what it contains"
<< "\n\tthis: " << this
);
// call the real function
return tokenizer::peek_type();
}
// ----------------------------------------------------------------------------------------
template <
typename tokenizer
>
void cpp_tokenizer_kernel_c<tokenizer>::
get_token (
int& type,
std::string& token
)
{
// make sure requires clause is not broken
DLIB_CASSERT( this->stream_is_set() == true,
"\tvoid cpp_tokenizer::get_token()"
<< "\n\tyou must set a stream for this object before you can get tokens from it."
<< "\n\tthis: " << this
);
// call the real function
tokenizer::get_token(type,token);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_TOKENIZER_KERNEl_C_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CRc32_
#define DLIB_CRc32_
#include "crc32/crc32_kernel_1.h"
namespace dlib
{
class crc32
{
crc32() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef crc32_kernel_1
kernel_1a;
};
}
#endif // DLIB_CRc32_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CRC32_KERNEl_1_
#define DLIB_CRC32_KERNEl_1_
#include "../algs.h"
#include <string>
#include "crc32_kernel_abstract.h"
namespace dlib
{
class crc32_kernel_1
{
/*!
INITIAL VALUE
checksum == 0xFFFFFFFF
table == crc table
CONVENTION
get_checksum() == checksum ^ 0xFFFFFFFF
table == crc table
!*/
public:
inline crc32_kernel_1 (
);
inline virtual ~crc32_kernel_1 (
);
inline void clear(
);
inline void add (
unsigned char item
);
inline void add (
const std::string& item
);
inline unsigned long get_checksum (
) const;
inline void swap (
crc32_kernel_1& item
);
private:
unsigned long checksum;
unsigned long table[256];
// restricted functions
crc32_kernel_1(const crc32_kernel_1&); // copy constructor
crc32_kernel_1& operator=(const crc32_kernel_1&); // assignment operator
};
inline void swap (
crc32_kernel_1& a,
crc32_kernel_1& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
crc32_kernel_1::
crc32_kernel_1 (
)
{
checksum = 0xFFFFFFFF;
unsigned long temp;
// fill out the crc table
for (unsigned long i = 0; i < 256; ++i)
{
temp = i;
for (unsigned long j = 0; j < 8; ++j)
{
if (temp&1)
temp = (temp>>1)^0xedb88320;
else
temp >>= 1;
}
table[i] = temp;
}
}
// ----------------------------------------------------------------------------------------
crc32_kernel_1::
~crc32_kernel_1 (
)
{
}
// ----------------------------------------------------------------------------------------
void crc32_kernel_1::
clear(
)
{
checksum = 0xFFFFFFFF;
}
// ----------------------------------------------------------------------------------------
void crc32_kernel_1::
add (
unsigned char item
)
{
checksum = (checksum>>8) ^ table[(checksum^item) & 0xFF];
}
// ----------------------------------------------------------------------------------------
void crc32_kernel_1::
add (
const std::string& item
)
{
for (std::string::size_type i = 0; i < item.size(); ++i)
checksum = (checksum>>8) ^ table[(checksum^item[i]) & 0xFF];
}
// ----------------------------------------------------------------------------------------
unsigned long crc32_kernel_1::
get_checksum (
) const
{
return checksum ^ 0xFFFFFFFF;
}
// ----------------------------------------------------------------------------------------
void crc32_kernel_1::
swap (
crc32_kernel_1& item
)
{
exchange(checksum,item.checksum);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CRC32_KERNEl_1_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_CRC32_KERNEl_ABSTRACT_
#ifdef DLIB_CRC32_KERNEl_ABSTRACT_
#include "../algs.h"
#include <string>
namespace dlib
{
class crc32
{
/*!
INITIAL VALUE
The current checksum covers zero bytes.
get_checksum() == 0x00000000
WHAT THIS OBJECT REPRESENTS
This object represents the CRC32 algorithm for calculating
checksums.
!*/
public:
crc32 (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~crc32 (
);
/*!
ensures
- any resources associated with *this have been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
void add (
unsigned char item
);
/*!
ensures
- #get_checksum() == The checksum of all items added to *this previously
concatenated with item.
!*/
void add (
const std::string& item
);
/*!
ensures
- #get_checksum() == The checksum of all items added to *this previously
concatenated with item.
!*/
unsigned long get_checksum (
) const;
/*!
ensures
- returns the current checksum
!*/
void swap (
crc32& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
crc32(const crc32&); // copy constructor
crc32& operator=(const crc32&); // assignment operator
};
void swap (
crc32& a,
crc32& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_CRC32_KERNEl_ABSTRACT_
#include "dlib_include_path_tutorial.txt"
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIR_NAv_
#define DLIB_DIR_NAv_
#include "platform.h"
#ifdef WIN32
#include "dir_nav/windows.h"
#endif
#ifndef WIN32
#include "dir_nav/posix.h"
#endif
#endif // DLIB_DIR_NAv_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIR_NAV_KERNEL_1_CPp_
#define DLIB_DIR_NAV_KERNEL_1_CPp_
#include "../platform.h"
#ifdef WIN32
#include "dir_nav_kernel_1.h"
#include "../string.h"
#ifdef __BORLANDC__
// Apparently the borland compiler doesn't define this.
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// file object implementation
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
file::
file (
const std::string& name
)
{
using namespace std;
state = new data;
state->count = 1;
char buf[3000];
char* str;
if (GetFullPathNameA(name.c_str(),sizeof(buf),buf,&str) == 0)
{
// the file was not found
throw file_not_found("Unable to find file " + name);
}
state->full_name = buf;
string::size_type pos = state->full_name.find_last_of(directory::get_separator());
if (pos == string::npos)
{
// no valid full path has no separtor characters.
throw file_not_found("Unable to find file " + name);
}
state->name = state->full_name.substr(pos+1);
// now find the size of this file
WIN32_FIND_DATAA data;
HANDLE ffind = FindFirstFileA(state->full_name.c_str(), &data);
if (ffind == INVALID_HANDLE_VALUE ||
(data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0)
{
throw file_not_found("Unable to find file " + name);
}
else
{
uint64 temp = data.nFileSizeHigh;
temp <<= 32;
temp |= data.nFileSizeLow;
state->file_size = temp;
FindClose(ffind);
}
}
// ----------------------------------------------------------------------------------------
bool file::
operator == (
const file& rhs
) const
{
using namespace std;
if (state->full_name.size() != rhs.state->full_name.size())
return false;
// compare the strings but ignore the case because file names
// are not case sensitive on windows
return tolower(state->full_name) == tolower(rhs.state->full_name);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// directory object implementation
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
directory::
directory (
const std::string& name
)
{
using namespace std;
state = new data;
state->count = 1;
char buf[3000];
char* str;
if (GetFullPathNameA(name.c_str(),sizeof(buf),buf,&str) == 0)
{
// the directory was not found
throw dir_not_found("Unable to find directory " + name);
}
state->full_name = buf;
const char sep = get_separator();
if (is_root_path(state->full_name) == false)
{
// ensure that thre is not a trialing separator
if (state->full_name[state->full_name.size()-1] == sep)
state->full_name.erase(state->full_name.size()-1);
// pick out the directory name
string::size_type pos = state->full_name.find_last_of(sep);
state->name = state->full_name.substr(pos+1);
}
else
{
// ensure that there is a trailing separator
if (state->full_name[state->full_name.size()-1] != sep)
state->full_name += sep;
}
// now check that this is actually a valid directory
DWORD attribs = GetFileAttributesA(state->full_name.c_str());
if (attribs == INVALID_FILE_ATTRIBUTES ||
(attribs&FILE_ATTRIBUTE_DIRECTORY) == 0)
{
// the directory was not found
throw dir_not_found("Unable to find directory " + name);
}
}
// ----------------------------------------------------------------------------------------
char directory::
get_separator (
)
{
return '\\';
}
// ----------------------------------------------------------------------------------------
bool directory::
operator == (
const directory& rhs
) const
{
using namespace std;
if (state->full_name.size() != rhs.state->full_name.size())
return false;
// compare the strings but ignore the case because file names
// are not case sensitive on windows
return tolower(state->full_name) == tolower(rhs.state->full_name);
}
// ----------------------------------------------------------------------------------------
const directory directory::
get_parent (
) const
{
using namespace std;
// if *this is the root then just return *this
if (is_root())
{
return *this;
}
else
{
directory temp;
const char sep = get_separator();
string::size_type pos = state->full_name.find_last_of(sep);
temp.state->full_name = state->full_name.substr(0,pos);
if ( is_root_path(temp.state->full_name))
{
temp.state->full_name += sep;
}
else
{
pos = temp.state->full_name.find_last_of(sep);
if (pos != string::npos)
{
temp.state->name = temp.state->full_name.substr(pos+1);
}
else
{
temp.state->full_name += sep;
}
}
return temp;
}
}
// ----------------------------------------------------------------------------------------
bool directory::
is_root_path (
const std::string& path
) const
{
using namespace std;
const char sep = get_separator();
bool root_path = false;
if (path.size() > 2 && path[0] == sep && path[1] == sep)
{
// in this case this is a windows share path
string::size_type pos = path.find_first_of(sep,2);
if (pos != string::npos)
{
pos = path.find_first_of(sep,pos+1);
if (pos == string::npos && path[path.size()-1] != sep)
root_path = true;
else if (pos == path.size()-1)
root_path = true;
}
}
else if ( (path.size() == 2 || path.size() == 3) && path[1] == ':')
{
// if this is a valid windows path then it must be a root path
root_path = true;
}
return root_path;
}
// ----------------------------------------------------------------------------------------
}
#endif // WIN32
#endif // DLIB_DIR_NAV_KERNEL_1_CPp_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIR_NAV_KERNEl_1_
#define DLIB_DIR_NAV_KERNEl_1_
#ifdef DLIB_ISO_CPP_ONLY
#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it."
#endif
#include "../platform.h"
#include "dir_nav_kernel_abstract.h"
#include <string>
#include "../uintn.h"
#include "../algs.h"
#include "../windows_magic.h"
#include <windows.h>
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// file object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class file
{
/*!
INITIAL VALUES
state->name == name()
state->full_name == full_name()
state->file_size == size()
CONVENTION
state->name == name()
state->full_name == full_name()
state->file_size == size()
state->count == the number of file objects that point to state
!*/
friend class directory;
struct data
{
uint64 file_size;
std::string name;
std::string full_name;
unsigned long count;
};
inline file (
const std::string& name,
const std::string& full_name,
const uint64 file_size
)
{
state = new data;
state->count = 1;
state->file_size = file_size;
state->name = name;
state->full_name = full_name;
}
public:
class file_not_found : public error {
public: file_not_found(const std::string& s): error(s){}
};
inline file (
)
{
state = new data;
state->count = 1;
state->file_size = 0;
}
file (
const std::string& name
);
inline file (
const file& item
)
{
state = item.state;
state->count += 1;
}
inline ~file (
)
{
if (state->count == 1)
delete state;
else
state->count -= 1;
}
inline const std::string& name (
) const { return state->name; }
inline const std::string& full_name (
) const { return state->full_name; }
inline uint64 size (
) const { return state->file_size; }
inline file& operator= (
const file& rhs
)
{
if (&rhs == this)
return *this;
if (state->count == 1)
delete state;
else
state->count -= 1;
state = rhs.state;
state->count += 1;
return *this;
}
bool operator == (
const file& rhs
) const;
inline bool operator < (
const file& item
) const { return full_name() < item.full_name(); }
inline void swap (
file& item
)
{
exchange(state,item.state);
}
private:
// member data
data* state;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// directory object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class directory
{
/*!
INITIAL VALUES
state->name == name()
state->full_name == full_name()
CONVENTION
state->name == name()
state->full_name == full_name()
state->count == the number of directory objects that point to state
is_root() == state->name.size() == 0
!*/
struct data
{
std::string name;
std::string full_name;
unsigned long count;
};
public:
/*
The reason we don't just make this constructor actually
private is because doing it this way avoids a bug that
sometimes occurs in visual studio 7.1. The bug has
something to do with templated friend functions
such as the get_filesystem_roots() function below if
it was declared as a friend template of this class.
*/
struct private_constructor{};
inline directory (
const std::string& name,
const std::string& full_name,
private_constructor
)
{
state = new data;
state->count = 1;
state->name = name;
state->full_name = full_name;
}
class dir_not_found : public error {
public: dir_not_found(const std::string& s):error(s){}
};
class listing_error : public error {
public: listing_error(const std::string& s):error(s){}
};
inline directory (
)
{
state = new data;
state->count = 1;
}
directory (
const std::string& name
);
inline directory (
const directory& item
)
{
state = item.state;
state->count += 1;
}
inline ~directory (
)
{
if (state->count == 1)
delete state;
else
state->count -= 1;
}
static char get_separator (
);
template <
typename queue_of_files
// Is an implementation of queue/queue_kernel_abstract.h with T set to file.
>
void get_files (
queue_of_files& files
) const;
template <
typename queue_of_dirs
// Is an implementation of queue/queue_kernel_abstract.h with T set to directory.
>
void get_dirs (
queue_of_dirs& dirs
) const;
const directory get_parent (
) const;
inline bool is_root (
) const { return state->name.size() == 0; }
inline const std::string& name (
) const { return state->name; }
inline const std::string& full_name (
) const { return state->full_name; }
directory& operator= (
const directory& rhs
)
{
if (&rhs == this)
return *this;
if (state->count == 1)
delete state;
else
state->count -= 1;
state = rhs.state;
state->count += 1;
return *this;
}
bool operator == (
const directory& rhs
) const;
inline bool operator < (
const directory& item
) const { return full_name() < item.full_name(); }
inline void swap (
directory& item
)
{
exchange(state,item.state);
}
private:
// member data
data* state;
bool is_root_path (
const std::string& path
) const;
/*!
ensures
- returns true if path is a root path.
Note that this function considers root paths that don't
have a trailing separator to also be valid.
!*/
};
// ----------------------------------------------------------------------------------------
template <
typename queue_of_dir
>
void get_filesystem_roots (
queue_of_dir& roots
)
{
roots.clear();
const DWORD mask = GetLogicalDrives();
DWORD bit = 1;
char buf[] = "A:\\";
do
{
if (mask & bit)
{
directory dir("",buf,directory::private_constructor());
roots.enqueue(dir);
}
bit <<= 1;
++buf[0];
} while (buf[0] != 'Z');
}
// ----------------------------------------------------------------------------------------
inline void swap (
file& a,
file& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
inline void swap (
directory& a,
directory& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// templated member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename queue_of_files
>
void directory::
get_files (
queue_of_files& files
) const
{
using namespace std;
files.clear();
if (state->full_name.size() == 0)
throw listing_error("This directory object currently doesn't represent any directory.");
HANDLE ffind = INVALID_HANDLE_VALUE;
try
{
WIN32_FIND_DATAA data;
string path = state->full_name;
// ensure that the path ends with a separator
if (path[path.size()-1] != get_separator())
path += get_separator();
ffind = FindFirstFileA((path+"*").c_str(), &data);
if (ffind == INVALID_HANDLE_VALUE)
{
throw listing_error("Unable to list the contents of " + state->full_name);
}
bool no_more_files = false;
do
{
if ((data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == 0)
{
uint64 file_size = data.nFileSizeHigh;
file_size <<= 32;
file_size |= data.nFileSizeLow;
// this is a file so add it to the queue
file temp(data.cFileName,path+data.cFileName,file_size);
files.enqueue(temp);
}
if (FindNextFileA(ffind,&data) == 0)
{
// an error occurred
if ( GetLastError() == ERROR_NO_MORE_FILES)
{
// there are no more files
no_more_files = true;
}
else
{
// there was an error
throw listing_error("Unable to list the contents of " + state->full_name);
}
}
} while (no_more_files == false);
FindClose(ffind);
ffind = INVALID_HANDLE_VALUE;
}
catch (...)
{
if (ffind != INVALID_HANDLE_VALUE)
FindClose(ffind);
files.clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename queue_of_dirs
>
void directory::
get_dirs (
queue_of_dirs& dirs
) const
{
using namespace std;
dirs.clear();
if (state->full_name.size() == 0)
throw listing_error("This directory object currently doesn't represent any directory.");
HANDLE dfind = INVALID_HANDLE_VALUE;
try
{
WIN32_FIND_DATAA data;
string path = state->full_name;
// ensure that the path ends with a separator
if (path[path.size()-1] != get_separator())
path += get_separator();
dfind = FindFirstFileA((path+"*").c_str(), &data);
if (dfind == INVALID_HANDLE_VALUE)
{
throw listing_error("Unable to list the contents of " + state->full_name);
}
bool no_more_files = false;
do
{
string tname(data.cFileName);
if ((data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0 &&
tname != "." &&
tname != "..")
{
// this is a directory so add it to the queue
directory temp(tname,path+tname,private_constructor());
dirs.enqueue(temp);
}
if (FindNextFileA(dfind,&data) == 0)
{
// an error occurred
if ( GetLastError() == ERROR_NO_MORE_FILES)
{
// there are no more files
no_more_files = true;
}
else
{
// there was an error
throw listing_error("Unable to list the contents of " + state->full_name);
}
}
} while (no_more_files == false);
FindClose(dfind);
dfind = INVALID_HANDLE_VALUE;
}
catch (...)
{
if (dfind != INVALID_HANDLE_VALUE)
FindClose(dfind);
dirs.clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "dir_nav_kernel_1.cpp"
#endif
#endif // DLIB_DIR_NAV_KERNEl_1_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIR_NAV_KERNEL_2_CPp_
#define DLIB_DIR_NAV_KERNEL_2_CPp_
#include "../platform.h"
#ifdef POSIX
#include "dir_nav_kernel_2.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// file object implementation
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
file::
file (
const std::string& name
)
{
using namespace std;
state = new data;
state->count = 1;
char buf[PATH_MAX];
if (realpath(name.c_str(),buf) == 0)
{
// the file was not found
throw file_not_found("Unable to find file " + name);
}
state->full_name = buf;
string::size_type pos = state->full_name.find_last_of(directory::get_separator());
if (pos == string::npos)
{
// no valid full path has no separtor characters.
throw file_not_found("Unable to find file " + name);
}
state->name = state->full_name.substr(pos+1);
// now find the size of this file
struct stat64 buffer;
if (::stat64(state->full_name.c_str(), &buffer) ||
S_ISDIR(buffer.st_mode))
{
// there was an error during the call to stat64 or
// name is actually a directory
throw file_not_found("Unable to find file " + name);
}
else
{
state->file_size = static_cast<uint64>(buffer.st_size);
}
}
// ----------------------------------------------------------------------------------------
bool file::
operator == (
const file& rhs
) const
{
using namespace std;
if (state->full_name.size() == 0 && rhs.state->full_name.size() == 0)
return true;
// These files might have different names but actually represent the same
// file due to the presence of symbolic links.
char buf[PATH_MAX];
string left, right;
if (realpath(state->full_name.c_str(),buf) == 0)
return false;
left = buf;
if (realpath(rhs.state->full_name.c_str(),buf) == 0)
return false;
right = buf;
return (left == right);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// directory object implementation
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
directory::
directory (
const std::string& name
)
{
using namespace std;
state = new data;
state->count = 1;
char buf[PATH_MAX];
if (realpath(name.c_str(),buf) == 0)
{
// the directory was not found
throw dir_not_found("Unable to find directory " + name);
}
state->full_name = buf;
const char sep = get_separator();
if (is_root_path(state->full_name) == false)
{
// ensure that thre is not a trialing separator
if (state->full_name[state->full_name.size()-1] == sep)
state->full_name.erase(state->full_name.size()-1);
// pick out the directory name
string::size_type pos = state->full_name.find_last_of(sep);
state->name = state->full_name.substr(pos+1);
}
else
{
// ensure that there is a trailing separator
if (state->full_name[state->full_name.size()-1] != sep)
state->full_name += sep;
}
struct stat64 buffer;
// now check that this is actually a valid directory
if (::stat64(state->full_name.c_str(),&buffer))
{
// the directory was not found
throw dir_not_found("Unable to find directory " + name);
}
else if (S_ISDIR(buffer.st_mode) == 0)
{
// It is not a directory
throw dir_not_found("Unable to find directory " + name);
}
}
// ----------------------------------------------------------------------------------------
char directory::
get_separator (
)
{
return '/';
}
// ----------------------------------------------------------------------------------------
bool directory::
operator == (
const directory& rhs
) const
{
using namespace std;
if (state->full_name.size() == 0 && rhs.state->full_name.size() == 0)
return true;
// These directories might have different names but actually represent the same
// directory due to the presence of symbolic links.
char buf[PATH_MAX];
string left, right;
if (realpath(state->full_name.c_str(),buf) == 0)
return false;
left = buf;
if (realpath(rhs.state->full_name.c_str(),buf) == 0)
return false;
right = buf;
return (left == right);
}
// ----------------------------------------------------------------------------------------
const directory directory::
get_parent (
) const
{
using namespace std;
// if *this is the root then just return *this
if (is_root())
{
return *this;
}
else
{
directory temp;
const char sep = get_separator();
string::size_type pos = state->full_name.find_last_of(sep);
temp.state->full_name = state->full_name.substr(0,pos);
if ( is_root_path(temp.state->full_name))
{
temp.state->full_name += sep;
}
else
{
pos = temp.state->full_name.find_last_of(sep);
if (pos != string::npos)
{
temp.state->name = temp.state->full_name.substr(pos+1);
}
else
{
temp.state->full_name += sep;
}
}
return temp;
}
}
// ----------------------------------------------------------------------------------------
bool directory::
is_root_path (
const std::string& path
) const
{
const char sep = get_separator();
if (path.size() == 1 && path[0] == sep)
return true;
else
return false;
}
// ----------------------------------------------------------------------------------------
}
#endif // POSIX
#endif // DLIB_DIR_NAV_KERNEL_2_CPp_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIR_NAV_KERNEl_2_
#define DLIB_DIR_NAV_KERNEl_2_
#ifdef DLIB_ISO_CPP_ONLY
#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it."
#endif
#include "dir_nav_kernel_abstract.h"
#include <string>
#include "../uintn.h"
#include "../algs.h"
#include <sys/types.h>
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#if !defined(__USE_LARGEFILE64 ) && !defined(_LARGEFILE64_SOURCE)
#define stat64 stat
#endif
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// file object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class file
{
/*!
INITIAL VALUES
state->name == name()
state->full_name == full_name()
state->file_size == size()
CONVENTION
state->name == name()
state->full_name == full_name()
state->file_size == size()
state->count == the number of file objects that point to state
!*/
friend class directory;
struct data
{
uint64 file_size;
std::string name;
std::string full_name;
unsigned long count;
};
inline file (
const std::string& name,
const std::string& full_name,
const uint64 file_size
)
{
state = new data;
state->count = 1;
state->file_size = file_size;
state->name = name;
state->full_name = full_name;
}
public:
class file_not_found : public error {
public: file_not_found(const std::string& s): error(s){}
};
inline file (
)
{
state = new data;
state->count = 1;
state->file_size = 0;
}
file (
const std::string& name
);
inline file (
const file& item
)
{
state = item.state;
state->count += 1;
}
inline ~file (
)
{
if (state->count == 1)
delete state;
else
state->count -= 1;
}
inline const std::string& name (
) const { return state->name; }
inline const std::string& full_name (
) const { return state->full_name; }
inline uint64 size (
) const { return state->file_size; }
inline file& operator= (
const file& rhs
)
{
if (&rhs == this)
return *this;
if (state->count == 1)
delete state;
else
state->count -= 1;
state = rhs.state;
state->count += 1;
return *this;
}
bool operator == (
const file& rhs
) const;
inline bool operator < (
const file& item
) const { return full_name() < item.full_name(); }
inline void swap (
file& item
)
{
exchange(state,item.state);
}
private:
// member data
data* state;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// directory object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class directory
{
/*!
INITIAL VALUES
state->name == name()
state->full_name == full_name()
CONVENTION
state->name == name()
state->full_name == full_name()
state->count == the number of directory objects that point to state
is_root() == state->name.size() == 0
!*/
struct data
{
std::string name;
std::string full_name;
unsigned long count;
};
inline directory (
const std::string& name,
const std::string& full_name
)
{
state = new data;
state->count = 1;
state->name = name;
state->full_name = full_name;
}
public:
class dir_not_found : public error {
public: dir_not_found(const std::string& s):error(s){}
};
class listing_error : public error {
public: listing_error(const std::string& s):error(s){}
};
inline directory (
)
{
state = new data;
state->count = 1;
}
directory (
const std::string& name
);
inline directory (
const directory& item
)
{
state = item.state;
state->count += 1;
}
inline ~directory (
)
{
if (state->count == 1)
delete state;
else
state->count -= 1;
}
static char get_separator (
);
template <
typename queue_of_files
// Is an implementation of queue/queue_kernel_abstract.h with T set to file.
>
void get_files (
queue_of_files& files
) const;
template <
typename queue_of_dirs
// Is an implementation of queue/queue_kernel_abstract.h with T set to directory.
>
void get_dirs (
queue_of_dirs& dirs
) const;
const directory get_parent (
) const;
inline bool is_root (
) const { return state->name.size() == 0; }
inline const std::string& name (
) const { return state->name; }
inline const std::string& full_name (
) const { return state->full_name; }
directory& operator= (
const directory& rhs
)
{
if (&rhs == this)
return *this;
if (state->count == 1)
delete state;
else
state->count -= 1;
state = rhs.state;
state->count += 1;
return *this;
}
bool operator == (
const directory& rhs
) const;
inline bool operator < (
const directory& item
) const { return full_name() < item.full_name(); }
inline void swap (
directory& item
)
{
exchange(state,item.state);
}
private:
// member data
data* state;
bool is_root_path (
const std::string& path
) const;
/*!
ensures
- returns true if path is a root path.
Note that this function considers root paths that don't
have a trailing separator to also be valid.
!*/
};
// ----------------------------------------------------------------------------------------
inline void swap (
file& a,
file& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
inline void swap (
directory& a,
directory& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// templated member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename queue_of_files
>
void directory::
get_files (
queue_of_files& files
) const
{
using namespace std;
files.clear();
if (state->full_name.size() == 0)
throw listing_error("This directory object currently doesn't represent any directory.");
DIR* ffind = 0;
struct dirent* data;
struct stat64 buffer;
try
{
string path = state->full_name;
// ensure that the path ends with a separator
if (path[path.size()-1] != get_separator())
path += get_separator();
// get a handle to something we can search with
ffind = opendir(state->full_name.c_str());
if (ffind == 0)
{
throw listing_error("Unable to list the contents of " + state->full_name);
}
while(true)
{
errno = 0;
if ( (data = readdir(ffind)) == 0)
{
// there was an error or no more files
if ( errno == 0)
{
// there are no more files
break;
}
else
{
// there was an error
throw listing_error("Unable to list the contents of " + state->full_name);
}
}
uint64 file_size;
// get a stat64 structure so we can see if this is a file
if (::stat64((path+data->d_name).c_str(), &buffer) != 0)
{
// this might be a broken symbolic link. We can check by calling
// readlink and seeing if it finds anything.
char buf[PATH_MAX];
ssize_t temp = readlink((path+data->d_name).c_str(),buf,sizeof(buf));
if (temp == -1)
throw listing_error("Unable to list the contents of " + state->full_name);
else
file_size = static_cast<uint64>(temp);
}
else
{
file_size = static_cast<uint64>(buffer.st_size);
}
if (S_ISDIR(buffer.st_mode) == 0)
{
// this is actually a file
file temp(
data->d_name,
path+data->d_name,
file_size
);
files.enqueue(temp);
}
} // while (true)
if (ffind != 0)
{
while (closedir(ffind))
{
if (errno != EINTR)
break;
}
ffind = 0;
}
}
catch (...)
{
if (ffind != 0)
{
while (closedir(ffind))
{
if (errno != EINTR)
break;
}
ffind = 0;
}
files.clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename queue_of_dirs
>
void directory::
get_dirs (
queue_of_dirs& dirs
) const
{
using namespace std;
dirs.clear();
if (state->full_name.size() == 0)
throw listing_error("This directory object currently doesn't represent any directory.");
DIR* ffind = 0;
struct dirent* data;
struct stat64 buffer;
try
{
string path = state->full_name;
// ensure that the path ends with a separator
if (path[path.size()-1] != get_separator())
path += get_separator();
// get a handle to something we can search with
ffind = opendir(state->full_name.c_str());
if (ffind == 0)
{
throw listing_error("Unable to list the contents of " + state->full_name);
}
while(true)
{
errno = 0;
if ( (data = readdir(ffind)) == 0)
{
// there was an error or no more files
if ( errno == 0)
{
// there are no more files
break;
}
else
{
// there was an error
throw listing_error("Unable to list the contents of " + state->full_name);
}
}
// get a stat64 structure so we can see if this is a file
if (::stat64((path+data->d_name).c_str(), &buffer) != 0)
{
// just assume this isn't a directory. It is probably a broken
// symbolic link.
continue;
}
string dtemp(data->d_name);
if (S_ISDIR(buffer.st_mode) &&
dtemp != "." &&
dtemp != ".." )
{
// this is a directory so add it to dirs
directory temp(dtemp,path+dtemp);
dirs.enqueue(temp);
}
} // while (true)
if (ffind != 0)
{
while (closedir(ffind))
{
if (errno != EINTR)
break;
}
ffind = 0;
}
}
catch (...)
{
if (ffind != 0)
{
while (closedir(ffind))
{
if (errno != EINTR)
break;
}
ffind = 0;
}
dirs.clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename queue_of_dir
>
void get_filesystem_roots (
queue_of_dir& roots
)
{
roots.clear();
directory dir("/");
roots.enqueue(dir);
}
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "dir_nav_kernel_2.cpp"
#endif
#endif // DLIB_DIR_NAV_KERNEl_2_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_DIR_NAV_KERNEl_ABSTRACT_
#ifdef DLIB_DIR_NAV_KERNEl_ABSTRACT_
#include <string>
#include "../uintn.h"
#include "../algs.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
/*!
GENERAL WARNING
Don't call any of these functions or make any of these objects
before main() has been entered. That means no instances
of file or directory at the global scope.
!*/
// ----------------------------------------------------------------------------------------
template <
typename queue_of_dir
// Is an implementation of queue/queue_kernel_abstract.h with T set to directory.
>
void get_filesystem_roots (
queue_of_dir& roots
);
/*!
ensures
- #roots == a queue containing directories that represent all the roots
of the filesystem on this machine. (e.g. in windows you have c:\, d:\
etc...)
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// file object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class file
{
/*!
WHAT THIS OBJECT REPRESENTS
This object represents a file.
Note that the size of a file is determined at the time the file
object is constructed. Thus if a file changes sizes after its
file object has been created its file object's size() method
will not reflect the new file size.
THREAD SAFETY
This object is reference counted so use with caution in a threaded
environment.
!*/
public:
class file_not_found : public error {};
file (
);
/*!
ensures
- #*this has been properly initialized
- #name() == ""
- #full_name() == ""
- #size() == 0
- #*this does not represent any file
throws
- std::bad_alloc
!*/
file (
const std::string& name
);
/*!
ensures
- #*this has been properly initialized
- #*this represents the file given by name
Note that name can be a fully qualified path or just a path
relative to the current working directory. Also, any symbolic
links in name will be resolved.
throws
- std::bad_alloc
- file_not_found
This exception is thrown if the file can not be found or
accessed.
!*/
file (
const file& item
);
/*!
ensures
- #*this == item
throws
- std::bad_alloc
!*/
~file (
);
/*!
ensures
- all resources associated with *this have been released
!*/
const std::string& name (
) const;
/*!
ensures
- returns the name of the file. This is full_name() minus
the path to the file.
!*/
const std::string& full_name (
) const;
/*!
ensures
- returns the fully qualified name for the file represented by *this
!*/
uint64 size (
) const;
/*!
ensures
- returns the size of this file in bytes.
!*/
file& operator= (
const file& rhs
);
/*!
ensures
- #*this == rhs
!*/
bool operator == (
const file& rhs
) const;
/*!
ensures
- if (*this and rhs represent the same file) then
- returns true
- else
- returns false
!*/
bool operator < (
const file& item
) const;
/*!
ensures
- if (full_name() < item.full_name()) then
- returns true
- else
- returns false
!*/
void swap (
file& item
);
/*!
ensures
- swaps *this and item
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// directory object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class directory
{
/*!
WHAT THIS OBJECT REPRESENTS
This object represents a directory in a file system. It gives
the ability to traverse a directory tree.
Note that the directories . and .. are not returned by get_dirs()
THREAD SAFETY
This object is reference counted so use with caution in a threaded
environment.
!*/
public:
class dir_not_found : public error {};
class listing_error : public error {};
directory (
);
/*!
ensures
- #*this has been properly initialized
- #full_name() == ""
- #name() == ""
- #is_root() == true
- #*this does not represent any directory
throws
- std::bad_alloc
!*/
directory (
const std::string& name
);
/*!
ensures
- #*this has been properly initialized
- #*this represents the directory given by name.
Note that name can be a fully qualified path or just a path
relative to the current working directory. Also, any symbolic
links in name will be resolved.
throws
- std::bad_alloc
- dir_not_found
This exception is thrown if the directory can not be found or
accessed.
!*/
directory (
const directory& item
);
/*!
ensures
- #*this == item
throws
- std::bad_alloc
!*/
~directory (
);
/*!
ensures
- all resources associated with *this have been released
!*/
static char get_separator (
);
/*!
ensures
- returns the character used to separate directories and file names in a
path. (i.e. \ on windows and / in unix)
!*/
template <
typename queue_of_files
// Is an implementation of queue/queue_kernel_abstract.h with T set to file.
>
void get_files (
queue_of_files& files
) const;
/*!
ensures
- #files == A queue containing all the files present in this directory.
(Note that symbolic links will not have been resolved in the names
of the returned files.)
- #files.size() == the number of files in this directory
throws
- bad_alloc
If this exception is thrown then the call to get_files() has
no effect on *this and #files is unusable until files.clear()
is called and succeeds.
- listing_error
This exception is thrown if listing access has been denied to this
directory or if some error occurred that prevented us from successfully
getting the contents of this directory.
If this exception is thrown then the call to get_files() has
no effect on *this and #files.size()==0.
!*/
template <
typename queue_of_dirs
// Is an implementation of queue/queue_kernel_abstract.h with T set to directory.
>
void get_dirs (
queue_of_dirs& dirs
) const;
/*!
ensures
- #dirs == a queue containing all the directories present in this directory.
(note that symbolic links will not have been resolved in the names
of the returned directories.)
- #dirs.size() == the number of subdirectories in this directory
throws
- bad_alloc
If this exception is thrown then the call to get_files() has
no effect on *this and #files is unusable until files.clear()
is called and succeeds.
- listing_error
This exception is thrown if listing access has been denied to this
directory or if some error occurred that prevented us from successfully
getting the contents of this directory.
If this exception is thrown then the call to get_dirs() has
no effect on *this and #dirs.size()==0.
!*/
bool is_root (
) const;
/*!
ensures
- if (*this represents the root of this directory tree) then
- returns true
- else
- returns false
!*/
const directory get_parent (
) const;
/*!
ensures
- if (is_root()) then
- returns a copy of *this
- else
- returns the parent directory of *this
throws
- bad_alloc
If this exception is thrown then the call to get_parent() will
have no effect.
!*/
const std::string& name (
) const;
/*!
ensures
- if (is_root()) then
- returns ""
- else
- returns the name of the directory. This is full_name() minus
the path to the directory.
!*/
const std::string& full_name (
) const;
/*!
ensures
- returns the fully qualified directory name for *this
- if (is_root()) then
- the last character of #full_name() is get_separator()
- else
- the last character of #full_name() is NOT get_separator()
!*/
directory& operator= (
const directory& rhs
);
/*!
ensures
- #*this == rhs
!*/
bool operator == (
const directory& rhs
) const;
/*!
ensures
- if (*this and rhs represent the same directory) then
- returns true
- else
- returns false
!*/
bool operator < (
const directory& item
) const;
/*!
ensures
- if (full_name() < item.full_name()) then
- returns true
- else
- returns false
!*/
void swap (
directory& item
);
/*!
ensures
- swaps *this and item
!*/
};
// ----------------------------------------------------------------------------------------
inline void swap (
file& a,
file& b
) { a.swap(b); }
/*!
provides a global swap function for file objects
!*/
// ----------------------------------------------------------------------------------------
inline void swap (
directory& a,
directory& b
) { a.swap(b); }
/*!
provides a global swap function for directory objects
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_DIR_NAV_KERNEl_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIR_NAV_KERNEl_1_
#include "dir_nav_kernel_2.h"
#endif
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIR_NAV_KERNEl_2_
#include "dir_nav_kernel_1.h"
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment