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) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_
#ifdef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_
#include "../interfaces/map_pair.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include "../memory_manager/memory_manager_kernel_abstract.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = memory_manager<char>::kernel_1a,
typename compare = std::less<domain>
>
class binary_search_tree : public enumerable<map_pair<domain,range> >,
public asc_pair_remover<domain,range,compare>
{
/*!
REQUIREMENTS ON domain
domain must be comparable by compare where compare is a functor compatible with std::less and
domain is swappable by a global swap() and
domain must have a default constructor
REQUIREMENTS ON range
range is swappable by a global swap() and
range must have a default constructor
REQUIREMENTS ON mem_manager
must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA
swap(), count(), height(), and operator[] functions
do not invalidate pointers or references to internal data.
position_enumerator() invalidates pointers or references to
data returned by element() and only by element() (i.e. pointers and
references returned by operator[] are still valid).
All other functions have no such guarantees.
INITIAL VALUE
size() == 0
height() == 0
ENUMERATION ORDER
The enumerator will iterate over the domain (and each associated
range element) elements in ascending order according to the compare functor.
(i.e. the elements are enumerated in sorted order)
WHAT THIS OBJECT REPRESENTS
this object represents a data dictionary that is built on top of some
kind of binary search tree. It maps objects of type domain to objects
of type range.
NOTE:
definition of equivalent:
a is equivalent to b if
a < b == false and
b < a == false
!*/
public:
typedef domain domain_type;
typedef range range_type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
binary_search_tree(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
!*/
virtual ~binary_search_tree(
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
short height (
) const;
/*!
ensures
- returns the number of elements in the longest path from the root
of the tree to a leaf
!*/
unsigned long count (
const domain& d
) const;
/*!
ensures
- returns the number of elements in the domain of *this that are
equivalent to d
!*/
void add (
domain& d,
range& r
);
/*!
requires
- &d != &r (i.e. d and r cannot be the same variable)
ensures
- adds a mapping between d and r to *this
- if (count(d) == 0) then
- #*(*this)[d] == r
- else
- #(*this)[d] != 0
- #d and #r have initial values for their types
- #count(d) == count(d) + 1
- #at_start() == true
- #size() == size() + 1
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if add() throws then it has no effect
!*/
void remove (
const domain& d,
domain& d_copy,
range& r
);
/*!
requires
- (*this)[d] != 0
- &d != &r (i.e. d and r cannot be the same variable)
- &d != &d_copy (i.e. d and d_copy cannot be the same variable)
- &r != &d_copy (i.e. r and d_copy cannot be the same variable)
ensures
- some element in the domain of *this that is equivalent to d has
been removed and swapped into #d_copy. Additionally, its
associated range element has been removed and swapped into #r.
- #count(d) == count(d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void destroy (
const domain& d
);
/*!
requires
- (*this)[d] != 0
ensures
- an element in the domain of *this equivalent to d has been removed.
The element in the range of *this associated with d has also been
removed.
- #count(d) == count(d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void remove_last_in_order (
domain& d,
range& r
);
/*!
requires
- size() > 0
ensures
- the last/biggest (according to the compare functor) element in the domain of *this has
been removed and swapped into #d. The element in the range of *this
associated with #d has also been removed and swapped into #r.
- #count(#d) == count(#d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void remove_current_element (
domain& d,
range& r
);
/*!
requires
- current_element_valid() == true
ensures
- the current element given by element() has been removed and swapped into d and r.
- #d == element().key()
- #r == element().value()
- #count(#d) == count(#d) - 1
- #size() == size() - 1
- moves the enumerator to the next element. If element() was the last
element in enumeration order then #current_element_valid() == false
and #at_start() == false.
!*/
void position_enumerator (
const domain& d
) const;
/*!
ensures
- #at_start() == false
- if (count(d) > 0) then
- #element().key() == d
- else if (there are any items in the domain of *this that are bigger than
d according to the compare functor) then
- #element().key() == the smallest item in the domain of *this that is
bigger than d according to the compare functor.
- else
- #current_element_valid() == false
!*/
const range* operator[] (
const domain& d
) const;
/*!
ensures
- if (there is an element in the domain equivalent to d) then
- returns a pointer to an element in the range of *this that
is associated with an element in the domain of *this
equivalent to d.
- else
- returns 0
!*/
range* operator[] (
const domain& d
);
/*!
ensures
- if (there is an element in the domain equivalent to d) then
- returns a pointer to an element in the range of *this that
is associated with an element in the domain of *this
equivalent to d.
- else
- returns 0
!*/
void swap (
binary_search_tree& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
binary_search_tree(binary_search_tree&);
binary_search_tree& operator=(binary_search_tree&);
};
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
inline void swap (
binary_search_tree<domain,range,mem_manager,compare>& a,
binary_search_tree<domain,range,mem_manager,compare>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void deserialize (
binary_search_tree<domain,range,mem_manager,compare>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_BINARY_SEARCH_TREE_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_BINARY_SEARCH_TREE_KERNEl_C_
#define DLIB_BINARY_SEARCH_TREE_KERNEl_C_
#include "../interfaces/map_pair.h"
#include "binary_search_tree_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename bst_base
>
class binary_search_tree_kernel_c : public bst_base
{
typedef typename bst_base::domain_type domain;
typedef typename bst_base::range_type range;
public:
binary_search_tree_kernel_c () {}
void remove (
const domain& d,
domain& d_copy,
range& r
);
void destroy (
const domain& d
);
void add (
domain& d,
range& r
);
void remove_any (
domain& d,
range& r
);
const map_pair<domain,range>& element (
) const;
map_pair<domain,range>& element (
);
void remove_last_in_order (
domain& d,
range& r
);
void remove_current_element (
domain& d,
range& r
);
};
template <
typename bst_base
>
inline void swap (
binary_search_tree_kernel_c<bst_base>& a,
binary_search_tree_kernel_c<bst_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
add (
domain& d,
range& r
)
{
DLIB_CASSERT( reinterpret_cast<const void*>(&d) != reinterpret_cast<void*>(&r),
"\tvoid binary_search_tree::add"
<< "\n\tyou can't call add() and give the same object to both parameters."
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&r: " << &r
<< "\n\tsize(): " << this->size()
);
bst_base::add(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
destroy (
const domain& d
)
{
DLIB_CASSERT(operator[](d) != 0,
"\tvoid binary_search_tree::destroy"
<< "\n\tthe element must be in the tree for it to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
);
bst_base::destroy(d);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove (
const domain& d,
domain& d_copy,
range& r
)
{
DLIB_CASSERT(operator[](d) != 0 &&
(reinterpret_cast<const void*>(&d) != reinterpret_cast<void*>(&d_copy)) &&
(reinterpret_cast<const void*>(&d) != reinterpret_cast<void*>(&r)) &&
(reinterpret_cast<const void*>(&r) != reinterpret_cast<void*>(&d_copy)),
"\tvoid binary_search_tree::remove"
<< "\n\tthe element must be in the tree for it to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&d_copy: " << &d_copy
<< "\n\t&r: " << &r
);
bst_base::remove(d,d_copy,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_any(
domain& d,
range& r
)
{
DLIB_CASSERT(this->size() != 0 &&
(reinterpret_cast<const void*>(&d) != reinterpret_cast<void*>(&r)),
"\tvoid binary_search_tree::remove_any"
<< "\n\ttree must not be empty if something is going to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&r: " << &r
);
bst_base::remove_any(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
const map_pair<typename bst_base::domain_type,typename bst_base::range_type>& binary_search_tree_kernel_c<bst_base>::
element (
) const
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tconst map_pair<domain,range>& binary_search_tree::element() const"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
return bst_base::element();
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
map_pair<typename bst_base::domain_type,typename bst_base::range_type>& binary_search_tree_kernel_c<bst_base>::
element (
)
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tmap_pair<domain,range>& binary_search_tree::element()"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
return bst_base::element();
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_last_in_order (
domain& d,
range& r
)
{
DLIB_CASSERT(this->size() > 0,
"\tvoid binary_search_tree::remove_last_in_order()"
<< "\n\tyou can't remove an element if it doesn't exist"
<< "\n\tthis: " << this
);
bst_base::remove_last_in_order(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_current_element (
domain& d,
range& r
)
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tvoid binary_search_tree::remove_current_element()"
<< "\n\tyou can't remove the current element if it doesn't exist"
<< "\n\tthis: " << this
);
bst_base::remove_current_element(d,r);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_C_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAm_
#define DLIB_BIT_STREAm_
#include "bit_stream/bit_stream_kernel_1.h"
#include "bit_stream/bit_stream_kernel_c.h"
#include "bit_stream/bit_stream_multi_1.h"
#include "bit_stream/bit_stream_multi_c.h"
namespace dlib
{
class bit_stream
{
bit_stream() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef bit_stream_kernel_1
kernel_1a;
typedef bit_stream_kernel_c<kernel_1a >
kernel_1a_c;
//---------- extensions ------------
// multi_1 extend kernel_1a
typedef bit_stream_multi_1<kernel_1a>
multi_1a;
typedef bit_stream_multi_c<bit_stream_multi_1<kernel_1a_c> >
multi_1a_c;
};
}
#endif // DLIB_BIT_STREAm_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_KERNEL_1_CPp_
#define DLIB_BIT_STREAM_KERNEL_1_CPp_
#include "bit_stream_kernel_1.h"
#include "../algs.h"
#include <iostream>
namespace dlib
{
inline void swap (
bit_stream_kernel_1& a,
bit_stream_kernel_1& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
clear (
)
{
if (write_mode)
{
write_mode = false;
// flush output buffer
if (buffer_size > 0)
{
buffer <<= 8 - buffer_size;
osp->write(reinterpret_cast<char*>(&buffer),1);
}
}
else
read_mode = false;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
set_input_stream (
std::istream& is
)
{
isp = &is;
read_mode = true;
buffer_size = 0;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
set_output_stream (
std::ostream& os
)
{
osp = &os;
write_mode = true;
buffer_size = 0;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
close (
)
{
if (write_mode)
{
write_mode = false;
// flush output buffer
if (buffer_size > 0)
{
buffer <<= 8 - buffer_size;
osp->write(reinterpret_cast<char*>(&buffer),1);
}
}
else
read_mode = false;
}
// ----------------------------------------------------------------------------------------
bool bit_stream_kernel_1::
is_in_write_mode (
) const
{
return write_mode;
}
// ----------------------------------------------------------------------------------------
bool bit_stream_kernel_1::
is_in_read_mode (
) const
{
return read_mode;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
write (
int bit
)
{
// flush buffer if necessary
if (buffer_size == 8)
{
buffer <<= 8 - buffer_size;
if (osp->rdbuf()->sputn(reinterpret_cast<char*>(&buffer),1) == 0)
{
throw std::ios_base::failure("error occured in the bit_stream object");
}
buffer_size = 0;
}
++buffer_size;
buffer <<= 1;
buffer += static_cast<unsigned char>(bit);
}
// ----------------------------------------------------------------------------------------
bool bit_stream_kernel_1::
read (
int& bit
)
{
// get new byte if necessary
if (buffer_size == 0)
{
if (isp->rdbuf()->sgetn(reinterpret_cast<char*>(&buffer), 1) == 0)
{
// if we didn't read anything then return false
return false;
}
buffer_size = 8;
}
// put the most significant bit from buffer into bit
bit = static_cast<int>(buffer >> 7);
// shift out the bit that was just read
buffer <<= 1;
--buffer_size;
return true;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
swap (
bit_stream_kernel_1& item
)
{
std::istream* isp_temp = item.isp;
std::ostream* osp_temp = item.osp;
bool write_mode_temp = item.write_mode;
bool read_mode_temp = item.read_mode;
unsigned char buffer_temp = item.buffer;
unsigned short buffer_size_temp = item.buffer_size;
item.isp = isp;
item.osp = osp;
item.write_mode = write_mode;
item.read_mode = read_mode;
item.buffer = buffer;
item.buffer_size = buffer_size;
isp = isp_temp;
osp = osp_temp;
write_mode = write_mode_temp;
read_mode = read_mode_temp;
buffer = buffer_temp;
buffer_size = buffer_size_temp;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_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_BIT_STREAM_KERNEl_1_
#define DLIB_BIT_STREAM_KERNEl_1_
#include "bit_stream_kernel_abstract.h"
#include <iosfwd>
namespace dlib
{
class bit_stream_kernel_1
{
/*!
INITIAL VALUE
write_mode == false
read_mode == false
CONVENTION
write_mode == is_in_write_mode()
read_mode == is_in_read_mode()
if (write_mode)
{
osp == pointer to an ostream object
buffer == the low order bits of buffer are the bits to be
written
buffer_size == the number of low order bits in buffer that are
bits that should be written
the lowest order bit is the last bit entered by the user
}
if (read_mode)
{
isp == pointer to an istream object
buffer == the high order bits of buffer are the bits
waiting to be read by the user
buffer_size == the number of high order bits in buffer that
are bits that are waiting to be read
the highest order bit is the next bit to give to the user
}
!*/
public:
bit_stream_kernel_1 (
) :
write_mode(false),
read_mode(false)
{}
virtual ~bit_stream_kernel_1 (
)
{}
void clear (
);
void set_input_stream (
std::istream& is
);
void set_output_stream (
std::ostream& os
);
void close (
);
inline bool is_in_write_mode (
) const;
inline bool is_in_read_mode (
) const;
inline void write (
int bit
);
bool read (
int& bit
);
void swap (
bit_stream_kernel_1& item
);
private:
// member data
std::istream* isp;
std::ostream* osp;
bool write_mode;
bool read_mode;
unsigned char buffer;
unsigned short buffer_size;
// restricted functions
bit_stream_kernel_1(bit_stream_kernel_1&); // copy constructor
bit_stream_kernel_1& operator=(bit_stream_kernel_1&); // assignment operator
};
inline void swap (
bit_stream_kernel_1& a,
bit_stream_kernel_1& b
);
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "bit_stream_kernel_1.cpp"
#endif
#endif // DLIB_BIT_STREAM_KERNEl_1_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BIT_STREAM_KERNEl_ABSTRACT_
#ifdef DLIB_BIT_STREAM_KERNEl_ABSTRACT_
#include <iosfwd>
namespace dlib
{
class bit_stream
{
/*!
INITIAL VALUE
is_in_write_mode() == false
is_in_read_mode() == false
WHAT THIS OBJECT REPRESENTS
this object is a middle man between a user and the iostream classes.
it allows single bits to be read/written easily to/from
the iostream classes
BUFFERING:
This object will only read/write single bytes at a time from/to the
iostream objects. Any buffered bits still in the bit_stream object
when it is closed or destructed are lost if it is in read mode. If
it is in write mode then any remaining bits are guaranteed to be
written to the output stream by the time it is closed or destructed.
!*/
public:
bit_stream (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~bit_stream (
);
/*!
ensures
- all memory associated with *this has 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_input_stream (
std::istream& is
);
/*!
requires
- is_in_write_mode() == false
- is_in_read_mode() == false
- is is ready to give input
ensures
- #is_in_write_mode() == false
- #is_in_read_mode() == true
- #*this will now be reading from is
throws
- std::bad_alloc
!*/
void set_output_stream (
std::ostream& os
);
/*!
requires
- is_in_write_mode() == false
- is_in_read_mode() == false
- os is ready to take output
ensures
- #is_in_write_mode() == true
- #is_in_read_mode() == false
- #*this will now write to os
throws
- std::bad_alloc
!*/
void close (
);
/*!
requires
- is_in_write_mode() == true || is_in_read_mode() == true
ensures
- #is_in_write_mode() == false
- #is_in_read_mode() == false
!*/
bool is_in_write_mode (
) const;
/*!
ensures
- returns true if *this is associated with an output stream object
- returns false otherwise
!*/
bool is_in_read_mode (
) const;
/*!
ensures
- returns true if *this is associated with an input stream object
- returns false otherwise
!*/
void write (
int bit
);
/*!
requires
- is_in_write_mode() == true
- bit == 0 || bit == 1
ensures
- bit will be written to the ostream object associated with *this
throws
- std::ios_base::failure
if (there was a problem writing to the output stream) then
this exception will be thrown. #*this will be unusable until
clear() is called and succeeds
- any other exception
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
bool read (
int& bit
);
/*!
requires
- is_in_read_mode() == true
ensures
- the next bit has been read and placed into #bit
- returns true if the read was successful, else false
(ex. false if EOF has been reached)
throws
- any exception
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
void swap (
bit_stream& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
bit_stream(bit_stream&); // copy constructor
bit_stream& operator=(bit_stream&); // assignment operator
};
inline void swap (
bit_stream& a,
bit_stream& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_BIT_STREAM_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_BIT_STREAM_KERNEl_C_
#define DLIB_BIT_STREAM_KERNEl_C_
#include "bit_stream_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include <iosfwd>
namespace dlib
{
template <
typename bit_stream_base // implements bit_stream/bit_stream_kernel_abstract.h
>
class bit_stream_kernel_c : public bit_stream_base
{
public:
void set_input_stream (
std::istream& is
);
void set_output_stream (
std::ostream& os
);
void close (
);
void write (
int bit
);
bool read (
int& bit
);
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_kernel_c<bit_stream_base>& a,
bit_stream_kernel_c<bit_stream_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
set_input_stream (
std::istream& is
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == false ) && ( this->is_in_read_mode() == false ),
"\tvoid bit_stream::set_intput_stream"
<< "\n\tbit_stream must not be in write or read mode"
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::set_input_stream(is);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
set_output_stream (
std::ostream& os
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == false ) && ( this->is_in_read_mode() == false ),
"\tvoid bit_stream::set_output_stream"
<< "\n\tbit_stream must not be in write or read mode"
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::set_output_stream(os);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
close (
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == true ) || ( this->is_in_read_mode() == true ),
"\tvoid bit_stream::close"
<< "\n\tyou can't close a bit_stream that isn't open"
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::close();
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
write (
int bit
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == true ) && ( bit == 0 || bit == 1 ),
"\tvoid bit_stream::write"
<< "\n\tthe bit stream bust be in write mode and bit must be either 1 or 0"
<< "\n\tis_in_write_mode() == " << this->is_in_write_mode()
<< "\n\tbit == " << bit
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::write(bit);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
bool bit_stream_kernel_c<bit_stream_base>::
read (
int& bit
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_read_mode() == true ),
"\tbool bit_stream::read"
<< "\n\tyou can't read from a bit_stream that isn't in read mode"
<< "\n\tthis: " << this
);
// call the real function
return bit_stream_base::read(bit);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_KERNEl_C_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_MULTi_1_
#define DLIB_BIT_STREAM_MULTi_1_
#include "bit_stream_multi_abstract.h"
namespace dlib
{
template <
typename bit_stream_base
>
class bit_stream_multi_1 : public bit_stream_base
{
public:
void multi_write (
unsigned long data,
int num_to_write
);
int multi_read (
unsigned long& data,
int num_to_read
);
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_multi_1<bit_stream_base>& a,
bit_stream_multi_1<bit_stream_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_multi_1<bit_stream_base>::
multi_write (
unsigned long data,
int num_to_write
)
{
// move the first bit into the most significant position
data <<= 32 - num_to_write;
for (int i = 0; i < num_to_write; ++i)
{
// write the first bit from data
this->write(static_cast<char>(data >> 31));
// shift the next bit into position
data <<= 1;
}
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
int bit_stream_multi_1<bit_stream_base>::
multi_read (
unsigned long& data,
int num_to_read
)
{
int bit, i;
data = 0;
for (i = 0; i < num_to_read; ++i)
{
// get a bit
if (this->read(bit) == false)
break;
// shift data to make room for this new bit
data <<= 1;
// put bit into the least significant position in data
data += static_cast<unsigned long>(bit);
}
return i;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_MULTi_1_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BIT_STREAM_MULTi_ABSTRACT_
#ifdef DLIB_BIT_STREAM_MULTi_ABSTRACT_
#include "bit_stream_kernel_abstract.h"
namespace dlib
{
template <
typename bit_stream_base
>
class bit_stream_multi : public bit_stream_base
{
/*!
REQUIREMENTS ON BIT_STREAM_BASE
it is an implementation of bit_stream/bit_stream_kernel_abstract.h
WHAT THIS EXTENSION DOES FOR BIT_STREAM
this gives a bit_stream object the ability to read/write multible bits
at a time
!*/
public:
void multi_write (
unsigned long data,
int num_to_write
);
/*!
requires
- is_in_write_mode() == true
- 0 <= num_to_write <= 32
ensures
- num_to_write low order bits from data will be written to the ostream
- object associated with *this
example: if data is 10010 then the bits will be written in the
order 1,0,0,1,0
!*/
int multi_read (
unsigned long& data,
int num_to_read
);
/*!
requires
- is_in_read_mode() == true
- 0 <= num_to_read <= 32
ensures
- tries to read num_to_read bits into the low order end of #data
example: if the incoming bits were 10010 then data would end
up with 10010 as its low order bits
- all of the bits in #data not filled in by multi_read() are zero
- returns the number of bits actually read into #data
!*/
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_multi<bit_stream_base>& a,
bit_stream_multi<bit_stream_base>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_BIT_STREAM_MULTi_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_MULTi_C_
#define DLIB_BIT_STREAM_MULTi_C_
#include "bit_stream_multi_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename bit_stream_base // implements bit_stream/bit_stream_multi_abstract.h
>
class bit_stream_multi_c : public bit_stream_base
{
public:
void multi_write (
unsigned long data,
int num_to_write
);
int multi_read (
unsigned long& data,
int num_to_read
);
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_multi_c<bit_stream_base>& a,
bit_stream_multi_c<bit_stream_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_multi_c<bit_stream_base>::
multi_write (
unsigned long data,
int num_to_write
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (this->is_in_write_mode() == true) && (num_to_write >= 0 && num_to_write <=32),
"\tvoid bit_stream::write"
<< "\n\tthe bit stream bust be in write mode and"
<< "\n\tnum_to_write must be between 0 and 32 inclusive"
<< "\n\tnum_to_write == " << num_to_write
<< "\n\tis_in_write_mode() == " << this->is_in_write_mode()
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::multi_write(data,num_to_write);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
int bit_stream_multi_c<bit_stream_base>::
multi_read (
unsigned long& data,
int num_to_read
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_read_mode() == true && ( num_to_read >= 0 && num_to_read <=32 ) ),
"\tvoid bit_stream::read"
<< "\n\tyou can't read from a bit_stream that isn't in read mode and"
<< "\n\tnum_to_read must be between 0 and 32 inclusive"
<< "\n\tnum_to_read == " << num_to_read
<< "\n\tis_in_read_mode() == " << this->is_in_read_mode()
<< "\n\tthis: " << this
);
// call the real function
return bit_stream_base::multi_read(data,num_to_read);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_MULTi_C_
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BYTE_ORDEREr_
#define DLIB_BYTE_ORDEREr_
#include "byte_orderer/byte_orderer_kernel_1.h"
namespace dlib
{
class byte_orderer
{
byte_orderer() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef byte_orderer_kernel_1
kernel_1a;
};
}
#endif // DLIB_BYTE_ORDEREr_
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BYTE_ORDEREr_KERNEL_1_
#define DLIB_BYTE_ORDEREr_KERNEL_1_
#include "byte_orderer_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
class byte_orderer_kernel_1
{
/*!
INITIAL VALUE
- if (this machine is little endian) then
- little_endian == true
- else
- little_endian == false
CONVENTION
- host_is_big_endian() == !little_endian
- host_is_little_endian() == little_endian
- if (this machine is little endian) then
- little_endian == true
- else
- little_endian == false
!*/
public:
byte_orderer_kernel_1 (
)
{
// This will probably never be false but if it is then it means chars are not 8bits
// on this system. Which is a problem for this object.
COMPILE_TIME_ASSERT(sizeof(short) >= 2);
unsigned long temp = 1;
unsigned char* ptr = reinterpret_cast<unsigned char*>(&temp);
if (*ptr == 1)
little_endian = true;
else
little_endian = false;
}
virtual ~byte_orderer_kernel_1 (
){}
bool host_is_big_endian (
) const { return !little_endian; }
bool host_is_little_endian (
) const { return little_endian; }
template <
typename T
>
inline void host_to_network (
T& item
) const
{ if (little_endian) flip(item); }
template <
typename T
>
inline void network_to_host (
T& item
) const { if (little_endian) flip(item); }
template <
typename T
>
void host_to_big (
T& item
) const { if (little_endian) flip(item); }
template <
typename T
>
void big_to_host (
T& item
) const { if (little_endian) flip(item); }
template <
typename T
>
void host_to_little (
T& item
) const { if (!little_endian) flip(item); }
template <
typename T
>
void little_to_host (
T& item
) const { if (!little_endian) flip(item); }
private:
template <
typename T,
size_t size
>
inline void flip (
T (&array)[size]
) const
/*!
ensures
- flips the bytes in every element of this array
!*/
{
for (size_t i = 0; i < size; ++i)
{
flip(array[i]);
}
}
template <
typename T
>
inline void flip (
T& item
) const
/*!
ensures
- reverses the byte ordering in item
!*/
{
// this is just here to provide a compile time check that T is a POD.
// this checks *most* of the requrements for being a POD type.
// You should not be calling this function on non POD types!
union
{
int a;
T value;
} temp;
// If you are getting this as an error then you are probably using
// this object wrong. If you think you aren't then send me (Davis) an
// email and I'll either set you straight or change/remove this check so
// your stuff works :)
COMPILE_TIME_ASSERT(sizeof(T) <= sizeof(long double));
// If you are getting a compile error on this line then it means T is
// a pointer type. It doesn't make any sense to byte swap pointers
// since they have no meaning outside the context of their own process.
// So you probably just forgot to dereference that pointer before passing
// it to this function :)
COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false);
const size_t size = sizeof(T);
unsigned char* const ptr = reinterpret_cast<unsigned char*>(&item);
unsigned char* const ptr_temp = reinterpret_cast<unsigned char*>(&temp.value);
for (size_t i = 0; i < size; ++i)
ptr_temp[size-i-1] = ptr[i];
item = temp.value;
}
bool little_endian;
// restricted functions
byte_orderer_kernel_1(const byte_orderer_kernel_1&); // copy constructor
byte_orderer_kernel_1& operator=(const byte_orderer_kernel_1&); // assignment operator
};
// make flip not do anything at all for chars
template <> inline void byte_orderer_kernel_1::flip<char> ( char& ) const {}
template <> inline void byte_orderer_kernel_1::flip<unsigned char> ( unsigned char& ) const {}
template <> inline void byte_orderer_kernel_1::flip<signed char> ( signed char& ) const {}
}
#endif // DLIB_BYTE_ORDEREr_KERNEL_1_
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BYTE_ORDEREr_ABSTRACT_
#ifdef DLIB_BYTE_ORDEREr_ABSTRACT_
#include "../algs.h"
namespace dlib
{
class byte_orderer
{
/*!
INITIAL VALUE
This object has no state.
WHAT THIS OBJECT REPRESENTS
This object simply provides a mechanism to convert data from a
host machine's own byte ordering to big or little endian and to
also do the reverse.
It also provides a pair of functions to convert to/from network byte
order where network byte order is big endian byte order. This pair of
functions does the exact same thing as the host_to_big() and big_to_host()
functions and is provided simply so that client code can use the most
self documenting name appropriate.
Also note that this object is capable of correctly flipping the contents
of arrays when the arrays are declared on the stack. e.g. You can
say things like:
int array[10];
bo.host_to_network(array);
!*/
public:
byte_orderer (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~byte_orderer (
);
/*!
ensures
- any resources associated with *this have been released
!*/
bool host_is_big_endian (
) const;
/*!
ensures
- if (the host computer is a big endian machine) then
- returns true
- else
- returns false
!*/
bool host_is_little_endian (
) const;
/*!
ensures
- if (the host computer is a little endian machine) then
- returns true
- else
- returns false
!*/
template <
typename T
>
void host_to_network (
T& item
) const;
/*!
ensures
- #item == the value of item converted from host byte order
to network byte order.
!*/
template <
typename T
>
void network_to_host (
T& item
) const;
/*!
ensures
- #item == the value of item converted from network byte order
to host byte order.
!*/
template <
typename T
>
void host_to_big (
T& item
) const;
/*!
ensures
- #item == the value of item converted from host byte order
to big endian byte order.
!*/
template <
typename T
>
void big_to_host (
T& item
) const;
/*!
ensures
- #item == the value of item converted from big endian byte order
to host byte order.
!*/
template <
typename T
>
void host_to_little (
T& item
) const;
/*!
ensures
- #item == the value of item converted from host byte order
to little endian byte order.
!*/
template <
typename T
>
void little_to_host (
T& item
) const;
/*!
ensures
- #item == the value of item converted from little endian byte order
to host byte order.
!*/
private:
// restricted functions
byte_orderer(const byte_orderer&); // copy constructor
byte_orderer& operator=(const byte_orderer&); // assignment operator
};
}
#endif // DLIB_BYTE_ORDEREr_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_CMD_LINE_PARSEr_
#define DLIB_CMD_LINE_PARSEr_
#include "cmd_line_parser/cmd_line_parser_kernel_1.h"
#include "cmd_line_parser/cmd_line_parser_kernel_c.h"
#include "cmd_line_parser/cmd_line_parser_print_1.h"
#include "cmd_line_parser/cmd_line_parser_check_1.h"
#include "cmd_line_parser/cmd_line_parser_check_c.h"
#include <string>
#include "map.h"
#include "sequence.h"
namespace dlib
{
template <
typename charT
>
class cmd_line_parser
{
cmd_line_parser() {}
typedef typename sequence<std::basic_string<charT> >::kernel_2a sequence_2a;
typedef typename sequence<std::basic_string<charT>*>::kernel_2a psequence_2a;
typedef typename map<std::basic_string<charT>,void*>::kernel_1a map_1a_string;
public:
//----------- kernels ---------------
// kernel_1a
typedef cmd_line_parser_kernel_1<charT,map_1a_string,sequence_2a,psequence_2a>
kernel_1a;
typedef cmd_line_parser_kernel_c<kernel_1a>
kernel_1a_c;
//----------- extensions ---------------
// print_1 extend kernel_1a
typedef cmd_line_parser_print_1<kernel_1a>
print_1a;
typedef cmd_line_parser_print_1<kernel_1a_c>
print_1a_c;
// check_1 extend print_1a
typedef cmd_line_parser_check_1<print_1a>
check_1a;
typedef cmd_line_parser_check_c<cmd_line_parser_check_1<print_1a_c> >
check_1a_c;
};
}
#endif // DLIB_CMD_LINE_PARSEr_
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CMD_LINE_PARSER_CHECk_1_
#define DLIB_CMD_LINE_PARSER_CHECk_1_
#include "cmd_line_parser_kernel_abstract.h"
#include <sstream>
#include <string>
#include "../string.h"
#include <vector>
namespace dlib
{
template <
typename clp_base
>
class cmd_line_parser_check_1 : public clp_base
{
/*!
This extension doesn't add any state.
!*/
public:
typedef typename clp_base::char_type char_type;
typedef typename clp_base::string_type string_type;
// ------------------------------------------------------------------------------------
class cmd_line_check_error : public dlib::error
{
friend class cmd_line_parser_check_1;
cmd_line_check_error(
error_type t,
const string_type& opt_,
const string_type& arg_
) :
dlib::error(t),
opt(opt_),
arg(arg_)
{ set_info_string(); }
cmd_line_check_error(
error_type t,
const string_type& opt_,
const string_type& opt2_,
int // this is just to make this constructor different from the one above
) :
dlib::error(t),
opt(opt_),
opt2(opt2_)
{ set_info_string(); }
cmd_line_check_error (
error_type t,
const string_type& opt_,
const std::vector<string_type>& vect
) :
dlib::error(t),
opt(opt_),
required_opts(vect)
{ set_info_string(); }
cmd_line_check_error(
error_type t,
const string_type& opt_
) :
dlib::error(t),
opt(opt_)
{ set_info_string(); }
~cmd_line_check_error() throw() {}
void set_info_string (
)
{
std::ostringstream sout;
switch (type)
{
case EINVALID_OPTION_ARG:
sout << "Command line error: '" << narrow(arg) << "' is not a valid argument to "
<< "the '" << narrow(opt) << "' option.";
break;
case EMISSING_REQUIRED_OPTION:
if (required_opts.size() == 1)
{
sout << "Command line error: The '" << narrow(opt) << "' option requires the presence of "
<< "the '" << required_opts[0] << "' option.";
}
else
{
sout << "Command line error: The '" << narrow(opt) << "' option requires the presence of "
<< "one of the following options: ";
for (unsigned long i = 0; i < required_opts.size(); ++i)
{
if (i == required_opts.size()-2)
sout << "'" << required_opts[i] << "' or ";
else if (i == required_opts.size()-1)
sout << "'" << required_opts[i] << "'.";
else
sout << "'" << required_opts[i] << "', ";
}
}
break;
case EINCOMPATIBLE_OPTIONS:
sout << "Command line error: The '" << narrow(opt) << "' and '" << narrow(opt2)
<< "' options can not be given together on the command line.";
break;
case EMULTIPLE_OCCURANCES:
sout << "Command line error: The '" << narrow(opt) << "' option can only "
<< "be given on the command line once.";
break;
default:
sout << "Command line error.";
break;
}
const_cast<std::string&>(info) = wrap_string(sout.str(),0,0);
}
public:
const string_type opt;
const string_type opt2;
const string_type arg;
const std::vector<string_type> required_opts;
};
// ------------------------------------------------------------------------------------
template <
typename T
>
void check_option_arg_type (
const string_type& option_name
) const;
template <
typename T
>
void check_option_arg_range (
const string_type& option_name,
const T& first,
const T& last
) const;
template <
typename T,
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const T (&arg_set)[length]
) const;
template <
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const char_type* (&arg_set)[length]
) const;
template <
size_t length
>
void check_incompatible_options (
const char_type* (&option_set)[length]
) const;
template <
size_t length
>
void check_one_time_options (
const char_type* (&option_set)[length]
) const;
void check_incompatible_options (
const string_type& option_name1,
const string_type& option_name2
) const;
template <
size_t length
>
void check_sub_options (
const string_type& parent_option,
const char_type* (&sub_option_set)[length]
) const;
template <
size_t length
>
void check_sub_options (
const char_type* (&parent_option_set)[length],
const string_type& sub_option
) const;
template <
size_t parent_length,
size_t sub_length
>
void check_sub_options (
const char_type* (&parent_option_set)[parent_length],
const char_type* (&sub_option_set)[sub_length]
) const;
};
template <
typename clp_base
>
inline void swap (
cmd_line_parser_check_1<clp_base>& a,
cmd_line_parser_check_1<clp_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template <typename T>
void cmd_line_parser_check_1<clp_base>::
check_option_arg_type (
const string_type& option_name
) const
{
try
{
const typename clp_base::option_type& opt = option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
string_cast<T>(opt.argument(i,j));
}
}
}
catch (string_cast_error& e)
{
throw cmd_line_check_error(EINVALID_OPTION_ARG,option_name,e.info);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template <typename T>
void cmd_line_parser_check_1<clp_base>::
check_option_arg_range (
const string_type& option_name,
const T& first,
const T& last
) const
{
try
{
const typename clp_base::option_type& opt = option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
T temp(string_cast<T>(opt.argument(i,j)));
if (temp < first || last < temp)
{
throw cmd_line_check_error(
EINVALID_OPTION_ARG,
option_name,
opt.argument(i,j)
);
}
}
}
}
catch (string_cast_error& e)
{
throw cmd_line_check_error(EINVALID_OPTION_ARG,option_name,e.info);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < typename T, size_t length >
void cmd_line_parser_check_1<clp_base>::
check_option_arg_range (
const string_type& option_name,
const T (&arg_set)[length]
) const
{
try
{
const typename clp_base::option_type& opt = option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
T temp(string_cast<T>(opt.argument(i,j)));
size_t k = 0;
for (; k < length; ++k)
{
if (arg_set[k] == temp)
break;
}
if (k == length)
{
throw cmd_line_check_error(
EINVALID_OPTION_ARG,
option_name,
opt.argument(i,j)
);
}
}
}
}
catch (string_cast_error& e)
{
throw cmd_line_check_error(EINVALID_OPTION_ARG,option_name,e.info);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_option_arg_range (
const string_type& option_name,
const char_type* (&arg_set)[length]
) const
{
const typename clp_base::option_type& opt = option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
size_t k = 0;
for (; k < length; ++k)
{
if (arg_set[k] == opt.argument(i,j))
break;
}
if (k == length)
{
throw cmd_line_check_error(
EINVALID_OPTION_ARG,
option_name,
opt.argument(i,j)
);
}
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_incompatible_options (
const char_type* (&option_set)[length]
) const
{
for (size_t i = 0; i < length; ++i)
{
for (size_t j = i+1; j < length; ++j)
{
if (option(option_set[i]).count() > 0 &&
option(option_set[j]).count() > 0 )
{
throw cmd_line_check_error(
EINCOMPATIBLE_OPTIONS,
option_set[i],
option_set[j],
0 // this argument has no meaning and is only here to make this
// call different from the other constructor
);
}
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
void cmd_line_parser_check_1<clp_base>::
check_incompatible_options (
const string_type& option_name1,
const string_type& option_name2
) const
{
if (option(option_name1).count() > 0 &&
option(option_name2).count() > 0 )
{
throw cmd_line_check_error(
EINCOMPATIBLE_OPTIONS,
option_name1,
option_name2,
0 // this argument has no meaning and is only here to make this
// call different from the other constructor
);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_sub_options (
const string_type& parent_option,
const char_type* (&sub_option_set)[length]
) const
{
if (option(parent_option).count() == 0)
{
size_t i = 0;
for (; i < length; ++i)
{
if (option(sub_option_set[i]).count() > 0)
break;
}
if (i != length)
{
std::vector<string_type> vect;
vect.resize(1);
vect[0] = parent_option;
throw cmd_line_check_error( EMISSING_REQUIRED_OPTION, sub_option_set[i], vect);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_sub_options (
const char_type* (&parent_option_set)[length],
const string_type& sub_option
) const
{
// first check if the sub_option is present
if (option(sub_option).count() > 0)
{
// now check if any of the parents are present
bool parents_present = false;
for (size_t i = 0; i < length; ++i)
{
if (option(parent_option_set[i]).count() > 0)
{
parents_present = true;
break;
}
}
if (!parents_present)
{
std::vector<string_type> vect(parent_option_set, parent_option_set+length);
throw cmd_line_check_error( EMISSING_REQUIRED_OPTION, sub_option, vect);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t parent_length, size_t sub_length >
void cmd_line_parser_check_1<clp_base>::
check_sub_options (
const char_type* (&parent_option_set)[parent_length],
const char_type* (&sub_option_set)[sub_length]
) const
{
// first check if any of the parent options are present
bool parents_present = false;
for (size_t i = 0; i < parent_length; ++i)
{
if (option(parent_option_set[i]).count() > 0)
{
parents_present = true;
break;
}
}
if (!parents_present)
{
// none of these sub options should be present
size_t i = 0;
for (; i < sub_length; ++i)
{
if (option(sub_option_set[i]).count() > 0)
break;
}
if (i != sub_length)
{
std::vector<string_type> vect(parent_option_set, parent_option_set+parent_length);
throw cmd_line_check_error( EMISSING_REQUIRED_OPTION, sub_option_set[i], vect);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_one_time_options (
const char_type* (&option_set)[length]
) const
{
size_t i = 0;
for (; i < length; ++i)
{
if (option(option_set[i]).count() > 1)
break;
}
if (i != length)
{
throw cmd_line_check_error(
EMULTIPLE_OCCURANCES,
option_set[i]
);
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CMD_LINE_PARSER_CHECk_1_
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_CMD_LINE_PARSER_CHECk_ABSTRACT_
#ifdef DLIB_CMD_LINE_PARSER_CHECk_ABSTRACT_
#include "cmd_line_parser_kernel_abstract.h"
#include <vector>
namespace dlib
{
template <
typename clp_base
>
class cmd_line_parser_check : public clp_base
{
/*!
REQUIREMENTS ON CLP_BASE
clp_base is an implementation of cmd_line_parser/cmd_line_parser_kernel_abstract.h
POINTERS AND REFERENCES TO INTERNAL DATA
None of the functions added by this extension will invalidate pointers
or references to internal data.
WHAT THIS EXTENSION DOES FOR CMD_LINE_PARSER
This gives a cmd_line_parser object the ability to easily perform various
kinds of validation on the command line input.
!*/
public:
typedef typename clp_base::char_type char_type;
typedef typename clp_base::string_type string_type;
// exception class
class cmd_line_check_error : public dlib::error
{
public:
const string_type opt;
const string_type opt2;
const string_type arg;
const std::vector<string_type> required_opts;
};
template <
typename T
>
void check_option_arg_type (
const string_type& option_name
) const;
/*!
requires
- parsed_line() == true
- option_is_defined(option_name) == true
- T is not a pointer type
ensures
- all the arguments for the given option are convertable
by string_cast<T>() to an object of type T.
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EINVALID_OPTION_ARG
- opt == option_name
- arg == the text of the offending argument
!*/
template <
typename T
>
void check_option_arg_range (
const string_type& option_name,
const T& first,
const T& last
) const;
/*!
requires
- parsed_line() == true
- option_is_defined(option_name) == true
- first <= last
- T is not a pointer type
ensures
- all the arguments for the given option are convertable
by string_cast<T>() to an object of type T and the resuting value is
in the range first to last inclusive.
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EINVALID_OPTION_ARG
- opt == option_name
- arg == the text of the offending argument
!*/
template <
typename T,
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const T (&arg_set)[length]
) const;
/*!
requires
- parsed_line() == true
- option_is_defined(option_name) == true
- T is not a pointer type
ensures
- for each argument to the given option:
- this argument is convertable by string_cast<T>() to an object of
type T and the resulting value is equal to some string in the
arg_set array.
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EINVALID_OPTION_ARG
- opt == option_name
- arg == the text of the offending argument
!*/
template <
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const char_type* (&arg_set)[length]
) const;
/*!
requires
- parsed_line() == true
- option_is_defined(option_name) == true
ensures
- for each argument to the given option:
- there is a string in the arg_set array that is equal to this argument.
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EINVALID_OPTION_ARG
- opt == option_name
- arg == the text of the offending argument
!*/
template <
size_t length
>
void check_one_time_options (
const char_type* (&option_set)[length]
) const;
/*!
requires
- parsed_line() == true
- for all valid i:
- option_is_defined(option_set[i]) == true
ensures
- all the options in the option_set array occur at most once on the
command line.
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EMULTIPLE_OCCURANCES
- opt == the option that occurred more than once on the command line.
!*/
void check_incompatible_options (
const string_type& option_name1,
const string_type& option_name2
) const;
/*!
requires
- parsed_line() == true
- option_is_defined(option_name1) == true
- option_is_defined(option_name2) == true
ensures
- option(option_name1).count() == 0 || option(option_name2).count() == 0
(i.e. at most, only one of the options is currently present)
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EINCOMPATIBLE_OPTIONS
- opt == option_name1
- opt2 == option_name2
!*/
template <
size_t length
>
void check_incompatible_options (
const char_type* (&option_set)[length]
) const;
/*!
requires
- parsed_line() == true
- for all valid i:
- option_is_defined(option_set[i]) == true
ensures
- At most only one of the options in the array option_set has a count()
greater than 0. (i.e. at most, only one of the options is currently present)
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EINCOMPATIBLE_OPTIONS
- opt == One of the incompatible options found.
- opt2 == The next incompatible option found.
!*/
template <
size_t length
>
void check_sub_options (
const char_type* (&parent_option_set)[length],
const string_type& sub_option
) const;
/*!
requires
- parsed_line() == true
- option_is_defined(sub_option) == true
- for all valid i:
- option_is_defined(parent_option_set[i] == true
ensures
- if (option(sub_option).count() > 0) then
- At least one of the options in the array parent_option_set has a count()
greater than 0. (i.e. at least one of the options in parent_option_set
is currently present)
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EMISSING_REQUIRED_OPTION
- opt == the first option from the sub_option that is present.
- required_opts == a vector containing everything from parent_option_set.
!*/
template <
size_t length
>
void check_sub_options (
const string_type& parent_option,
const char_type* (&sub_option_set)[length]
) const;
/*!
requires
- parsed_line() == true
- option_is_defined(parent_option) == true
- for all valid i:
- option_is_defined(sub_option_set[i]) == true
ensures
- if (option(parent_option).count() == 0) then
- for all valid i:
- option(sub_option_set[i]).count() == 0
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EMISSING_REQUIRED_OPTION
- opt == the first option from the sub_option_set that is present.
- required_opts == a vector that contains only parent_option.
!*/
template <
size_t parent_length,
size_t sub_length
>
void check_sub_options (
const char_type* (&parent_option_set)[parent_length],
const char_type* (&sub_option_set)[sub_length]
) const;
/*!
requires
- parsed_line() == true
- for all valid i:
- option_is_defined(parent_option_set[i] == true
- for all valid j:
- option_is_defined(sub_option_set[j]) == true
ensures
- for all valid j:
- if (option(sub_option_set[j]).count() > 0) then
- At least one of the options in the array parent_option_set has a count()
greater than 0. (i.e. at least one of the options in parent_option_set
is currently present)
throws
- std::bad_alloc
- cmd_line_check_error
This exception is thrown if the ensures clause could not be satisfied.
The exception's members will be set as follows:
- type == EMISSING_REQUIRED_OPTION
- opt == the first option from the sub_option_set that is present.
- required_opts == a vector containing everything from parent_option_set.
!*/
};
template <
template clp_base
>
inline void swap (
cmd_line_parser_check<clp_base>& a,
cmd_line_parser_check<clp_base>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_CMD_LINE_PARSER_CHECk_ABSTRACT_
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CMD_LINE_PARSER_CHECk_C_
#define DLIB_CMD_LINE_PARSER_CHECk_C_
#include "cmd_line_parser_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include <string>
#include "../interfaces/cmd_line_parser_option.h"
#include "../string.h"
namespace dlib
{
template <
typename clp_check
>
class cmd_line_parser_check_c : public clp_check
{
public:
typedef typename clp_check::char_type char_type;
typedef typename clp_check::string_type string_type;
template <
typename T
>
void check_option_arg_type (
const string_type& option_name
) const;
template <
typename T
>
void check_option_arg_range (
const string_type& option_name,
const T& first,
const T& last
) const;
template <
typename T,
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const T (&arg_set)[length]
) const;
template <
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const char_type* (&arg_set)[length]
) const;
template <
size_t length
>
void check_incompatible_options (
const char_type* (&option_set)[length]
) const;
template <
size_t length
>
void check_one_time_options (
const char_type* (&option_set)[length]
) const;
void check_incompatible_options (
const string_type& option_name1,
const string_type& option_name2
) const;
template <
size_t length
>
void check_sub_options (
const string_type& parent_option,
const char_type* (&sub_option_set)[length]
) const;
template <
size_t length
>
void check_sub_options (
const char_type* (&parent_option_set)[length],
const string_type& sub_option
) const;
template <
size_t parent_length,
size_t sub_length
>
void check_sub_options (
const char_type* (&parent_option_set)[parent_length],
const char_type* (&sub_option_set)[sub_length]
) const;
};
template <
typename clp_check
>
inline void swap (
cmd_line_parser_check_c<clp_check>& a,
cmd_line_parser_check_c<clp_check>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template <typename T>
void cmd_line_parser_check_c<clp_check>::
check_option_arg_type (
const string_type& option_name
) const
{
COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false);
// make sure requires clause is not broken
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name),
"\tvoid cmd_line_parser_check::check_option_arg_type()"
<< "\n\tYou must have already parsed the command line and option_name must be valid."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\toption_name: " << option_name
);
clp_check::template check_option_arg_type<T>(option_name);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template <typename T>
void cmd_line_parser_check_c<clp_check>::
check_option_arg_range (
const string_type& option_name,
const T& first,
const T& last
) const
{
COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false);
// make sure requires clause is not broken
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name) &&
first <= last,
"\tvoid cmd_line_parser_check::check_option_arg_range()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\toption_name: " << option_name
<< "\n\tfirst: " << first
<< "\n\tlast: " << last
);
clp_check::check_option_arg_range(option_name,first,last);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template < typename T, size_t length >
void cmd_line_parser_check_c<clp_check>::
check_option_arg_range (
const string_type& option_name,
const T (&arg_set)[length]
) const
{
COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false);
// make sure requires clause is not broken
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name),
"\tvoid cmd_line_parser_check::check_option_arg_range()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\toption_name: " << option_name
);
clp_check::check_option_arg_range(option_name,arg_set);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template < size_t length >
void cmd_line_parser_check_c<clp_check>::
check_option_arg_range (
const string_type& option_name,
const char_type* (&arg_set)[length]
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name),
"\tvoid cmd_line_parser_check::check_option_arg_range()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\toption_name: " << option_name
);
clp_check::check_option_arg_range(option_name,arg_set);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template < size_t length >
void cmd_line_parser_check_c<clp_check>::
check_incompatible_options (
const char_type* (&option_set)[length]
) const
{
// make sure requires clause is not broken
for (size_t i = 0; i < length; ++i)
{
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_set[i]),
"\tvoid cmd_line_parser_check::check_incompatible_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(option_set[i]): " << ((this->option_is_defined(option_set[i]))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\toption_set[i]: " << option_set[i]
<< "\n\ti: " << static_cast<unsigned long>(i)
);
}
clp_check::check_incompatible_options(option_set);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
void cmd_line_parser_check_c<clp_check>::
check_incompatible_options (
const string_type& option_name1,
const string_type& option_name2
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name1) &&
this->option_is_defined(option_name2),
"\tvoid cmd_line_parser_check::check_incompatible_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(option_name1): " << ((this->option_is_defined(option_name1))?"true":"false")
<< "\n\toption_is_defined(option_name2): " << ((this->option_is_defined(option_name2))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\toption_name1: " << option_name1
<< "\n\toption_name2: " << option_name2
);
clp_check::check_incompatible_options(option_name1,option_name2);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template < size_t length >
void cmd_line_parser_check_c<clp_check>::
check_sub_options (
const string_type& parent_option,
const char_type* (&sub_option_set)[length]
) const
{
// make sure requires clause is not broken
for (size_t i = 0; i < length; ++i)
{
DLIB_CASSERT( this->option_is_defined(sub_option_set[i]),
"\tvoid cmd_line_parser_check::check_sub_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(sub_option_set[i]): "
<< ((this->option_is_defined(sub_option_set[i]))?"true":"false")
<< "\n\tsub_option_set[i]: " << sub_option_set[i]
<< "\n\ti: " << static_cast<unsigned long>(i)
);
}
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(parent_option),
"\tvoid cmd_line_parser_check::check_sub_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(parent_option): " << ((this->option_is_defined(parent_option))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\tparent_option: " << parent_option
);
clp_check::check_sub_options(parent_option,sub_option_set);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template < size_t length >
void cmd_line_parser_check_c<clp_check>::
check_sub_options (
const char_type* (&parent_option_set)[length],
const string_type& sub_option
) const
{
// make sure requires clause is not broken
for (size_t i = 0; i < length; ++i)
{
DLIB_CASSERT( this->option_is_defined(parent_option_set[i]),
"\tvoid cmd_line_parser_check::check_sub_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(parent_option_set[i]): "
<< ((this->option_is_defined(parent_option_set[i]))?"true":"false")
<< "\n\tparent_option_set[i]: " << parent_option_set[i]
<< "\n\ti: " << static_cast<unsigned long>(i)
);
}
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(sub_option),
"\tvoid cmd_line_parser_check::check_sub_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(sub_option): " << ((this->option_is_defined(sub_option))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\tsub_option: " << sub_option
);
clp_check::check_sub_options(parent_option_set,sub_option);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template < size_t parent_length, size_t sub_length >
void cmd_line_parser_check_c<clp_check>::
check_sub_options (
const char_type* (&parent_option_set)[parent_length],
const char_type* (&sub_option_set)[sub_length]
) const
{
// make sure requires clause is not broken
for (size_t i = 0; i < sub_length; ++i)
{
DLIB_CASSERT( this->option_is_defined(sub_option_set[i]),
"\tvoid cmd_line_parser_check::check_sub_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(sub_option_set[i]): "
<< ((this->option_is_defined(sub_option_set[i]))?"true":"false")
<< "\n\tsub_option_set[i]: " << sub_option_set[i]
<< "\n\ti: " << static_cast<unsigned long>(i)
);
}
for (size_t i = 0; i < parent_length; ++i)
{
DLIB_CASSERT( this->option_is_defined(parent_option_set[i]),
"\tvoid cmd_line_parser_check::check_parent_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(parent_option_set[i]): "
<< ((this->option_is_defined(parent_option_set[i]))?"true":"false")
<< "\n\tparent_option_set[i]: " << parent_option_set[i]
<< "\n\ti: " << static_cast<unsigned long>(i)
);
}
DLIB_CASSERT( this->parsed_line() == true ,
"\tvoid cmd_line_parser_check::check_sub_options()"
<< "\n\tYou must have parsed the command line before you call this function."
<< "\n\tthis: " << this
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
);
clp_check::check_sub_options(parent_option_set,sub_option_set);
}
// ----------------------------------------------------------------------------------------
template <typename clp_check>
template < size_t length >
void cmd_line_parser_check_c<clp_check>::
check_one_time_options (
const char_type* (&option_set)[length]
) const
{
// make sure requires clause is not broken
for (size_t i = 0; i < length; ++i)
{
DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_set[i]),
"\tvoid cmd_line_parser_check::check_one_time_options()"
<< "\n\tSee the requires clause for this function."
<< "\n\tthis: " << this
<< "\n\toption_is_defined(option_set[i]): " << ((this->option_is_defined(option_set[i]))?"true":"false")
<< "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false")
<< "\n\toption_set[i]: " << option_set[i]
<< "\n\ti: " << static_cast<unsigned long>(i)
);
}
clp_check::check_one_time_options(option_set);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CMD_LINE_PARSER_CHECk_C_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CMD_LINE_PARSER_KERNEl_1_
#define DLIB_CMD_LINE_PARSER_KERNEl_1_
#include "../algs.h"
#include <string>
#include <sstream>
#include "../interfaces/enumerable.h"
#include "../interfaces/cmd_line_parser_option.h"
#include "../assert.h"
#include "../string.h"
namespace dlib
{
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
class cmd_line_parser_kernel_1 : public enumerable<cmd_line_parser_option<charT> >
{
/*!
REQUIREMENTS ON map
is an implementation of map/map_kernel_abstract.h
is instantiated to map items of type std::basic_string<charT> to void*
REQUIREMENTS ON sequence
is an implementation of sequence/sequence_kernel_abstract.h and
is instantiated with std::basic_string<charT>
REQUIREMENTS ON sequence2
is an implementation of sequence/sequence_kernel_abstract.h and
is instantiated with std::basic_string<charT>*
INITIAL VALUE
options.size() == 0
argv.size() == 0
have_parsed_line == false
CONVENTION
have_parsed_line == parsed_line()
argv[index] == operator[](index)
argv.size() == number_of_arguments()
*((option_t*)options[name]) == option(name)
options.is_in_domain(name) == option_is_defined(name)
!*/
public:
typedef charT char_type;
typedef std::basic_string<charT> string_type;
typedef cmd_line_parser_option<charT> option_type;
// exception class
class cmd_line_parse_error : public dlib::error
{
void set_info_string (
)
{
std::ostringstream sout;
switch (type)
{
case EINVALID_OPTION:
sout << "Command line error: '" << narrow(item) << "' is not a valid option.";
break;
case ETOO_FEW_ARGS:
if (num > 1)
{
sout << "Command line error: The '" << narrow(item) << "' option requires " << num
<< " arguments.";
}
else
{
sout << "Command line error: The '" << narrow(item) << "' option requires " << num
<< " argument.";
}
break;
case ETOO_MANY_ARGS:
sout << "Command line error: The '" << narrow(item) << "' option does not take any arguments.\n";
break;
default:
sout << "Command line error.";
break;
}
const_cast<std::string&>(info) = wrap_string(sout.str(),0,0);
}
public:
cmd_line_parse_error(
error_type t,
const std::basic_string<charT>& _item
) :
dlib::error(t),
item(_item),
num(0)
{ set_info_string();}
cmd_line_parse_error(
error_type t,
const std::basic_string<charT>& _item,
unsigned long _num
) :
dlib::error(t),
item(_item),
num(_num)
{ set_info_string();}
cmd_line_parse_error(
) :
dlib::error(),
num(0)
{ set_info_string();}
~cmd_line_parse_error() throw() {}
const std::basic_string<charT> item;
const unsigned long num;
};
private:
class option_t : public cmd_line_parser_option<charT>
{
/*!
INITIAL VALUE
options.size() == 0
CONVENTION
name_ == name()
description_ == description()
number_of_arguments_ == number_of_arguments()
options[index] == operator[](index)
num_present == count()
!*/
friend class cmd_line_parser_kernel_1<charT,map,sequence,sequence2>;
public:
const std::basic_string<charT>& name (
) const { return name_; }
const std::basic_string<charT>& description (
) const { return description_; }
unsigned long number_of_arguments(
) const { return number_of_arguments_; }
unsigned long count (
) const { return num_present; }
const std::basic_string<charT>& argument (
unsigned long arg,
unsigned long N
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( N < count() && arg < number_of_arguments(),
"\tconst string_type& cmd_line_parser_option::argument(unsigned long,unsigned long)"
<< "\n\tsee the requires clause of argument()"
<< "\n\tthis: " << this
<< "\n\tN: " << N
<< "\n\targ: " << arg
<< "\n\tcount(): " << count()
<< "\n\tnumber_of_arguments(): " << number_of_arguments()
);
return options[N][arg];
}
protected:
option_t (
) :
num_present(0)
{}
~option_t()
{
clear();
}
private:
void clear()
/*!
ensures
- #count() == 0
- clears everything out of options and frees memory
!*/
{
for (unsigned long i = 0; i < options.size(); ++i)
{
delete [] options[i];
}
options.clear();
num_present = 0;
}
// data members
std::basic_string<charT> name_;
std::basic_string<charT> description_;
sequence2 options;
unsigned long number_of_arguments_;
unsigned long num_present;
// restricted functions
option_t(option_t&); // copy constructor
option_t& operator=(option_t&); // assignment operator
};
// --------------------------
public:
cmd_line_parser_kernel_1 (
);
virtual ~cmd_line_parser_kernel_1 (
);
void clear(
);
void parse (
int argc,
const charT** argv
);
void parse (
int argc,
charT** argv
)
{
parse(argc, const_cast<const charT**>(argv));
}
bool parsed_line(
) const;
bool option_is_defined (
const string_type& name
) const;
void add_option (
const string_type& name,
const string_type& description,
unsigned long number_of_arguments = 0
);
const cmd_line_parser_option<charT>& option (
const string_type& name
) const;
unsigned long number_of_arguments(
) const;
const string_type& operator[] (
unsigned long index
) const;
void swap (
cmd_line_parser_kernel_1& item
);
// functions from the enumerable interface
bool at_start (
) const { return options.at_start(); }
void reset (
) const { options.reset(); }
bool current_element_valid (
) const { return options.current_element_valid(); }
const cmd_line_parser_option<charT>& element (
) const { return *reinterpret_cast<cmd_line_parser_option<charT>*>(options.element().value()); }
cmd_line_parser_option<charT>& element (
) { return *reinterpret_cast<cmd_line_parser_option<charT>*>(options.element().value()); }
bool move_next (
) const { return options.move_next(); }
unsigned long size (
) const { return options.size(); }
private:
// data members
map options;
sequence argv;
bool have_parsed_line;
// restricted functions
cmd_line_parser_kernel_1(cmd_line_parser_kernel_1&); // copy constructor
cmd_line_parser_kernel_1& operator=(cmd_line_parser_kernel_1&); // assignment operator
};
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
inline void swap (
cmd_line_parser_kernel_1<charT,map,sequence,sequence2>& a,
cmd_line_parser_kernel_1<charT,map,sequence,sequence2>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
cmd_line_parser_kernel_1 (
) :
have_parsed_line(false)
{
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
~cmd_line_parser_kernel_1 (
)
{
// delete all option_t objects in options
options.reset();
while (options.move_next())
{
delete reinterpret_cast<option_t*>(options.element().value());
}
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
clear(
)
{
have_parsed_line = false;
argv.clear();
// delete all option_t objects in options
options.reset();
while (options.move_next())
{
delete reinterpret_cast<option_t*>(options.element().value());
}
options.clear();
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
parse (
int argc_,
const charT** argv
)
{
using namespace std;
// make sure there aren't any arguments hanging around from the last time
// parse was called
this->argv.clear();
// make sure that the options have been cleared of any arguments since
// the last time parse() was called
if (have_parsed_line)
{
options.reset();
while (options.move_next())
{
reinterpret_cast<option_t*>(options.element().value())->clear();
}
options.reset();
}
// this tells us if we have seen -- on the command line all by itself
// or not.
bool escape = false;
const unsigned long argc = static_cast<unsigned long>(argc_);
try
{
for (unsigned long i = 1; i < argc; ++i)
{
if (argv[i][0] == _dT(charT,'-') && !escape)
{
// we are looking at the start of an option
// --------------------------------------------------------------------
if (argv[i][1] == _dT(charT,'-'))
{
// we are looking at the start of a "long named" option
string_type temp = &argv[i][2];
string_type first_argument;
typename string_type::size_type pos = temp.find_first_of(_dT(charT,'='));
// This variable will be 1 if there is an argument supplied via the = sign
// and 0 otherwise.
unsigned long extra_argument = 0;
if (pos != string_type::npos)
{
// there should be an extra argument
extra_argument = 1;
first_argument = temp.substr(pos+1);
temp = temp.substr(0,pos);
}
// make sure this name is defined
if (!options.is_in_domain(temp))
{
// the long name is not a valid option
if (argv[i][2] == _dT(charT,'\0'))
{
// there was nothing after the -- on the command line
escape = true;
continue;
}
else
{
// there was something after the command line but it
// wasn't a valid option
throw cmd_line_parse_error(EINVALID_OPTION,temp);
}
}
option_t* o = reinterpret_cast<option_t*>(options[temp]);
// check the number of arguments after this option and make sure
// it is correct
if (argc + extra_argument <= o->number_of_arguments() + i)
{
// there are too few arguments
throw cmd_line_parse_error(ETOO_FEW_ARGS,temp,o->number_of_arguments());
}
if (extra_argument && first_argument.size() == 0 )
{
// if there would be exactly the right number of arguments if
// the first_argument wasn't empty
if (argc == o->number_of_arguments() + i)
throw cmd_line_parse_error(ETOO_FEW_ARGS,temp,o->number_of_arguments());
else
{
// in this case we just ignore the trailing = and parse everything
// the same.
extra_argument = 0;
}
}
// you can't force an option that doesn't have any arguments to take
// one by using the --option=arg syntax
if (extra_argument == 1 && o->number_of_arguments() == 0)
{
throw cmd_line_parse_error(ETOO_MANY_ARGS,temp);
}
// at this point we know that the option is ok and we should
// populate its options object
if (o->number_of_arguments() > 0)
{
string_type* stemp = new string_type[o->number_of_arguments()];
unsigned long j = 0;
// add the argument after the = sign if one is present
if (extra_argument)
{
stemp[0] = first_argument;
++j;
}
for (; j < o->number_of_arguments(); ++j)
{
stemp[j] = argv[i+j+1-extra_argument];
}
o->options.add(o->options.size(),stemp);
}
o->num_present += 1;
// adjust the value of i to account for the arguments to
// this option
i += o->number_of_arguments() - extra_argument;
}
// --------------------------------------------------------------------
else
{
// we are looking at the start of a list of a single char options
// make sure there is something in this string other than -
if (argv[i][1] == _dT(charT,'\0'))
{
throw cmd_line_parse_error();
}
string_type temp = &argv[i][1];
const typename string_type::size_type num = temp.size();
for (unsigned long k = 0; k < num; ++k)
{
string_type name;
name = temp[k];
// make sure this name is defined
if (!options.is_in_domain(name))
{
// the name is not a valid option
throw cmd_line_parse_error(EINVALID_OPTION,name);
}
option_t* o = reinterpret_cast<option_t*>(options[name]);
// if there are chars immediately following this option
int delta = 0;
if (num != k+1)
{
delta = 1;
}
// check the number of arguments after this option and make sure
// it is correct
if (argc + delta <= o->number_of_arguments() + i)
{
// there are too few arguments
std::ostringstream sout;
throw cmd_line_parse_error(ETOO_FEW_ARGS,name,o->number_of_arguments());
}
o->num_present += 1;
// at this point we know that the option is ok and we should
// populate its options object
if (o->number_of_arguments() > 0)
{
string_type* stemp = new string_type[o->number_of_arguments()];
if (delta == 1)
{
temp = &argv[i][2+k];
k = (unsigned long)num; // this ensures that the argument to this
// option isn't going to be treated as a
// list of options
stemp[0] = temp;
}
for (unsigned long j = 0; j < o->number_of_arguments()-delta; ++j)
{
stemp[j+delta] = argv[i+j+1];
}
o->options.add(o->options.size(),stemp);
// adjust the value of i to account for the arguments to
// this option
i += o->number_of_arguments()-delta;
}
} // for (unsigned long k = 0; k < num; ++k)
}
// --------------------------------------------------------------------
}
else
{
// this is just a normal argument
string_type temp = argv[i];
this->argv.add(this->argv.size(),temp);
}
}
have_parsed_line = true;
}
catch (...)
{
have_parsed_line = false;
// clear all the option objects
options.reset();
while (options.move_next())
{
reinterpret_cast<option_t*>(options.element().value())->clear();
}
options.reset();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
bool cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
parsed_line(
) const
{
return have_parsed_line;
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
bool cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
option_is_defined (
const string_type& name
) const
{
return options.is_in_domain(name);
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
add_option (
const string_type& name,
const string_type& description,
unsigned long number_of_arguments
)
{
option_t* temp = new option_t;
try
{
temp->name_ = name;
temp->description_ = description;
temp->number_of_arguments_ = number_of_arguments;
void* t = temp;
string_type n(name);
options.add(n,t);
}catch (...) { delete temp; throw;}
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
const cmd_line_parser_option<charT>& cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
option (
const string_type& name
) const
{
return *reinterpret_cast<cmd_line_parser_option<charT>*>(options[name]);
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
unsigned long cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
number_of_arguments(
) const
{
return argv.size();
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
const std::basic_string<charT>& cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
operator[] (
unsigned long index
) const
{
return argv[index];
}
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
swap (
cmd_line_parser_kernel_1<charT,map,sequence,sequence2>& item
)
{
options.swap(item.options);
argv.swap(item.argv);
exchange(have_parsed_line,item.have_parsed_line);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CMD_LINE_PARSER_KERNEl_1_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_CMD_LINE_PARSER_KERNEl_ABSTRACT_
#ifdef DLIB_CMD_LINE_PARSER_KERNEl_ABSTRACT_
#include "../algs.h"
#include <string>
#include "../interfaces/enumerable.h"
#include "../interfaces/cmd_line_parser_option.h"
namespace dlib
{
template <
typename charT
>
class cmd_line_parser : public enumerable<cmd_line_parser_option<charT> >
{
/*!
REQUIREMENTS ON charT
Must be an integral type suitable for storing characters. (e.g. char
or wchar_t)
INITIAL VALUE
parsed_line() == false
option_is_defined(x) == false, for all values of x
ENUMERATION ORDER
The enumerator will enumerate over all the options defined in *this
in alphebetical order according to the name of the option.
POINTERS AND REFERENCES TO INTERNAL DATA
parsed_line(), option_is_defined(), option(), number_of_arguments(),
operator[](), and swap() functions do not invalidate pointers or
references to internal data. All other functions have no such guarantee.
WHAT THIS OBJECT REPRESENTS
This object represents a command line parser.
The command lines must match the following BNF.
command_line ::= <program_name> { <options> | <arg> } [ -- {<word>} ]
program_name ::= <word>
arg ::= any <word> that does not start with -
option_arg ::= <sword>
option_name ::= <char>
long_option_name ::= <char> {<char> | - }
options ::= <bword> - <option_name> {<option_name>} {<option_arg>} |
<bword> -- <long_option_name> [=<option_arg>] {<bword> <option_arg>}
char ::= any character other than - or =
word ::= any string from argv where argv is the second
parameter to main()
sword ::= any suffix of a string from argv where argv is the
second parameter to main()
bword ::= This is an empty string which denotes the begining of a
<word>.
Options with arguments:
An option with N arguments will consider the next N swords to be
its arguments.
so for example, if we have an option o that expects 2 arguments
then the following are a few legal examples:
program -o arg1 arg2 general_argument
program -oarg1 arg2 general_argument
arg1 and arg2 are associated with the option o and general_argument
is not.
Arguments not associated with an option:
An argument that is not associated with an option is considered a
general command line argument and is indexed by operator[] defined
by the cmd_line_parser object. Additionally, if the string
"--" appears in the command line all by itself then all words
following it are considered to be general command line arguments.
Consider the following two examples involving a command line and
a cmd_line_parser object called parser.
Example 1:
command line: program general_arg1 -o arg1 arg2 general_arg2
Then the following is true (assuming the o option is defined
and takes 2 arguments).
parser[0] == "general_arg1"
parser[1] == "general_arg2"
parser.number_of_arguments() == 2
parser.option("o").argument(0) == "arg1"
parser.option("o").argument(1) == "arg2"
parser.option("o").count() == 1
Example 2:
command line: program general_arg1 -- -o arg1 arg2 general_arg2
Then the following is true (the -- causes everything following
it to be treated as a general argument).
parser[0] == "general_arg1"
parser[1] == "-o"
parser[2] == "arg1"
parser[3] == "arg2"
parser[4] == "general_arg2"
parser.number_of_arguments() == 5
parser.option("o").count() == 0
!*/
public:
typedef charT char_type;
typedef std::basic_string<charT> string_type;
typedef cmd_line_parser_option<charT> option_type;
// exception class
class cmd_line_parse_error : public dlib::error
{
/*!
GENERAL
This exception is thrown if there is an error detected in a
command line while it is being parsed. You can consult this
object's type and item members to determine the nature of the
error. (note that the type member is inherited from dlib::error).
INTERPRETING THIS EXCEPTION
- if (type == EINVALID_OPTION) then
- There was an undefined option on the command line
- item == The invalid option that was on the command line
- if (type == ETOO_FEW_ARGS) then
- An option was given on the command line but it was not
supplied with the required number of arguments.
- item == The name of this option.
- num == The number of arguments expected by this option.
- if (type == ETOO_MANY_ARGS) then
- An option was given on the command line such as --option=arg
but this option doesn't take any arguments.
- item == The name of this option.
!*/
public:
const std::basic_string<charT> item;
const unsigned long num;
};
// --------------------------
cmd_line_parser (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~cmd_line_parser (
);
/*!
ensures
- all memory associated with *this has 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 parse (
int argc,
const charT** argv
);
/*!
requires
- argv == an array of strings that was obtained from the second argument
of the function main().
(i.e. argv[0] should be the <program> token, argv[1] should be
an <options> or <arg> token, etc...)
- argc == the number of strings in argv
ensures
- parses the command line given by argc and argv
- #parsed_line() == true
- #at_start() == true
throws
- std::bad_alloc
if this exception is thrown then #*this is unusable until clear()
is called successfully
- cmd_line_parse_error
This exception is thrown if there is an error parsing the command line.
If this exception is thrown then #parsed_line() == false and all
options will have their count() set to 0 but otherwise there will
be no effect (i.e. all registered options will remain registered).
!*/
void parse (
int argc,
charT** argv
);
/*!
This just calls this->parse(argc,argv) and performs the necessary const_cast
on argv.
!*/
bool parsed_line(
) const;
/*!
ensures
- returns true if parse() has been called successfully
- returns false otherwise
!*/
bool option_is_defined (
const string_type& name
) const;
/*!
ensures
- returns true if the option has been added to the parser object
by calling add_option(name).
- returns false otherwise
!*/
void add_option (
const string_type& name,
const string_type& description,
unsigned long number_of_arguments = 0
);
/*!
requires
- parsed_line() == false
- option_is_defined(name) == false
- name does not contain any ' ', '\t', '\n', or '=' characters
- name[0] != '-'
- name.size() > 0
ensures
- #option_is_defined(name) == true
- #at_start() == true
- #option(name).count() == 0
- #option(name).description() == description
- #option(name).number_of_arguments() == number_of_arguments
throws
- std::bad_alloc
if this exception is thrown then the add_option() function has no
effect
!*/
const option_type& option (
const string_type& name
) const;
/*!
requires
- option_is_defined(name) == true
ensures
- returns the option specified by name
!*/
unsigned long number_of_arguments(
) const;
/*!
requires
- parsed_line() == true
ensures
- returns the number of arguments present in the command line.
This count does not include options or their arguments. Only
arguments unrelated to any option are counted.
!*/
const string_type& operator[] (
unsigned long N
) const;
/*!
requires
- parsed_line() == true
- N < number_of_arguments()
ensures
- returns the Nth command line argument
!*/
void swap (
cmd_line_parser& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
cmd_line_parser(cmd_line_parser&); // copy constructor
cmd_line_parser& operator=(cmd_line_parser&); // assignment operator
};
template <
typename charT
>
inline void swap (
cmd_line_parser<charT>& a,
cmd_line_parser<charT>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_CMD_LINE_PARSER_KERNEl_ABSTRACT_
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