Use Doxygen on lib*

Doxygen comments are now used in libowlps, libowlps-client and
libowlps-resultreader. doc/Doxyfile was added as well as CMake rules to
generate man pages for the libraries' header files.
This commit is contained in:
Matteo Cypriani 2013-06-03 20:28:13 -04:00
parent 9d640cd4d6
commit 3aa5ae7513
10 changed files with 2380 additions and 274 deletions

View File

@ -5,7 +5,7 @@ Work to do in OwlPS
= Documentation =
- Generalise the use of Doxygen, at least in the libraries.
- Doxygen: solve problem with structs (member fields are not documented).
- Topics to write on:
- Architecture

View File

@ -47,3 +47,39 @@ endfunction()
add_manpage(owlps 7)
add_manpage(owlps-architecture 7)
add_manpage(owlps-client 1)
### Doxygen-generated man pages ###
if (NOT DOXYGEN_FOUND)
message(WARNING
"Couldn't find Doxygen: disabling generation of Doxygen-based man pages")
return()
endif()
# Base output directory for Doxygen (it will append "man" for the
# man pages, "html" for the HTML output, etc.)
set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
# Section of the man pages we generate
set(SECTION 3)
# Final output directory (as assembled by Doxygen)
set(OUTPUT_DIRECTORY "${DOXYGEN_OUTPUT_DIRECTORY}/man/man${SECTION}")
# Output files
set(DOXYGEN_MANPAGES "${OUTPUT_DIRECTORY}/owlps.h.${SECTION}" "${OUTPUT_DIRECTORY}/owlps-client.h.${SECTION}" "${OUTPUT_DIRECTORY}/owlps-resultreader.h.${SECTION}")
# Doxygen configuration file name
set(DOXYFILE Doxyfile)
add_custom_command(
OUTPUT ${DOXYGEN_MANPAGES}
COMMAND DOXYGEN_OUTPUT_DIRECTORY=${DOXYGEN_OUTPUT_DIRECTORY} DOXYGEN_MAN_EXTENSION=.${SECTION} OWLPS_VERSION=${OWLPS_VERSION} "${DOXYGEN_EXECUTABLE}" "${DOXYFILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating Doxygen-based man pages")
add_custom_target(doc_doxygen true DEPENDS ${DOXYGEN_MANPAGES})
add_dependencies(doc doc_doxygen)
# Clean Doxygen garbage
file(GLOB DOXYGEN_GARBAGE "${OUTPUT_DIRECTORY}/_*_owlps_libowlps*_.${SECTION}")
if (DOXYGEN_GARBAGE)
file(REMOVE ${DOXYGEN_GARBAGE})
endif()

1797
doc/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -27,12 +27,18 @@
/*
* Opens an UDP socket to the server whose IP address is 'dest_ip'
* and which listens 'dest_port'. The server information is stored
* into 'server'. The socket will send through the network interface
* 'iface' if specified (if you want the interface to be selected,
* automatically, this parameter should be NULL or an empty string).
/**
* Opens a transmission UDP socket to a server in a simplified way.
* This function uses `owl_create_udp_trx_socket()` (from libowlps)
* as a backend, and allows to select a particular network interface.
*
* @param[in] dest_ip IP address of the remote server.
* @param[in] dest_port Port on which the remote server listens.
* @param[out] server Structure in which the server information will
* be saved.
* @param[in] iface The name of the network interface to send through.
* If this parameter is `NULL` or an empty string, the interface will
* be selected automatically.
*/
int owl_create_trx_socket(const char *const dest_ip,
const uint_fast16_t dest_port,
@ -59,7 +65,10 @@ int owl_create_trx_socket(const char *const dest_ip,
/* Selects 'iface' as sending interface for the socket 'sockfd'. */
/**
* Selects the interface named `iface` as a transmission interface for
* the socket `sockfd`.
*/
void owl_use_iface(const int sockfd, const char *const iface)
{
#if defined(linux) && defined(__GLIBC__)
@ -80,12 +89,20 @@ void owl_use_iface(const int sockfd, const char *const iface)
/*
/**
* Transmits a request.
* No packet will be transmitted if the variable owl_run is (or
* becomes) false.
* nb_pkt: number of packets to transmit.
* delay: delay between two transmissions, in milliseconds.
* No packet will be transmitted if the global variable `owl_run` is
* `false`, and the transmission will stop as soon as possible if it
* becomes `false`.
*
* @param[in] sockfd The file descriptor of the socket to use for the
* transmission.
* @param[in] server The server's information (as generated by
* `owl_create_trx_socket()`, for example).
* @param[in] packet The buffer to send through the socket.
* @param[in] packet_size The buffer's size.
* @param[in] nb_pkt Number of packets to transmit.
* @param[in] delay Delay between two transmissions, in milliseconds.
*/
void owl_send_request(const int sockfd,
const struct sockaddr_in *const server,
@ -125,6 +142,11 @@ void owl_send_request(const int sockfd,
/**
* Transmits a single packet of a request.
* See the documentation of the `owl_send_request()` function for an
* explanation on the parameters.
*/
void owl_send_packet(const int sockfd,
const struct sockaddr_in *const server,
const void *const packet,

View File

@ -9,12 +9,14 @@
* contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
* distributed along with this file, either separately or by replacing
* this notice by the COPYRIGHT.t2t file's contents.
*/
/**
* @file owlps-client.h
* @brief OwlPS Client library
*
***********************************************************************
*
* This is the header file of libowlps-client, the library that contains
* the code used to send positioning requests (normal, calibration and
* autocalibration).
* libowlps-client is the library that contains used to send positioning
* requests (normal, calibration and autocalibration).
*/
@ -25,11 +27,14 @@
/* Function headers */
/// Opens a transmission socket
int owl_create_trx_socket(const char *const dest_ip,
const uint_fast16_t dest_port,
struct sockaddr_in *const server,
const char *const iface) ;
/// Selects a transmission interface for the socket `sockfd`
void owl_use_iface(const int sockfd, const char *const iface) ;
/// Transmits a request
void owl_send_request(const int sockfd,
const struct sockaddr_in *const server,
const void *const packet,

View File

@ -31,16 +31,19 @@
#define CSV_DELIMITER ";"
/*
* Receives a result from the socket of file descriptor 'sockfd', fills
* an owl_result structure with the received information, and returns a
/**
* Receives a result from the socket of file descriptor `sockfd`, fills
* an `owl_result` structure with the received information, and returns a
* pointer to it.
*
* Note that the new owl_result is allocated with malloc() and must be
* deleted using free().
* Note that the new owl_result is allocated with `malloc()` and must be
* deleted using `free()`.
*
* In case of error, a message is printed, except if owl_run (from
* libowlps) is false, and NULL is returned.
* In case of error, a message is printed, except if `owl_run` (from
* `owlps.h`) is `false`, and `NULL` is returned.
*
* @returns A pointer to a new `owl_result`.
* @returns `NULL` in case of error.
*/
owl_result* owl_receive_position(int sockfd)
{
@ -61,19 +64,26 @@ owl_result* owl_receive_position(int sockfd)
}
/*
* Splits the 'csv' string received from OwlPS Positioner and stores
* the fields in a new owl_result, and returns a pointer to it (or NULL
* in case of error).
/**
* Splits the `csv` string received from OwlPS Positioner and stores
* the fields in a new `owl_result`, and returns a pointer to it (or
* `NULL` in case of error).
*
* Note that the new owl_result is allocated with malloc() and must be
* deleted using free().
* Note that the new `owl_result` is allocated with `malloc()` and must
* be deleted using `free()`.
*
* Handled CSV format:
* Mobile_MAC;Request_type;Request_timestamp;Algorithm;X;Y;Z;Error;Area
*
* Mobile_MAC;Request_type;Request_timestamp;Algorithm;X;Y;Z;Error;Area
*
* The Request_timestamp format is:
* seconds.nanoseconds
* The Area field can be empty.
*
* seconds.nanoseconds
*
* The *Area* field can be empty.
*
* @returns A pointer to a new `owl_result`.
* @returns `NULL` in case of error.
*/
owl_result* owl_fill_result(char *csv)
{
@ -158,17 +168,22 @@ owl_result* owl_fill_result(char *csv)
}
/*
* Splits the 'csv' string, stores the fields in a new
* owl_algorithm_result, and returns a pointer to it (or NULL
/**
* Splits the `csv` string, stores the fields in a new
* `owl_algorithm_result`, and returns a pointer to it (or `NULL`
* in case of error).
*
* Note that the new owl_algorithm_result is allocated with malloc()
* and must be deleted using free().
* Note that the new owl_algorithm_result is allocated with `malloc()`
* and must be deleted using `free()`.
*
* 'csv' must follow this CSV format:
* Algorithm;X;Y;Z;Error;Area
* The Area field can be empty.
* Handled CSV format:
*
* Algorithm;X;Y;Z;Error;Area
*
* The *Area* field can be empty.
*
* @returns A pointer to a new `owl_algorithm_result`.
* @returns `NULL` in case of error.
*/
owl_algorithm_result* owl_fill_algorithm_result(char **csv)
{
@ -247,15 +262,18 @@ owl_algorithm_result* owl_fill_algorithm_result(char **csv)
}
/*
* Converts an owl_result back to a CSV string.
* 'dst' must be an allocated string of at least OWL_CSV_RESULT_STRLEN
/**
* Converts an `owl_result back` to a CSV string.
* `dst` must be an allocated string of at least `OWL_CSV_RESULT_STRLEN`
* characters.
*
* CSV format:
* Mobile_MAC;Request_type;Request_timestamp;Nb_algo;Algo_1;;Algo_n
* Nb_algo is the number of algorithms in the result.
* The format of Algo_i is documented in owl_algorithm_result_to_csv().
*
* Mobile_MAC;Request_type;Request_timestamp;Nb_algo;Algo_1;;Algo_n
*
* *Nb_algo* is the number of algorithms in the result.
* The format of *Algo_i* is documented in the documentation of the
* `owl_algorithm_result_to_csv()` function.
*/
void owl_result_to_csv(char dst[OWL_CSV_RESULT_STRLEN],
const owl_result *const src)
@ -287,17 +305,19 @@ void owl_result_to_csv(char dst[OWL_CSV_RESULT_STRLEN],
}
/*
* Converts an owl_algorithm_result back to a CSV string.
* 'dst' must be an allocated string of at least
* OWL_CSV_ALGORITHM_RESULT_STRLEN characters.
/**
* Converts an `owl_algorithm_result` back to a CSV string.
* `dst` must be an allocated string of at least
* `OWL_CSV_ALGORITHM_RESULT_STRLEN` characters.
*
* CSV format:
* Algorithm_name;X;Y;Z;Error;Area_name
* Error is the distance from the true coordinates of the mobile, if
* known; if unknown, Error is set to -1.
* Area_name is the name of the area or room in which the mobile is (may
* be empty).
*
* Algorithm_name;X;Y;Z;Error;Area_name
*
* *Error* is the distance from the true coordinates of the mobile, if
* known; if unknown, *Error* is set to -1.
* *Area_name* is the name of the area or room in which the mobile is
* (may be empty).
*/
void
owl_algorithm_result_to_csv(char dst[OWL_CSV_ALGORITHM_RESULT_STRLEN],
@ -316,17 +336,20 @@ owl_algorithm_result_to_csv(char dst[OWL_CSV_ALGORITHM_RESULT_STRLEN],
}
/*
* Converts an owl_result back to a CSV string, in a simplified format.
* Only the *first* algorithm in the result's algorithm list will be
/**
* Converts an `owl_result` back to a CSV string, in a simplified format:
* only the *first* algorithm in the result's algorithm list will be
* included in the string.
* 'dst' must be an allocated string of at least
* OWL_CSV_RESULT_SIMPLE_STRLEN characters.
* `dst` must be an allocated string of at least
* `OWL_CSV_RESULT_SIMPLE_STRLEN` characters.
*
* CSV format:
* Mobile_MAC;First_algorithm
* First_algorithm is the first algorithm in src->results. Its format
* is documented in owl_algorithm_result_to_csv_simple().
*
* Mobile_MAC;First_algorithm
*
* *First_algorithm* is the first algorithm in `src->results`. Its format
* is documented in the documentation of the
* `owl_algorithm_result_to_csv_simple()` function.
*/
void owl_result_to_csv_simple(char dst[OWL_CSV_RESULT_SIMPLE_STRLEN],
const owl_result *const src)
@ -349,16 +372,18 @@ void owl_result_to_csv_simple(char dst[OWL_CSV_RESULT_SIMPLE_STRLEN],
}
/*
* Converts an owl_algorithm_result back to a CSV string, in a
/**
* Converts an `owl_algorithm_result` back to a CSV string, in a
* simplified format.
* 'dst' must be an allocated string of at least
* OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN characters.
* `dst` must be an allocated string of at least
* `OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN` characters.
*
* CSV format:
* X;Y;Z;Area_name
* Area_name is the name of the area or room in which the mobile is (may
* be empty).
*
* X;Y;Z;Area_name
*
* *Area_name* is the name of the area or room in which the mobile is
* (may be empty).
*/
void owl_algorithm_result_to_csv_simple
(char dst[OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN],
@ -375,8 +400,9 @@ void owl_algorithm_result_to_csv_simple
}
/*
* Prints an owl_result to the given stream.
/**
* Prints an `owl_result` to the given stream, using `fprintf()`.
* `src` must not be `NULL`.
*/
void owl_fprint_result(FILE *stream, const owl_result *const src)
{
@ -405,8 +431,10 @@ void owl_fprint_result(FILE *stream, const owl_result *const src)
}
/*
* Prints an owl_algorithm_result to the given stream.
/**
* Prints an `owl_algorithm_result` to the given stream, using
* `fprintf()`.
* `src` must not be `NULL`.
*/
void owl_fprint_algorithm_result(FILE *stream,
const owl_algorithm_result *const src)
@ -432,11 +460,11 @@ void owl_fprint_algorithm_result(FILE *stream,
/*
* Frees the memory allocated by an owl_result. The 'results' and
* 'mobile_mac_addr' fields *must* be defined, either to NULL or to a
* valid memory block allocated with malloc().
* Note that the pointer will not set to NULL.
/**
* Frees the memory allocated for an `owl_result`. The `results` and
* `mobile_mac_addr` fields of `result` *must* be defined, either to
* `NULL` or to a valid memory block allocated with `malloc()`.
* Note that `result` will not set to `NULL`.
*/
void owl_free_result(owl_result *result)
{
@ -453,11 +481,12 @@ void owl_free_result(owl_result *result)
}
/*
* Frees the memory allocated by a single owl_algorithm_result (*not*
* recursively). The 'algorithm' and 'area' fields *must* be defined,
* either to NULL or to a valid memory block allocated with malloc().
* Note that the pointer will not set to NULL.
/**
* Frees the memory allocated for a single `owl_algorithm_result` (*not*
* recursively). The `algorithm` and `area` fields of `algo` *must* be
* defined, either to `NULL` or to a valid memory block allocated with
* `malloc()`.
* Note that `algo` will not set to `NULL`.
*/
void owl_free_algorithm_result(owl_algorithm_result *algo)
{

View File

@ -16,12 +16,13 @@
* program demonstrating the use of libowlps-resultreader-udp.
* The received results are printed on the standard output.
*
* This program must be linked against libowlps and its dependencies
* (see the Makefile).
* This program must be linked against libowlps-resultreader and
* libowlps.
*/
#include "owlps-resultreader.h"
#include <owlps.h>
#include <signal.h>
#include <unistd.h>

View File

@ -9,13 +9,17 @@
* contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
* distributed along with this file, either separately or by replacing
* this notice by the COPYRIGHT.t2t file's contents.
*/
/**
* @file owlps-resultreader.h
* @brief OwlPS Result Reader library
*
***********************************************************************
* libowlps-resultreader is the the library that provides functions to
* read and display results sent on UDP by OwlPS Positioner.
*
* This is the header file of libowlps-resultreader, the library that
* provides functions to read results sent on UDP by OwlPS Positioner.
*
* See also the example program owlps-resultreader-udp.c.
* See also the source code of the example program
* `owlps-resultreader-udp`.
*/
@ -43,6 +47,7 @@
#define OWL_CSV_ALGORITHM_RESULT_STRLEN \
(OWL_ALGORITHM_STRLEN + 4 * OWL_COORDINATE_STRLEN + \
OWL_AREA_STRLEN + 1)
/// Maximum size of a result CSV string sent by OwlPS Positioner
#define OWL_CSV_RESULT_STRLEN \
(OWL_CSV_RESULT_REQUEST_STRLEN + \
OWL_NB_ALGORITHMS * OWL_CSV_ALGORITHM_RESULT_STRLEN + 1)
@ -56,64 +61,90 @@
#define OWL_CSV_RESULT_REQUEST_SIMPLE_STRLEN OWL_ETHER_ADDR_STRLEN
#define OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN \
(3 * OWL_COORDINATE_STRLEN + OWL_AREA_STRLEN + 1)
/// Maximum size of a simplified result CSV string as created by
/// *_to_csv_simple()
#define OWL_CSV_RESULT_SIMPLE_STRLEN \
(OWL_CSV_RESULT_REQUEST_SIMPLE_STRLEN + \
OWL_NB_ALGORITHMS * OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN + 1)
/* Linked list of algorithms' results.
* Each structure is the result of a single algorithm.
/// Structure of linked list of algorithm's results
/**
* This structure represents the result of a single algorithm, and
* includes a field `next` which points to the next algorithm's result,
* if any, or `NULL` if it is the last algorithm.
*/
typedef struct _owl_algorithm_result
struct _owl_algorithm_result
{
char *algorithm ;
float x ;
float y ;
float z ;
float error ;
char *area ;
char *algorithm ; ///< Name of the algorithm used to compute the result
float x ; ///< Computed X coordinate
float y ; ///< Computed Y coordinate
float z ; ///< Computed Z coordinate
float error ; ///< Distance error (if available)
char *area ; ///< Name of the area in which the result point is
struct _owl_algorithm_result *next ;
} owl_algorithm_result ;
struct _owl_algorithm_result *next ; ///< Next result
} ;
/// Linked list of algorithms' results
typedef struct _owl_algorithm_result owl_algorithm_result ;
/* Results for a request. Includes the request's data, and the
* list of algorithms' results.
/// Structure of the generated results for a request
/**
* This structure stores the information of a request along with a
* pointer to the list of generated results.
*/
typedef struct _owl_result
struct _owl_result
{
char *mobile_mac_addr ;
uint8_t request_type ;
char *mobile_mac_addr ; ///< Mobile's MAC address
uint8_t request_type ; ///< Type of the request
/// Local time on the mobile when sending the request
owl_timestamp mobile_timestamp ;
unsigned int nb_results ;
owl_algorithm_result *results ;
} owl_result ;
unsigned int nb_results ; ///< Number of results generated
owl_algorithm_result *results ; ///< List of the generated results
} ;
/// Generated results for a request
typedef struct _owl_result owl_result ;
/// Receives a result from the socket `sockfd`
owl_result* owl_receive_position(int sockfd) ;
/// Splits the `csv` string and stores it in a new `owl_result`
owl_result* owl_fill_result(char *csv) ;
/// Splits the `csv` string and stores it in a new `owl_algorithm_result`
owl_algorithm_result* owl_fill_algorithm_result(char **csv) ;
/// Converts an `owl_result back` to a CSV string
void owl_result_to_csv(char dst[OWL_CSV_RESULT_STRLEN],
const owl_result *const src) ;
/// Converts an `owl_algorithm_result` back to a CSV string
void
owl_algorithm_result_to_csv(char dst[OWL_CSV_ALGORITHM_RESULT_STRLEN],
const owl_algorithm_result *const src) ;
/// Converts an `owl_result` back to a CSV string (simplified format)
void owl_result_to_csv_simple(char dst[OWL_CSV_RESULT_SIMPLE_STRLEN],
const owl_result *const src) ;
/// Converts an `owl_algorithm_result` back to a CSV string (simplified
/// format)
void owl_algorithm_result_to_csv_simple
(char dst[OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN],
const owl_algorithm_result *const src) ;
/// Prints an `owl_result` to the given stream
void owl_fprint_result(FILE *stream, const owl_result *const src) ;
/// Prints an `owl_algorithm_result` to the given stream
void owl_fprint_algorithm_result(FILE *stream,
const owl_algorithm_result *const src) ;
/// Prints an `owl_result` to the standard output
#define owl_print_result(SRC) \
(owl_fprint_result(stdout, (SRC)))
/// Prints an `owl_algorithm_result` to the standard output
#define owl_print_algorithm_result(SRC) \
(owl_fprint_algorithm_result(stdout, (SRC)))
/// Frees an `owl_result`
void owl_free_result(owl_result *result) ;
/// Frees a single `owl_algorithm_result`
void owl_free_algorithm_result(owl_algorithm_result *algo) ;

View File

@ -40,11 +40,14 @@ bool owl_run = true ;
/* *** Miscellaneous functions *** */
/*
* Converts a MAC address from bytes to string.
/**
* Converts a MAC address from bytes to character string.
* The string is allocated in a static buffer, and will be overwritten
* each time this function is called.
* This function is not thread-safe!
* **This function is not thread-safe!**
*
* @returns A pointer to the static buffer containing the character
* string. This pointer must *not* be freed manually by the caller.
*/
const char* owl_mac_bytes_to_string(const uint8_t *const mac_binary)
{
@ -54,9 +57,10 @@ const char* owl_mac_bytes_to_string(const uint8_t *const mac_binary)
}
/*
* Converts a MAC address from bytes to string.
* 'mac_str' must be allocated by the caller.
/**
* Converts a MAC address from bytes to character string.
* The `mac_str` buffer must be allocated by the caller and its length
* must be of at least `OWL_ETHER_ADDR_STRLEN`.
* This function is thread-safe.
*/
void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary,
@ -69,9 +73,10 @@ void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary,
}
/*
/**
* Compares two MAC addresses.
* Returns true if they are identical, false otherwise.
*
* @returns `true` if the two addresses are identical, `false` otherwise.
*/
bool owl_mac_equals(const uint8_t *const mac1,
const uint8_t *const mac2)
@ -84,9 +89,12 @@ bool owl_mac_equals(const uint8_t *const mac1,
}
/*
* Converts a IEEE 802.11 frequency into a channel number.
* Returns 0 if the frequency does not correspond to an official channel.
/**
* Converts a IEEE 802.11 frequency (in MHz) into a channel number.
*
* @returns The channel number corresponding to `frequency`.
* @returns 0 if the frequency does not correspond to an official
* channel.
*/
uint_fast8_t owl_frequency_to_channel(const uint_fast16_t frequency)
{
@ -129,12 +137,15 @@ uint_fast8_t owl_frequency_to_channel(const uint_fast16_t frequency)
/* *** Time *** */
/*
/**
* Sleeps for a given amount of milliseconds.
* 'time_ms' is an unsigned value, so please be careful: passing a
* `time_ms` is an unsigned value, so please be careful: passing a
* negative value may not do what you think.
* In case of error, a message is displayed and a non-zero error code
* is returned (if positive, it is the number of non-sleeped seconds).
* In case of error, a message is displayed on the standard error.
*
* @returns 0 if everything went well.
* @returns A non-zero error code in case of error; if positive, it is
* the number of non-slept seconds.
*/
int owl_msleep(uint32_t time_ms)
{
@ -163,9 +174,10 @@ int owl_msleep(uint32_t time_ms)
}
/*
* Sets the owl_timestamp 'now' at the current time.
* Returns 0 in case of success non-zero otherwise.
/**
* Sets the `owl_timestamp` `now` to the current time.
*
* @returns 0 in case of success, non-zero otherwise.
*/
int owl_timestamp_now(owl_timestamp *const now)
{
@ -195,8 +207,9 @@ int owl_timestamp_now(owl_timestamp *const now)
}
/*
* Converts the struct timespec 'src' into the owl_timestamp 'dst'.
/**
* Converts the `struct timespec` `src` into the `owl_timestamp` `dst`.
* `src` and `dst` must not be `NULL`.
*/
void owl_timespec_to_timestamp(const struct timespec *const src,
owl_timestamp *const dst)
@ -208,8 +221,9 @@ void owl_timespec_to_timestamp(const struct timespec *const src,
}
/*
* Converts the struct timeval 'src' into the owl_timestamp 'dst'.
/**
* Converts the `struct timeval` `src` into the `owl_timestamp` `dst`.
* `src` and `dst` must not be `NULL`.
*/
void owl_timeval_to_timestamp(const struct timeval *const src,
owl_timestamp *const dst)
@ -221,6 +235,11 @@ void owl_timeval_to_timestamp(const struct timeval *const src,
}
/**
* Compares two `owl_timestamp` and returns `true` if they are equal,
* `false` otherwise.
* `d1` and `d2` must not be `NULL`.
*/
bool owl_timestamp_equals(const owl_timestamp *const d1,
const owl_timestamp *const d2)
{
@ -230,8 +249,11 @@ bool owl_timestamp_equals(const owl_timestamp *const d1,
}
/*
* Converts a owl_timestamp date value into milliseconds.
/**
* Converts the `owl_timestamp` date value `d` into milliseconds.
* `d` must not be `NULL`.
*
* @returns The millisecond value of `d`.
*/
uint64_t owl_timestamp_to_ms(const owl_timestamp *const d)
{
@ -241,9 +263,10 @@ uint64_t owl_timestamp_to_ms(const owl_timestamp *const d)
}
/*
* Converts a owl_timestamp date value into a printable string.
* 'dst' must be an allocated array of at least OWL_TIMESTAMP_STRLEN
/**
* Converts the `owl_timestamp` date value `src` into a printable string.
* `src` must not be `NULL`.
* `dst` must be an allocated array of at least `OWL_TIMESTAMP_STRLEN`
* characters.
*/
void owl_timestamp_to_string(const owl_timestamp *const src,
@ -256,8 +279,12 @@ void owl_timestamp_to_string(const owl_timestamp *const src,
}
/*
* Returns the time (in milliseconds) between two dates.
/**
* Returns the time (in milliseconds) elapsed between two `owl_timestamp`
* `d1` and `d2`. `d1` can either be lower (before) or greater (after)
* `d2`, the returned value will always be the delay between the older
* and the newer time.
* `d1` and `d2` must not be NULL.
*/
uint_fast32_t owl_time_elapsed_ms(const owl_timestamp *const d1,
const owl_timestamp *const d2)
@ -268,12 +295,12 @@ uint_fast32_t owl_time_elapsed_ms(const owl_timestamp *const d1,
}
/*
* Computes the time difference between two owl_timestamp 'd1' and
* 'd2'.
/**
* Computes the time difference between two `owl_timestamp` `d1` and
* `d2`. The result is stored in the `elapsed` parameter.
* Note that it is a delay, not a simple substraction, therefore the
* result is always positive. The result is stored in the 'elapsed'
* argument.
* result is always positive.
* NULL parameters are not accepted.
*/
void owl_time_elapsed(const owl_timestamp *const d1,
const owl_timestamp *const d2,
@ -323,11 +350,13 @@ void owl_time_elapsed(const owl_timestamp *const d1,
/* *** Endianess *** */
/* *** Endianness *** */
/*
* Converts a owl_timestamp from host endianness to network endianness.
/**
* Converts an `owl_timestamp` from host endianness to network
* endianness.
* The conversion is done in-place. `d` must not be `NULL`.
*/
void owl_hton_timestamp(owl_timestamp *const d)
{
@ -337,8 +366,10 @@ void owl_hton_timestamp(owl_timestamp *const d)
}
/*
* Converts a owl_timestamp from network endianness to host endianness.
/**
* Converts an `owl_timestamp` from network endianness to host
* endianness.
* The conversion is done in-place. `d` must not be `NULL`.
*/
void owl_ntoh_timestamp(owl_timestamp *const d)
{
@ -348,10 +379,13 @@ void owl_ntoh_timestamp(owl_timestamp *const d)
}
/*
* Swap bytes composing a float.
* You probably want to use the macros owl_htonf() and owl_ntohf()
/**
* This function swaps the bytes composing a `float`, i.e. it changes
* their order.
* You probably want to use the `owl_htonf()` and `owl_ntohf()` macros
* instead of this function.
*
* @returns The swapped `float`.
*/
float owl_swap_float(const float f)
{
@ -375,16 +409,18 @@ float owl_swap_float(const float f)
/* *** Network *** */
/*
* Creates a UDP transmission socket and returns its descriptor.
* Parameters:
* - server_address: the server IP address.
* - server_port: the listening port on the server.
* - server_description (in/out): the structure in which the server
* description will be saved.
* - client_description (in/out): the structure in which the client
* description will be saved.
* Returns a negative error code in case of error.
/**
* Opens a UDP transmission socket and returns its descriptor.
*
* @param[in] server_address The server's IP address.
* @param[in] server_port The listening port on the server.
* @param[out] server_description The structure in which the server
* description will be saved.
* @param[out] client_description The structure in which the client
* description will be saved.
*
* @returns A file descriptor to the opened socket in case of success,
* or a negative error code.
*/
int owl_create_udp_trx_socket(const char *const server_address,
const uint_fast16_t server_port,
@ -418,11 +454,12 @@ int owl_create_udp_trx_socket(const char *const server_address,
}
/*
* Creates a UDP reception socket and returns its descriptor.
* Parameters:
* - port: port on which the socket listens.
* Returns a negative error code in case of error.
/**
* Opens a UDP reception socket and returns its descriptor.
* `port` is the port on which the socket will listen.
*
* @returns A file descriptor to the opened socket in case of success,
* or a negative error code.
*/
int owl_create_udp_listening_socket(const uint_fast16_t port)
{
@ -463,8 +500,11 @@ int owl_create_udp_listening_socket(const uint_fast16_t port)
/* *** Signals *** */
/*
/**
* Generic signal handler for SIGINT.
*
* @param num The catched signal. This function will exit with
* `OWL_ERR_BAD_SIGNAL` if `num != SIGINT`.
*/
void owl_sigint_handler(const int num)
{
@ -484,8 +524,11 @@ void owl_sigint_handler(const int num)
}
/*
/**
* Generic signal handler for SIGTERM.
*
* @param num The catched signal. This function will exit with
* `OWL_ERR_BAD_SIGNAL` if `num != SIGTERM`.
*/
void owl_sigterm_handler(const int num)
{
@ -504,9 +547,11 @@ void owl_sigterm_handler(const int num)
/* *** Thread-related functions *** */
/*
* Closes the file descriptor 'fd'.
* 'fd' must be passed as an int pointer (int*).
/**
* Closes the file descriptor `fd`.
* `fd` must be passed as an int pointer (`int*`). If `fd` is `NULL`,
* nothing will be done. Uppon error, a message is displayed on the
* standard error.
*/
void owl_close_fd(void *const fd)
{
@ -524,10 +569,11 @@ void owl_close_fd(void *const fd)
}
/*
* Closes the stream 'file'.
* 'file' must be passed as a pointer on a pointer of FILE (FILE**).
* If *file either stdout, stderr or stdin, it will not be closed.
/**
* Closes the stream `file`.
* `file` must be passed as a pointer on a pointer of FILE (FILE**).
* If `*file` is either `stdout`, `stderr` or `stdin`, it will not be
* closed.
*/
void owl_close_file(void *const file)
{

View File

@ -9,23 +9,31 @@
* contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
* distributed along with this file, either separately or by replacing
* this notice by the COPYRIGHT.t2t file's contents.
*/
/**
* @file owlps.h
* @brief OwlPS library
*
***********************************************************************
*
* This is the header file of libowlps, the library containing the code
* shared by most of the OwlPS programs.
* libowlps is the library containing the code shared by most of the
* OwlPS programs.
*/
#ifndef _LIBOWLPS_H_
#define _LIBOWLPS_H_
#ifdef __cplusplus
# include <cstdint>
#else // __cplusplus
# include <stdint.h>
#endif // __cplusplus
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <stdint.h> // We'll use <cstdint> with C++ 0x
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -34,114 +42,180 @@ extern "C" {
#include <netinet/if_ether.h>
// Port on which the positioning and calibration requests are sent by
// the mobiles (or the listeners for autocalibration requests):
/** @name Network ports */
//@{
/// Port on which the positioning and calibration requests are sent by
/// the mobiles (or the listeners for autocalibration requests)
#define OWL_DEFAULT_REQUEST_PORT 9900
// Port on which listeners and aggregator communicate:
/// Port on which listeners and aggregator communicate
#define OWL_DEFAULT_LISTENER_PORT 9901
// Port on which Aggregator and Positioner communicate:
/// Port on which Aggregator and Positioner communicate
#define OWL_DEFAULT_AGGREGATION_PORT 9902
// Port on which the aggregator listens for hello messages from the
// listeners:
/// Port on which the aggregator listens for hello messages from the
/// listeners
#define OWL_DEFAULT_AUTOCALIBRATION_HELLO_PORT 9903
// Port on which the listeners listen for orders from the aggregator:
/// Port on which the listeners listen for orders from the aggregator
#define OWL_DEFAULT_AUTOCALIBRATION_ORDER_PORT 9904
// Port on which the mobile listens for its position:
/// Port on which the mobile listens for its position
#define OWL_DEFAULT_RESULT_PORT 9910
//@}
/* Direction type */
enum {owl_north = 1, owl_east, owl_south, owl_west} ;
/// Directions
enum owl_directions
{
owl_north = 1, ///< North direction
owl_east, ///< East direction
owl_south, ///< South direction
owl_west ///< West direction
} ;
/// First [direction](@ref owl_direction)
#define OWL_DIRECTION_MIN 1
/// Last [direction](@ref owl_direction)
#define OWL_DIRECTION_MAX 4
/// Direction type
typedef uint8_t owl_direction ;
/* Timestamp type (struct timespec clone with fixed size fields) */
typedef struct _owl_timestamp
/// Timestamp structure
/**
* This timestamp structure is a clone of `struct timespec` (from
* `time.h`), but with fixed-size fields.
*/
struct _owl_timestamp
{
uint32_t tv_sec ;
uint32_t tv_nsec ;
} owl_timestamp ;
// Length of a owl_timestamp when converted to string:
#define OWL_TIMESTAMP_STRLEN 22 // 22 = 10 digits, '.', 10 digits, '\0'
uint32_t tv_sec ; ///< Seconds
uint32_t tv_nsec ; ///< Nanoseconds
} ;
/// Timestamp type
typedef struct _owl_timestamp owl_timestamp ;
/** @name String lengths */
//@{
/// Length of a owl_timestamp when converted to string
/**
* 22 = 10 digits, '.', 10 digits, '\0'
*/
#define OWL_TIMESTAMP_STRLEN 22
//@}
/* Message sent by the listener to the aggregator */
typedef struct _owl_captured_request
/// Message sent by the Listener to the Aggregator
/**
* Message sent by the Listener to the Aggregator for each captured
* request.
*/
struct _owl_captured_request
{
uint8_t type ; // Type of the captured request
uint16_t nb_packets ; // Number of packets for this request
uint16_t packet_id ; // Number of the current packet
uint8_t ap_mac_addr_bytes[ETHER_ADDR_LEN] ; // MAC of the listener
uint8_t mobile_mac_addr_bytes[ETHER_ADDR_LEN] ; // MAC of the mobile
uint8_t mobile_ip_addr_bytes[4] ; // IP of the mobile
owl_timestamp request_time ; // Timestamp on the mobile
owl_timestamp capture_time ; // Timestamp of arrival on the listener
int8_t ss_dbm ; // Signal strength measured by the listener (dBm)
uint8_t type ; ///< Type of the captured request
uint16_t nb_packets ; ///< Number of packets for this request
uint16_t packet_id ; ///< Number of the current packet
uint8_t ap_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the listener
uint8_t mobile_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the mobile
uint8_t mobile_ip_addr_bytes[4] ; ///< IP of the mobile
owl_timestamp request_time ; ///< Timestamp on the mobile
owl_timestamp capture_time ; ///< Timestamp of arrival on the listener
int8_t ss_dbm ; ///< Signal strength measured by the listener (dBm)
/* Calibration data */
float x_position ;
float y_position ;
float z_position ;
owl_direction direction ;
} owl_captured_request ;
float x_position ; ///< X coordinate
float y_position ; ///< Y coordinate
float z_position ; ///< Z coordinate
owl_direction direction ; ///< Orientation of the mobile
} ;
/// Captured request type
typedef struct _owl_captured_request owl_captured_request ;
/* Message sent by the Aggregator to the Positioner containing
* the main data of a request */
typedef struct _owl_request
/// Message sent by the Aggregator to the Positioner (request's data)
/**
* Message sent by the Aggregator to the Positioner containing
* the main data of a request.
*/
struct _owl_request
{
uint8_t type ; // Type of the request
uint16_t nb_packets ; // Number of packets sent for this request
uint8_t mobile_mac_addr_bytes[ETHER_ADDR_LEN] ; // MAC of the mobile
uint8_t mobile_ip_addr_bytes[4] ; // IP of the mobile
owl_timestamp request_time ; // Timestamp on the mobile
uint16_t nb_info ; // Number of owl_request_info
uint8_t type ; ///< Type of the request
uint16_t nb_packets ; ///< Number of packets sent for this request
uint8_t mobile_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the mobile
uint8_t mobile_ip_addr_bytes[4] ; ///< IP of the mobile
owl_timestamp request_time ; ///< Timestamp on the mobile
uint16_t nb_info ; ///< Number of owl_request_info
/* Calibration data */
float x_position ;
float y_position ;
float z_position ;
owl_direction direction ;
} owl_request ;
float x_position ; ///< X coordinate
float y_position ; ///< Y coordinate
float z_position ; ///< Z coordinate
owl_direction direction ; ///< Orientation of the mobile
} ;
/// Aggregated request type
typedef struct _owl_request owl_request ;
/* Message sent by the Aggregator to the Positioner refering to
/// Message sent by the Aggregator to the Positioner (signal strength)
/**
* Message sent by the Aggregator to the Positioner refering to
* a request, indicating that an AP received the request with a given
* signal strength */
typedef struct _owl_request_info
* signal strength.
*/
struct _owl_request_info
{
uint16_t packet_id ; // Number of the current packet
uint8_t ap_mac_addr_bytes[ETHER_ADDR_LEN] ; // MAC of the listener
owl_timestamp capture_time ; // Timestamp of arrival on the listener
int8_t ss_dbm ; // Signal strength measured by the listener (dBm)
} owl_request_info ;
uint16_t packet_id ; ///< Number of the current packet
uint8_t ap_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the listener
owl_timestamp capture_time ; ///< Timestamp of arrival on the listener
int8_t ss_dbm ; ///< Signal strength measured by the listener (dBm)
} ;
/// Aggregated request information type
typedef struct _owl_request_info owl_request_info ;
/* Hello message sent by the listener to the aggregator */
typedef struct _owl_autocalibration_hello
/// *Hello* message sent by the Listener to the Aggregator
/**
* This structure represents a *hello* message sent to the Aggregator by
* each Listener to signal its presence.
*/
struct _owl_autocalibration_hello
{
/// MAC address of the Listener
uint8_t ap_mac_addr_bytes[ETHER_ADDR_LEN] ;
} owl_autocalibration_hello ;
} ;
/// *Hello* message type
typedef struct _owl_autocalibration_hello owl_autocalibration_hello ;
/* Message sent to the listener to order an emission */
#define AUTOCALIBRATION_ORDER_SEND 1
typedef struct _owl_autocalibration_order
/// Message sent to the Listener to order an emission
/**
* This structure represents a message sent by the Aggregator to a
* Listener to order it to send an autocalibration request.
*/
struct _owl_autocalibration_order
{
uint8_t order ;
} owl_autocalibration_order ;
uint8_t order ; ///< Code of the order
} ;
/// Autocalibration order type
typedef struct _owl_autocalibration_order owl_autocalibration_order ;
/** @name Autocalibration order type identifiers */
//@{
#define AUTOCALIBRATION_ORDER_SEND 1
//@}
/* Positioning request types */
/** @name Request type identifiers */
//@{
/// "Normal" positioning request
#define OWL_REQUEST_NORMAL 0
/// Calibration request
#define OWL_REQUEST_CALIBRATION 1
/// Autocalibration request
#define OWL_REQUEST_AUTOCALIBRATION 2
/// Generated request (in Positioner)
#define OWL_REQUEST_GENERATED 3
/// Implicit positioning request
#define OWL_REQUEST_IMPLICIT 10
/// Undefined or unknown request type
#define OWL_REQUEST_UNDEFINED 255
//@}
/* Wi-Fi channel frequencies in MHz */
/** @name Wi-Fi channels' frequencies in MHz */
//@{
#define OWL_80211_MHZ_CHANNEL_1 2412
#define OWL_80211_MHZ_CHANNEL_2 2417
#define OWL_80211_MHZ_CHANNEL_3 2422
@ -156,8 +230,10 @@ typedef struct _owl_autocalibration_order
#define OWL_80211_MHZ_CHANNEL_12 2467
#define OWL_80211_MHZ_CHANNEL_13 2472
#define OWL_80211_MHZ_CHANNEL_14 2477
//@}
/* Wi-Fi channel frequencies in Hz */
/** @name Wi-Fi channels' frequencies in Hz */
//@{
#define OWL_80211_HZ_CHANNEL_1 2412000000ul
#define OWL_80211_HZ_CHANNEL_2 2417000000ul
#define OWL_80211_HZ_CHANNEL_3 2422000000ul
@ -172,87 +248,137 @@ typedef struct _owl_autocalibration_order
#define OWL_80211_HZ_CHANNEL_12 2467000000ul
#define OWL_80211_HZ_CHANNEL_13 2472000000ul
#define OWL_80211_HZ_CHANNEL_14 2477000000ul
//@}
/* Misc. */
// Length of a MAC address in string format (including '\0')
/** @name String lengths */
//@{
/// Length of a MAC address in string format (including '\0')
#define OWL_ETHER_ADDR_STRLEN 18
// Maximum length of an algorithm name (including '\0')
/// Maximum length of an algorithm name (including '\0')
#define OWL_ALGORITHM_STRLEN 31
// Maximum length of an area name (including '\0')
/// Maximum length of an area name (including '\0')
#define OWL_AREA_STRLEN 31
// Maximum length of a coordinate X, Y or Z (including '\0')
/// Maximum length of a coordinate X, Y or Z (including '\0')
#define OWL_COORDINATE_STRLEN 16
//@}
/* Global variables */
// Used to handle end of loops:
/// Global variable used to handle end of loops
extern bool owl_run ;
/* Error codes */
/* User interface */
// Wrong program invokation (command-line arguments):
/** @name Error codes */
//@{
/// Wrong program invokation (command-line arguments)
#define OWL_ERR_BAD_USAGE 100
// Error when reading/parsing the configuration file:
/// Error when reading/parsing the configuration file
#define OWL_ERR_CONFIG_FILE 101
/* System */
// Error when creating a thread:
/// Error when creating a thread
#define OWL_ERR_THREAD_CREATE 110
// Wrong signal received:
/// Wrong signal received
#define OWL_ERR_BAD_SIGNAL 111
/* Network communication */
// Error when creating a socket:
/// Error when creating a socket
#define OWL_ERR_SOCKET_CREATE 120
// Error when sending a message on a socket:
/// Error when sending a message on a socket
#define OWL_ERR_SOCKET_SEND 121
// Error when reading from a socket:
/// Error when reading from a socket
#define OWL_ERR_SOCKET_RECV 122
/* Network interface / capture */
// Error when opening the capture interface:
/// Error when opening the capture interface
#define OWL_ERR_IFACE_PCAP_OPEN 130
// Error when reading the interface Wi-Fi mode:
/// Error when reading the interface Wi-Fi mode
#define OWL_ERR_IFACE_MODE_GET 131
// Error when setting the interface Wi-Fi mode:
/// Error when setting the interface Wi-Fi mode
#define OWL_ERR_IFACE_MODE_SET 132
//@}
/* Macros */
// Converts a bool to the corresponding string
/// Converts a bool to the corresponding string
#define OWL_BOOL_TO_STRING(B) ((B) ? "true" : "false")
/* Function headers */
// Misc
/** @name Miscellaneous */
//@{
/// Converts a MAC address from bytes to string
const char* owl_mac_bytes_to_string(const uint8_t *const mac_binary) ;
/// Converts a MAC address from bytes to string
void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary,
char mac_str[OWL_ETHER_ADDR_STRLEN]) ;
/// Compares two MAC addresses
bool owl_mac_equals(const uint8_t *const mac1,
const uint8_t *const mac2) ;
/// Converts a IEEE 802.11 frequency into a channel number
uint_fast8_t owl_frequency_to_channel(const uint_fast16_t frequency) ;
//@}
// Time
/** @name Time */
//@{
/// Sleeps for a given amount of milliseconds
int owl_msleep(uint32_t time_ms) ;
/// Sets the `owl_timestamp` `now` to the current time
int owl_timestamp_now(owl_timestamp *const now) ;
/// Converts a `struct timespec` to an `owl_timestamp`
void owl_timespec_to_timestamp(const struct timespec *const src,
owl_timestamp *const dst) ;
/// Converts a `struct timeval` to an `owl_timestamp`
void owl_timeval_to_timestamp(const struct timeval *const src,
owl_timestamp *const dst) ;
/// Compares two `owl_timestamp`
bool owl_timestamp_equals(const owl_timestamp *const d1,
const owl_timestamp *const d2) ;
/// Converts an `owl_timestamp` date value into milliseconds
uint64_t owl_timestamp_to_ms(const owl_timestamp *const d) ;
/// Converts an `owl_timestamp` date value into a printable string
void owl_timestamp_to_string(const owl_timestamp *const src,
char *const dst) ;
/// Returns the time (in milliseconds) between two dates
uint_fast32_t owl_time_elapsed_ms(const owl_timestamp *const d1,
const owl_timestamp *const d2) ;
/// Computes the time difference between two dates
void owl_time_elapsed(const owl_timestamp *const d1,
const owl_timestamp *const d2,
owl_timestamp *const elapsed) ;
//@}
// Endianess
/** @name Endianness */
//@{
/// Changes the endianness of an `owl_timestamp` from host to network
/// order
void owl_hton_timestamp(owl_timestamp *const d) ;
/// Changes the endianness of an `owl_timestamp` from network to host
/// order
void owl_ntoh_timestamp(owl_timestamp *const d) ;
/// Changes the order of the bytes of a `float`
float owl_swap_float(const float f) ;
//@}
/** @name Endianness-related macros */
//@{
/**
* @def owl_htonf
* @brief Changes the endianness of a `float` from host to network
*
* This macro converts the byte order of a `float` if needed, depending
* on the endianness of the host, to adopt the endianness of the network.
* To actually change the byte order, the `owl_swap_float()` function is
* used.
*
* @def owl_ntohf
* @brief Changes the endianness of a `float` from network to host
*
* This macro converts the byte order of a `float` encoded with a network
* endianness to adopt the endianness of the host, if the two endianness
* are different.
* To actually change the byte order, the `owl_swap_float()` function is
* used.
*/
//@}
#if __BYTE_ORDER == __BIG_ENDIAN
# define owl_htonf(f) (f)
# define owl_ntohf(f) (f)
@ -265,20 +391,33 @@ float owl_swap_float(const float f) ;
# endif // __BYTE_ORDER == __LITTLE_ENDIAN
#endif // __BYTE_ORDER == __BIG_ENDIAN
// Network
/** @name Network */
//@{
/// Opens a UDP transmission socket
int owl_create_udp_trx_socket(const char *const server_address,
const uint_fast16_t server_port,
struct sockaddr_in *const server_description,
struct sockaddr_in *const client_description) ;
/// Opens a UDP reception socket
int owl_create_udp_listening_socket(const uint_fast16_t port) ;
//@}
// Signals
/** @name Signals */
//@{
/// Generic signal handler for SIGINT
void owl_sigint_handler(const int num) ;
/// Generic signal handler for SIGTERM
void owl_sigterm_handler(const int num) ;
//@}
// Threads
/** @name Threads */
//@{
/// Closes the file descriptor `fd`
void owl_close_fd(void *const fd) ;
/// Closes the stream `file`
void owl_close_file(void *const file) ;
//@}
#ifdef __cplusplus