improve the doxygen docu of PStartupHandler.*

This commit is contained in:
2025-11-23 17:35:31 +01:00
parent 736c96c66e
commit 9452d7ec6b
2 changed files with 594 additions and 63 deletions

View File

@@ -49,15 +49,36 @@ ClassImpQ(PStartupHandler)
// It is needed because in certain environments ParseFile does not work but ParseBuffer does.
//--------------------------------------------------------------------------
/**
* <p> Replacement for the ParseFile method of TSAXParser.
* \brief Replacement for TSAXParser::ParseFile() that uses buffer-based parsing.
*
* <p><b>return:</b>
* - 1 if file cannot be read
* - 0 if the file has been parsed successfully
* - parse error code otherwise
* This function provides a workaround for environments where the standard
* TSAXParser::ParseFile() method fails but ParseBuffer() works correctly.
* It reads the entire XML file into memory and then parses it as a buffer.
*
* \param saxParser pointer to a TSAXParser object
* \param startup_path_name full path to the XML file to be read
* <b>Algorithm:</b>
* -# Open XML file in binary mode, positioned at end to determine size
* -# Allocate buffer for entire file content
* -# Read file into buffer
* -# Close file
* -# Call saxParser->ParseBuffer() with buffer contents
* -# Free buffer memory
*
* <b>Memory Management:</b>
* The function allocates a buffer equal to the file size, which is freed
* after parsing completes. For very large XML files, this may consume
* significant memory temporarily.
*
* \param saxParser Pointer to an initialized TSAXParser object. The parser
* should have its signal slots connected to a handler object
* (e.g., PStartupHandler) before calling this function.
* \param startup_path_name Full filesystem path to the XML file to be parsed.
*
* \return Parse status code:
* - 0: Success (file parsed without errors)
* - 1: File could not be opened or read
* - Other: XML parse error code from TSAXParser::ParseBuffer()
*
* \see PStartupHandler for the XML content handler implementation
*/
int parseXmlFile(TSAXParser *saxParser, const char *startup_path_name)
{
@@ -89,7 +110,40 @@ int parseXmlFile(TSAXParser *saxParser, const char *startup_path_name)
// Constructor
//--------------------------------------------------------------------------
/**
* <p>Constructor. Check if the musrfit_startup.xml file is found in some standard search paths
* \brief Constructor that locates and optionally resets the musrfit startup configuration.
*
* Searches for the musrfit_startup.xml configuration file in standard locations
* and initializes the handler. If no file is found, creates a default configuration.
*
* <b>Search Order:</b>
* -# Current working directory: \c ./musrfit_startup.xml
* -# User config directory: \c $HOME/.musrfit/musrfit_startup.xml
* -# MUSRFITPATH environment variable: \c $MUSRFITPATH/musrfit_startup.xml
* -# ROOT installation: \c $ROOTSYS/bin/musrfit_startup.xml (with warning)
*
* <b>File Creation:</b>
* If no startup file is found in any location, a default configuration is
* automatically created at \c $HOME/.musrfit/musrfit_startup.xml. This includes:
* - Standard PSI facility data paths
* - Run name templates for all PSI instruments
* - Default Fourier transform settings
* - Standard marker and color lists
*
* <b>Reset Mode:</b>
* When reset_startup_file=true and a file is found, the existing file is
* overwritten with default content. This is useful for:
* - Restoring corrupted configurations
* - Updating to new default settings after software updates
* - Resetting user customizations to defaults
*
* \param reset_startup_file If true, overwrites existing startup file with defaults.
* If false (default), uses existing file or creates new one.
*
* \note This constructor only locates the file. Actual XML parsing must be
* performed separately by connecting this handler to a TSAXParser and
* calling parseXmlFile().
*
* \see StartupFileFound(), GetStartupFilePath(), WriteDefaultStartupFile()
*/
PStartupHandler::PStartupHandler(bool reset_startup_file)
{
@@ -178,7 +232,16 @@ PStartupHandler::PStartupHandler(bool reset_startup_file)
// Destructor
//--------------------------------------------------------------------------
/**
* <p>Destructor
* \brief Destructor that releases all allocated configuration data.
*
* Clears all configuration vectors to free memory:
* - fDataPathList: Data file search paths
* - fMarkerList: ROOT marker style codes
* - fColorList: ROOT color codes
* - fRunNameTemplate: Instrument run name patterns
*
* \note The Fourier defaults structure is a value type and is automatically
* cleaned up when the object is destroyed.
*/
PStartupHandler::~PStartupHandler()
{
@@ -193,7 +256,25 @@ PStartupHandler::~PStartupHandler()
// OnStartDocument
//--------------------------------------------------------------------------
/**
* <p>Called on start of the XML file reading. Initializes all necessary variables.
* \brief SAX callback invoked at the start of XML document parsing.
*
* Initializes all configuration variables to default values before parsing
* begins. This ensures a clean state even if the same handler is reused.
*
* <b>Initialization:</b>
* - fKey = eEmpty (no active element)
* - Fourier defaults:
* - fFourierBlockPresent = false
* - fUnits = FOURIER_UNIT_GAUSS
* - fFourierPower = 0 (no zero-padding)
* - fApodization = FOURIER_APOD_NONE
* - fPlotTag = FOURIER_PLOT_REAL_AND_IMAG
* - fRangeForPhaseCorrection = [-1.0, -1.0] (auto)
* - fPlotRange = [-1.0, -1.0] (auto)
* - fPhaseIncrement = 1.0 degree
*
* \note This is a SAX parser callback connected via TQObject signals.
* It is automatically called by TSAXParser at document start.
*/
void PStartupHandler::OnStartDocument()
{
@@ -220,7 +301,16 @@ void PStartupHandler::OnStartDocument()
// OnEndDocument
//--------------------------------------------------------------------------
/**
* <p>Called on end of XML file reading.
* \brief SAX callback invoked at the end of XML document parsing.
*
* Finalizes configuration by calling CheckLists() to ensure all required
* settings have values. If any list is empty after parsing, it will be
* populated with default values.
*
* \note This is a SAX parser callback connected via TQObject signals.
* It is automatically called by TSAXParser when parsing completes.
*
* \see CheckLists()
*/
void PStartupHandler::OnEndDocument()
{
@@ -232,11 +322,33 @@ void PStartupHandler::OnEndDocument()
// OnStartElement
//--------------------------------------------------------------------------
/**
* <p>Called when a XML start element is found. Filters out the needed elements
* and sets a proper key.
* \brief SAX callback invoked when an XML start element tag is encountered.
*
* \param str XML element name
* \param attributes not used
* Identifies the element type and sets the parsing state (fKey) accordingly.
* This state is used by OnCharacters() to determine how to process element content.
*
* <b>Recognized Elements:</b>
* - \c data_path → eDataPath (data file search directory)
* - \c run_name_template → eRunNameTemplate (with inst attribute extraction)
* - \c marker → eMarker (ROOT marker style code)
* - \c color → eColor (RGB color specification)
* - \c units → eUnits (Fourier frequency units)
* - \c fourier_power → eFourierPower (zero-padding power)
* - \c apodization → eApodization (windowing function)
* - \c plot → ePlot (Fourier plot type)
* - \c phase → ePhase (Fourier phase value)
* - \c phase_increment → ePhaseIncrement (phase adjustment step)
*
* <b>Attribute Handling:</b>
* For \c run_name_template elements, extracts the \c inst attribute value
* and stores it in fCurrentInstrumentName for use when processing the
* element content.
*
* \param str XML element name (tag name without angle brackets)
* \param attributes TList of TXMLAttr objects containing element attributes
*
* \note Unrecognized elements leave fKey unchanged (typically eEmpty),
* causing their content to be ignored.
*/
void PStartupHandler::OnStartElement(const Char_t *str, const TList *attributes)
{
@@ -276,9 +388,15 @@ void PStartupHandler::OnStartElement(const Char_t *str, const TList *attributes)
// OnEndElement
//--------------------------------------------------------------------------
/**
* <p>Called when a XML end element is found. Resets the handler key.
* \brief SAX callback invoked when an XML end element tag is encountered.
*
* \param str not used
* Resets the parsing state (fKey) to eEmpty, indicating that any subsequent
* character data should be ignored until the next start element is found.
*
* \param str XML element name (unused, state is always reset to eEmpty)
*
* \note The element name parameter is not used because all elements reset
* to the same state. This simplifies handling of nested elements.
*/
void PStartupHandler::OnEndElement(const Char_t *str)
{
@@ -289,10 +407,53 @@ void PStartupHandler::OnEndElement(const Char_t *str)
// OnCharacters
//--------------------------------------------------------------------------
/**
* <p>Content of a given XML element. Filters out the data and feeds them to
* the internal variables.
* \brief SAX callback invoked with text content between XML element tags.
*
* \param str XML element string
* Processes element content based on the current parsing state (fKey) set
* by OnStartElement(). Each element type has specific parsing logic and
* validation.
*
* <b>Element Processing:</b>
*
* - <b>eDataPath:</b> Adds path string directly to fDataPathList
*
* - <b>eRunNameTemplate:</b> Creates PRunNameTemplate with current instrument
* name and template string, adds to fRunNameTemplate
*
* - <b>eMarker:</b> Validates numeric string, converts to int, adds to fMarkerList
*
* - <b>eColor:</b> Parses "R,G,B" format (comma-separated integers 0-255),
* converts to ROOT color code via TColor::GetColor(), adds to fColorList
*
* - <b>eUnits:</b> Maps string to FOURIER_UNIT_* constant:
* - "gauss" → FOURIER_UNIT_GAUSS
* - "tesla" → FOURIER_UNIT_TESLA
* - "mhz" → FOURIER_UNIT_FREQ
* - "mc/s" → FOURIER_UNIT_CYCLES
*
* - <b>eFourierPower:</b> Validates integer 0-20, sets fFourierDefaults.fFourierPower
*
* - <b>eApodization:</b> Maps string to FOURIER_APOD_* constant:
* - "none" → FOURIER_APOD_NONE
* - "weak" → FOURIER_APOD_WEAK
* - "medium" → FOURIER_APOD_MEDIUM
* - "strong" → FOURIER_APOD_STRONG
*
* - <b>ePlot:</b> Maps string to FOURIER_PLOT_* constant:
* - "real" → FOURIER_PLOT_REAL
* - "imag" → FOURIER_PLOT_IMAG
* - "real_and_imag" → FOURIER_PLOT_REAL_AND_IMAG
* - "power" → FOURIER_PLOT_POWER
* - "phase" → FOURIER_PLOT_PHASE
*
* - <b>ePhase:</b> Validates float, adds to fFourierDefaults.fPhase vector
*
* - <b>ePhaseIncrement:</b> Validates float, sets fFourierDefaults.fPhaseIncrement
*
* \param str Text content between XML tags
*
* \note Invalid values generate warning messages to stderr but do not cause
* parsing to fail. The invalid value is simply ignored.
*/
void PStartupHandler::OnCharacters(const Char_t *str)
{
@@ -475,9 +636,14 @@ void PStartupHandler::OnCharacters(const Char_t *str)
// OnComment
//--------------------------------------------------------------------------
/**
* <p>Called when a XML comment is found. Not used.
* \brief SAX callback invoked when an XML comment is encountered.
*
* \param str not used.
* Currently does nothing. XML comments in the startup file are ignored.
*
* \param str Comment text content (without \<!-- and --\> delimiters)
*
* \note Comments in musrfit_startup.xml are for documentation purposes only
* and have no effect on configuration.
*/
void PStartupHandler::OnComment(const Char_t *str)
{
@@ -488,9 +654,17 @@ void PStartupHandler::OnComment(const Char_t *str)
// OnWarning
//--------------------------------------------------------------------------
/**
* <p>Called when the XML parser emits a warning.
* \brief SAX callback invoked when the XML parser generates a warning.
*
* \param str warning string
* Outputs the warning message to stderr with a "PStartupHandler **WARNING**"
* prefix. Warnings typically indicate non-fatal issues such as:
* - Deprecated XML constructs
* - Minor schema violations
* - Character encoding issues
*
* \param str Warning message from the XML parser
*
* \note Parsing continues after warnings; they do not cause failure.
*/
void PStartupHandler::OnWarning(const Char_t *str)
{
@@ -502,9 +676,18 @@ void PStartupHandler::OnWarning(const Char_t *str)
// OnError
//--------------------------------------------------------------------------
/**
* <p>Called when the XML parser emits an error.
* \brief SAX callback invoked when the XML parser encounters an error.
*
* \param str error string
* Outputs the error message to stderr with a "PStartupHandler **ERROR**"
* prefix. Errors indicate significant parsing problems such as:
* - Malformed XML syntax
* - Missing required elements
* - Invalid attribute values
*
* \param str Error message from the XML parser
*
* \note Depending on error severity, parsing may or may not continue.
* The configuration may be incomplete after errors.
*/
void PStartupHandler::OnError(const Char_t *str)
{
@@ -516,9 +699,19 @@ void PStartupHandler::OnError(const Char_t *str)
// OnFatalError
//--------------------------------------------------------------------------
/**
* <p>Called when the XML parser emits a fatal error.
* \brief SAX callback invoked when the XML parser encounters a fatal error.
*
* \param str fatal error string
* Outputs the error message to stderr with a "PStartupHandler **FATAL ERROR**"
* prefix. Fatal errors indicate unrecoverable parsing failures such as:
* - Document not well-formed (mismatched tags)
* - Invalid XML declaration
* - Character encoding that cannot be processed
*
* \param str Fatal error message from the XML parser
*
* \warning After a fatal error, parsing stops immediately and the configuration
* will be incomplete. CheckLists() will provide default values for
* missing settings when OnEndDocument() is called.
*/
void PStartupHandler::OnFatalError(const Char_t *str)
{
@@ -530,10 +723,17 @@ void PStartupHandler::OnFatalError(const Char_t *str)
// OnCdataBlock
//--------------------------------------------------------------------------
/**
* <p>Not used.
* \brief SAX callback invoked when a CDATA section is encountered.
*
* \param str not used
* \param len not used
* Currently does nothing. CDATA sections in the startup file are not used.
* CDATA sections would typically be used for content containing special
* characters that would otherwise need escaping.
*
* \param str CDATA content (without \<![CDATA[ and ]]\> delimiters)
* \param len Length of the CDATA content in characters
*
* \note The musrfit_startup.xml format does not require CDATA sections
* as all content uses standard XML escaping where needed.
*/
void PStartupHandler::OnCdataBlock(const Char_t *str, Int_t len)
{
@@ -544,8 +744,35 @@ void PStartupHandler::OnCdataBlock(const Char_t *str, Int_t len)
// CheckLists
//--------------------------------------------------------------------------
/**
* <p>Check if the default lists are present and if not, feed them with some default settings
* \brief Validates configuration lists and populates empty ones with defaults.
*
* Called at the end of XML parsing (OnEndDocument) to ensure all required
* configuration lists have values. If any list is empty after parsing,
* it is populated with sensible defaults.
*
* <b>Default Data Paths:</b>
* Standard PSI facility data directories:
* - /mnt/data/nemu/his, /mnt/data/nemu/wkm
* - /afs/psi.ch/project/nemu/data/his, /afs/psi.ch/project/nemu/data/wkm
* - /afs/psi.ch/project/bulkmusr/data/gps, dolly, gpd, ltf, alc
*
* <b>Default Markers:</b>
* ROOT TMarker style codes for distinguishing multiple data sets:
* - 24 (open circle), 25 (open square), 26 (open triangle)
* - 27 (open diamond), 28 (open cross), 29 (full star)
* - 30 (open star), 20 (full circle), 21 (full square)
* - 22 (full triangle), 23 (full down triangle)
* - 2 (thin cross), 3 (thin star), 5 (thin x)
*
* <b>Default Colors:</b>
* Standard plotting colors (RGB → ROOT color code):
* - Black (0,0,0), Red (255,0,0), Green (0,255,0)
* - Blue (0,0,255), Magenta (255,0,255), Cyan (0,255,255)
* - Violet (156,0,255), Yellow-ish (99,101,49)
* - Dark Green (49,101,49), Orange (156,48,0)
*
* \note This method only populates empty lists. If a list has any entries
* from the XML file, no defaults are added.
*/
void PStartupHandler::CheckLists()
{
@@ -601,13 +828,18 @@ void PStartupHandler::CheckLists()
// StartupFileExists
//--------------------------------------------------------------------------
/**
* <p>Checks if a file is present on the disc.
* \brief Checks if a file exists and is readable at the specified path.
*
* <b>return:</b>
* - true, if the file is present
* - false, otherwise
* Attempts to open the file for reading to verify its existence and
* accessibility. The file is immediately closed after the check.
*
* \param fln file name
* \param fln Full filesystem path to the file to check
*
* \return true if file exists and can be opened for reading,
* false if file does not exist or cannot be accessed
*
* \note This method uses std::ifstream for portability across platforms.
* It only checks readability, not write permissions.
*/
Bool_t PStartupHandler::StartupFileExists(Char_t *fln)
{
@@ -628,6 +860,52 @@ Bool_t PStartupHandler::StartupFileExists(Char_t *fln)
//--------------------------------------------------------------------------
// WriteDefaultStartupFile
//--------------------------------------------------------------------------
/**
* \brief Creates or overwrites a startup configuration file with default content.
*
* Writes a complete musrfit_startup.xml file containing comprehensive default
* settings for the musrfit package. This method is called when:
* - No startup file is found in any search location
* - User requests reset of existing configuration (reset_startup_file=true)
*
* <b>File Location:</b>
* - If reset_startup_file=true: Overwrites file at fStartupFilePath
* - If reset_startup_file=false: Creates new file at $HOME/.musrfit/musrfit_startup.xml
* (creates .musrfit directory if it doesn't exist)
*
* <b>Default Content Includes:</b>
*
* <b>Data Paths:</b>
* - PSI LEM, GPS, GPD, Dolly, Flame, HIFI, LTF, ALC data directories
* - Both local mount points and AFS paths
*
* <b>Run Name Templates:</b>
* - Templates for all PSI μSR instruments (GPS, GPD, Dolly, Flame, etc.)
* - Templates for various data formats (ROOT, binary, MDU)
* - Year and run number placeholder patterns
*
* <b>Fourier Settings:</b>
* - Units: Gauss
* - Fourier power: 0 (no zero-padding)
* - Apodization: none
* - Plot type: real_and_imag
* - Phase: 0.0 degrees
* - Phase increment: 1.0 degree
*
* <b>ROOT Settings:</b>
* - Marker list: 14 distinct marker styles
* - Color list: 10 distinct colors (RGB format)
*
* \param reset_startup_file If true, overwrites existing file at fStartupFilePath.
* If false, creates new file at $HOME/.musrfit/musrfit_startup.xml.
*
* \return true if file was successfully written, false on error:
* - $HOME environment variable not set
* - Cannot create .musrfit directory
* - Cannot open file for writing
*
* \see PStartupHandler() constructor, CheckLists()
*/
Bool_t PStartupHandler::WriteDefaultStartupFile(bool reset_startup_file)
{
Char_t startup_path_name[256];