-
Notifications
You must be signed in to change notification settings - Fork 0
Modify filecontentsserver to take an output file #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rerpha
wants to merge
8
commits into
master
Choose a base branch
from
tpar_2
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
20dd9f6
Modifying filecontentsserver to take an output file
rerpha 51a5608
use getStringParam with std::string
rerpha 656ecfc
use binary for open and save, use ifstream for open, use NULL compari…
rerpha a30afdb
Trap both NULL and zero length
FreddieAkeroyd ac52cf5
Update FileContentsServerApp/src/FileContentsServerDriver.cpp
rerpha fb5eddf
Adjust comment
FreddieAkeroyd 56a6f26
Merge branch 'tpar_2' of https://github.com/ISISComputingGroup/EPICS-…
FreddieAkeroyd 0ce321e
Remove newFileWarning as no longer used
FreddieAkeroyd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,14 +5,13 @@ | |
| #include <math.h> | ||
| #include <exception> | ||
| #include <iostream> | ||
| #include <format> | ||
| #include <map> | ||
| #include <list> | ||
| #include <vector> | ||
| #include <iomanip> | ||
| #include <fstream> | ||
| #include <sys/timeb.h> | ||
| #include <boost/algorithm/string.hpp> | ||
| #include <boost/algorithm/string/join.hpp> | ||
| #include <sstream> | ||
|
|
||
| #include <epicsTypes.h> | ||
|
|
@@ -40,9 +39,9 @@ | |
|
|
||
| static const char *driverName = "FileContentsServerDriver"; | ||
|
|
||
| FileContentsServerDriver::FileContentsServerDriver(const char *portName, const char *fileDir) | ||
| FileContentsServerDriver::FileContentsServerDriver(const char *portName, const char *fileDir, const char *inputFile, const char *outputFile) | ||
| : asynPortDriver(portName, | ||
| 0, /* maxAddr */ | ||
| 0, /* maxAddr */ | ||
| asynInt32Mask | asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynOctetMask | asynDrvUserMask, /* Interface mask */ | ||
| asynInt32Mask | asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynOctetMask, /* Interrupt mask */ | ||
| ASYN_CANBLOCK, /* asynFlags. This driver can block but it is not multi-device */ | ||
|
|
@@ -52,30 +51,85 @@ FileContentsServerDriver::FileContentsServerDriver(const char *portName, const c | |
| m_fileDir(fileDir) | ||
| { | ||
| const char *functionName = "FileContentsServerDriver"; | ||
| createParam(P_fileNameString, asynParamOctet, &P_fileName); | ||
|
|
||
| createParam(P_inputFileNameString, asynParamOctet, &P_inputFileName); | ||
| createParam(P_outputFileNameString, asynParamOctet, &P_outputFileName); | ||
| createParam(P_fileContentsString, asynParamOctet, &P_fileContents); | ||
| createParam(P_saveFileString, asynParamInt32, &P_saveFile); | ||
| createParam(P_resetString, asynParamInt32, &P_reset); | ||
| createParam(P_fileDirString, asynParamOctet, &P_fileDir); | ||
| createParam(P_logString, asynParamOctet, &P_log); | ||
| createParam(P_newFileWarningString, asynParamInt32, &P_newFileWarning); | ||
| createParam(P_unsavedChangesString, asynParamInt32, &P_unsavedChanges); | ||
|
|
||
| setStringParam(P_fileDir, fileDir); | ||
| setStringParam(P_inputFileName, inputFile); | ||
|
|
||
| // Read the original contents in first. | ||
| readFile(); | ||
|
|
||
| if (outputFile && *outputFile) | ||
| { | ||
| setStringParam(P_outputFileName, outputFile); | ||
| // Save the file so that the output file has the contents of the input file initially. | ||
| saveFile(); | ||
| } | ||
| else | ||
| { | ||
| // If the output file is not specified, default to saving output to the input file. | ||
| setStringParam(P_outputFileName, inputFile); | ||
| } | ||
|
|
||
| const int defaultSaveFile = 0; | ||
| setIntegerParam(P_saveFile, defaultSaveFile); | ||
| const int defaultReset = 0; | ||
| setIntegerParam(P_reset, defaultReset); | ||
| const int defaultNewFileWarning = 0; | ||
| setIntegerParam(P_newFileWarning, defaultNewFileWarning); | ||
| const int defaultUnsavedChanges = 0; | ||
| setIntegerParam(P_unsavedChanges, defaultUnsavedChanges); | ||
| setStringParam(P_fileContents, ""); | ||
| setStringParam(P_log, ""); | ||
| logMessage("Editor initialized"); | ||
| callParamCallbacks(); | ||
| } | ||
|
|
||
| asynStatus FileContentsServerDriver::saveFile() | ||
| { | ||
| logMessage("Triggering save"); | ||
|
|
||
| std::string buffer; | ||
|
|
||
| // Get the value of the parameter we just set | ||
| getStringParam(P_fileContents, buffer); | ||
|
|
||
| std::string fileName; | ||
| getStringParam(P_outputFileName, fileName); | ||
| // join the file name with the file directory | ||
| std::string fullFileName = m_fileDir + "/" + fileName; | ||
| // Write the contents of buffer to a file | ||
| try | ||
| { | ||
| std::ofstream outfile(fullFileName, std::ios::trunc | std::ios::binary); // Open in write mode | ||
| if (outfile.is_open()) | ||
| { | ||
| outfile << buffer; | ||
| outfile.close(); | ||
| logMessage("File saved successfully"); | ||
| setIntegerParam(P_saveFile, 0); | ||
| setIntegerParam(P_unsavedChanges, 0); | ||
| } | ||
| else | ||
| { | ||
| logMessage(std::format("Failed to open file ({}) for writing", fullFileName)); | ||
| return asynError; | ||
| } | ||
| } | ||
| catch (const std::exception &e) | ||
| { | ||
| logMessage(e.what()); | ||
| return asynError; | ||
| } | ||
| callParamCallbacks(); | ||
| return asynSuccess; | ||
| } | ||
|
|
||
| // Override the method to handle writes to parameters | ||
| asynStatus FileContentsServerDriver::writeInt32(asynUser *pasynUser, epicsInt32 value) | ||
| { | ||
|
|
@@ -85,55 +139,17 @@ asynStatus FileContentsServerDriver::writeInt32(asynUser *pasynUser, epicsInt32 | |
| { | ||
| if (value == 1 && hasChanged == 1) | ||
| { | ||
| std::cout << "Triggering save" << std::endl; | ||
| std::cout << "Value received by asyn: " << value << std::endl; | ||
|
|
||
| char buffer[5000]; // Assuming the response will fit within 256 characters | ||
|
|
||
| // Get the value of the parameter we just set | ||
| getStringParam(P_fileContents, sizeof(buffer), buffer); | ||
|
|
||
| char fileName[512]; | ||
| getStringParam(P_fileName, sizeof(fileName), fileName); | ||
| // join the file name with the file directory | ||
| std::string m_fullFileName = m_fileDir + "/" + fileName; | ||
| // Write the contents of buffer to a file | ||
| try | ||
| { | ||
| std::ofstream outfile(m_fullFileName, std::ios::trunc | std::ios::binary); // Open in write mode | ||
| if (outfile.is_open()) | ||
| { | ||
| outfile << buffer; | ||
| outfile.close(); | ||
| std::cout << "Contents written to file successfully." << std::endl; | ||
| logMessage("File saved successfully"); | ||
| setIntegerParam(P_saveFile, 0); | ||
| setIntegerParam(P_newFileWarning, 0); | ||
| setIntegerParam(P_unsavedChanges, 0); | ||
| } | ||
| else | ||
| { | ||
| std::cerr << "Failed to open file for writing." << std::endl; | ||
| logMessage("Failed to open file for writing"); | ||
| return asynError; | ||
| } | ||
| } | ||
| catch (const std::exception &e) | ||
| { | ||
| std::cerr << "Exception caught: " << e.what() << std::endl; | ||
| logMessage(e.what()); | ||
| return asynError; | ||
| } | ||
| callParamCallbacks(); | ||
| return saveFile(); | ||
| } | ||
| return asynSuccess; | ||
| } | ||
| else if (pasynUser->reason == P_reset) | ||
| { | ||
| if (value == 1) | ||
| { | ||
| std::cout << "Resetting" << std::endl; | ||
| logMessage("Reloading from disk"); | ||
| setStringParam(P_fileContents, m_original_lines_array); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't actually reloading from disk, it is resetting to what was there the first time it loaded from disk. Is that what the users would expect? |
||
| saveFile(); | ||
| logMessage("Reset successful."); | ||
| setIntegerParam(P_reset, 0); | ||
| setIntegerParam(P_unsavedChanges, 0); | ||
|
|
@@ -147,7 +163,7 @@ asynStatus FileContentsServerDriver::writeInt32(asynUser *pasynUser, epicsInt32 | |
| } | ||
| } | ||
|
|
||
| void FileContentsServerDriver::logMessage(const std::string& message) | ||
| void FileContentsServerDriver::logMessage(const std::string &message) | ||
| { | ||
| // add the time to the front of the log message | ||
| // current time | ||
|
|
@@ -162,38 +178,38 @@ void FileContentsServerDriver::logMessage(const std::string& message) | |
| // Create the log message | ||
| std::string log_message = std::string(time_str) + ": " + message; | ||
|
|
||
| std::cout << log_message << std::endl; | ||
| setStringParam(P_log, log_message); | ||
| callParamCallbacks(); | ||
| } | ||
|
|
||
| void FileContentsServerDriver::readFile() | ||
| { | ||
| std::cout << "Calling readFile" << std::endl; | ||
| std::fstream f; | ||
| char fileName[256]; | ||
| getStringParam(P_fileName, sizeof(fileName), fileName); | ||
| std::string m_fullFileName = m_fileDir + "/" + fileName; | ||
| std::cout << "FileContentsServerDriver: Reading file " << m_fullFileName << std::endl; | ||
| std::ifstream f; | ||
| std::string fileName; | ||
| getStringParam(P_inputFileName, fileName); | ||
| std::string fullFileName = m_fileDir + "/" + fileName; | ||
|
|
||
| logMessage(std::format("Reading file {}", fullFileName)); | ||
| try | ||
| { | ||
| f.open(m_fullFileName, std::ios::in); | ||
| f.open(fullFileName, std::ios::binary); | ||
| if (!f.is_open()) | ||
| { | ||
| m_original_lines_array = ""; | ||
| setStringParam(P_fileContents, ""); | ||
| if (errno == ENOENT) // File not found | ||
| { | ||
| std::cout << "File not found: " + m_fullFileName << std::endl; | ||
| setIntegerParam(P_newFileWarning, 1); | ||
| throw std::runtime_error("File not found"); | ||
| logMessage(std::format("File not found: {}", fullFileName)); | ||
| throw std::runtime_error("File not found"); | ||
| } | ||
| else // Other errors, e.g., permission denied | ||
| { | ||
| std::cerr << "Unable to open file: " + m_fullFileName << std::endl; | ||
| throw std::runtime_error(std::string("Unable to open file: ") + std::string(strerror(errno))); | ||
| logMessage(std::format("Unable to open file: {}, error {}", fullFileName, std::string(strerror(errno)))); | ||
| throw std::runtime_error(std::string("Unable to open file: ") + std::string(strerror(errno))); | ||
| } | ||
| } | ||
| setIntegerParam(P_newFileWarning, 0); | ||
| int i = 0; | ||
|
|
||
| std::stringstream buffer; | ||
|
|
@@ -209,7 +225,7 @@ void FileContentsServerDriver::readFile() | |
| catch (const std::exception &e) | ||
| { | ||
| std::cerr << "Exception caught: " << e.what() << std::endl; | ||
| logMessage(e.what()); | ||
| logMessage(e.what()); | ||
| } | ||
|
|
||
| callParamCallbacks(); | ||
|
|
@@ -235,12 +251,6 @@ asynStatus FileContentsServerDriver::writeOctet(asynUser *pasynUser, const char | |
| setIntegerParam(P_unsavedChanges, 0); | ||
| } | ||
| } | ||
| else if (function == P_fileName) | ||
| { | ||
| std::cout << "Setting file name to " << value << std::endl; | ||
| setStringParam(P_fileName, value); | ||
| readFile(); | ||
| } | ||
| else | ||
| { | ||
| return asynPortDriver::writeOctet(pasynUser, value, maxChars, nActual); | ||
|
|
@@ -259,11 +269,11 @@ extern "C" | |
|
|
||
| /// \param[in] portName @copydoc initArg0 | ||
| /// \param[in] fileDir @copydoc initArg1 | ||
| int FileContentsServerConfigure(const char *portName, const char *fileDir) | ||
| int FileContentsServerConfigure(const char *portName, const char *fileDir, const char *inputFile, const char *outputFile) | ||
| { | ||
| try | ||
| { | ||
| FileContentsServerDriver *driver = new FileContentsServerDriver(portName, fileDir); | ||
| FileContentsServerDriver *driver = new FileContentsServerDriver(portName, fileDir, inputFile, outputFile); | ||
| if (driver == NULL) | ||
| { | ||
| errlogSevPrintf(errlogMajor, "FileContentsServerConfigure failed (NULL)\n"); | ||
|
|
@@ -283,17 +293,21 @@ extern "C" | |
|
|
||
| // EPICS iocsh shell commands | ||
|
|
||
| static const iocshArg initArg0 = {"portName", iocshArgString}; ///< The name of the asyn driver port we will create | ||
| static const iocshArg initArg1 = {"fileDir", iocshArgString}; ///< file name | ||
| static const iocshArg initArg0 = {"portName", iocshArgString}; ///< The name of the asyn driver port we will create | ||
| static const iocshArg initArg1 = {"fileDir", iocshArgString}; ///< The directory to open/save files into | ||
| static const iocshArg initArg2 = {"inputFile", iocshArgString}; ///< input file name to read and initially serve contents of | ||
| static const iocshArg initArg3 = {"outputFile", iocshArgString}; ///< file name to save output to when a user hits save. If not set this defaults to inputFile. | ||
|
|
||
| static const iocshArg *const initArgs[] = {&initArg0, | ||
| &initArg1}; | ||
| &initArg1, | ||
| &initArg2, | ||
| &initArg3}; | ||
|
|
||
| static const iocshFuncDef initFuncDef = {"FileContentsServerConfigure", sizeof(initArgs) / sizeof(iocshArg *), initArgs}; | ||
|
|
||
| static void initCallFunc(const iocshArgBuf *args) | ||
| { | ||
| FileContentsServerConfigure(args[0].sval, args[1].sval); | ||
| FileContentsServerConfigure(args[0].sval, args[1].sval, args[2].sval, args[3].sval); | ||
| } | ||
|
|
||
| static void FileContentsServerRegister(void) | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.