Skip to content
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

Issue #57 - Recover responsiveness to stdin and upgrade strOrFile #140

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0086563
Initial tests indicate I am successfully ungetting content to the ung…
wbkboyer Jan 24, 2025
72509a7
Implemented sf_ReadInteger() and confirmed AdjList version of nauty e…
wbkboyer Jan 27, 2025
60ce360
Want to make sure we only allow valid negative integers and bail out …
wbkboyer Jan 28, 2025
a2cab2e
Refactored to use stack for ungetBuf
wbkboyer Jan 29, 2025
c44a9ff
Merge branch 'master' into Issue57-strOrFileHandleStdin
wbkboyer Jan 30, 2025
12d7aec
Confirmed reading LEDA graph works by transforming nauty example (in …
wbkboyer Jan 30, 2025
271e191
Added sf_ReadSingleDigit() to help _ReadAdjMatrix(), updated paramete…
wbkboyer Jan 31, 2025
75406da
Added new function to g6-read-iterator.c, _ReadGraphFromG6StrOrFile()…
wbkboyer Jan 31, 2025
d02c8b3
-test passes, indicating reading from both pFile and theStr is succes…
wbkboyer Feb 4, 2025
c6af035
Debugging required; seems to be breaking down on -test for in-memory…
wbkboyer Feb 6, 2025
a74a1f9
Fixed bug where G6WriteIterator cleanup meant that outputContainer wa…
wbkboyer Feb 6, 2025
8782df0
-test passes; must still test to ensure RandomGraphs() and TestAllGra…
wbkboyer Feb 7, 2025
8e1714a
Changed function signatures of sf_ReadSkipWhitespace() and sf_ReadSki…
wbkboyer Feb 7, 2025
c456e80
Resolving some warnings from MSVC cl and MinGW-w64 UCRT gcc
wbkboyer Feb 10, 2025
ca03869
Merge branch 'master' into Issue57-strOrFileHandleStdin
wbkboyer Feb 10, 2025
2fcc012
Refactor so that extraData is now a null-terminated char * (rather th…
wbkboyer Feb 10, 2025
1540b64
Added newline to end of hand-written LEDA translation of nauty_exampl…
wbkboyer Feb 10, 2025
74c3339
Minor fix - need to make sure outputStr is not NULL before trying to …
wbkboyer Feb 11, 2025
8a25a54
Return NULL from sf_New() if containerType is OUTPUT_CONTAINER and ye…
wbkboyer Feb 12, 2025
b285c85
Minor bugfix: when stdout or stderr chosen as output stream, incorrec…
wbkboyer Feb 13, 2025
c8fe178
Fixed bug where accessing SpecificGraph() from menu allowed user to s…
wbkboyer Feb 13, 2025
c3f34f5
Addressing PR comments; all manual tests plus command-line -test pass
wbkboyer Feb 14, 2025
7f4bc04
Addressing PR comments:
wbkboyer Feb 14, 2025
c2f48da
Fixed issue with incorrect exitCode being returned from _ReadGraphFro…
wbkboyer Feb 20, 2025
cf568bf
Changed amount of stack-allocated memory for containing the numberStr…
wbkboyer Feb 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions c/graphLib/extensionSystem/graphFunctionTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ extern "C"
int (*fpEnsureArcCapacity)(graphP, int);
int (*fpSortVertices)(graphP);

int (*fpReadPostprocess)(graphP, void *, long);
int (*fpWritePostprocess)(graphP, void **, long *);
int (*fpReadPostprocess)(graphP, char *);
int (*fpWritePostprocess)(graphP, char **);

void (*fpHideEdge)(graphP, int);
void (*fpRestoreEdge)(graphP, int);
Expand Down
4 changes: 2 additions & 2 deletions c/graphLib/graphUtils.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ extern int _MarkDFSPath(graphP theGraph, int ancestor, int descendant);
extern int _EmbedPostprocess(graphP theGraph, int v, int edgeEmbeddingResult);
extern int _CheckEmbeddingIntegrity(graphP theGraph, graphP origGraph);
extern int _CheckObstructionIntegrity(graphP theGraph, graphP origGraph);
extern int _ReadPostprocess(graphP theGraph, void *extraData, long extraDataSize);
extern int _WritePostprocess(graphP theGraph, void **pExtraData, long *pExtraDataSize);
extern int _ReadPostprocess(graphP theGraph, char *extraData);
extern int _WritePostprocess(graphP theGraph, char **pExtraData);

/* Internal util functions for FUNCTION POINTERS */

Expand Down
229 changes: 44 additions & 185 deletions c/graphLib/io/g6-read-iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,95 +100,25 @@ int getPointerToGraphReadIn(G6ReadIterator *pG6ReadIterator, graphP *ppGraph)
return OK;
}

int beginG6ReadIterationFromG6FilePath(G6ReadIterator *pG6ReadIterator, char *g6FilePath)
int beginG6ReadIterationFromG6StrOrFile(G6ReadIterator *pG6ReadIterator, strOrFileP g6InputContainer)
{
int exitCode = OK;

if (!_isG6ReadIteratorAllocated(pG6ReadIterator))
{
ErrorMessage("G6ReadIterator is not allocated.\n");
return NOTOK;
}

if (g6FilePath == NULL || strlen(g6FilePath) == 0)
if (
sf_ValidateStrOrFile(g6InputContainer) != OK ||
(g6InputContainer->theStr != NULL && sb_GetSize(g6InputContainer->theStr) == 0))
{
ErrorMessage("g6FilePath is null or has length 0.\n");
ErrorMessage("Invalid g6InputContainer; must contain either valid input stream or non-empty string.\n");
return NOTOK;
}

g6FilePath[strcspn(g6FilePath, "\n\r")] = '\0';
pG6ReadIterator->g6Input = g6InputContainer;

FILE *g6Infile = fopen(g6FilePath, "r");

if (g6Infile == NULL)
{
char *messageFormat = "Unable to open .g6 file with path \"%.*s\"\n";
char messageContents[MAXLINE + 1];
int charsAvailForFilename = (int)(MAXLINE - strlen(messageFormat));
sprintf(messageContents, messageFormat, charsAvailForFilename, g6FilePath);
ErrorMessage(messageContents);
return NOTOK;
}

exitCode = beginG6ReadIterationFromG6FilePointer(pG6ReadIterator, g6Infile);

return exitCode;
}

int beginG6ReadIterationFromG6FilePointer(G6ReadIterator *pG6ReadIterator, FILE *g6Infile)
{
int exitCode = OK;

if (g6Infile == NULL)
{
ErrorMessage(".g6 file pointer is NULL.\n");
return NOTOK;
}

strOrFileP g6Input = sf_New(g6Infile, NULL);

if (g6Input == NULL)
{
ErrorMessage("Unable to allocate string-or-file container.\n");
return NOTOK;
}

pG6ReadIterator->g6Input = g6Input;

exitCode = _beginG6ReadIteration(pG6ReadIterator);

return exitCode;
}

int beginG6ReadIterationFromG6String(G6ReadIterator *pG6ReadIterator, char *g6InputStr)
{
int exitCode = OK;

if (g6InputStr == NULL || strlen(g6InputStr) <= 0)
{
ErrorMessage("g6InputStr must not be null or empty string.\n");
return NOTOK;
}

strOrFileP g6Input = sf_New(NULL, g6InputStr);

if (g6Input == NULL)
{
ErrorMessage("Unable to allocate string-or-file container.\n");
return NOTOK;
}

pG6ReadIterator->g6Input = g6Input;

exitCode = _beginG6ReadIteration(pG6ReadIterator);

return exitCode;
return _beginG6ReadIteration(pG6ReadIterator);
}

int _beginG6ReadIteration(G6ReadIterator *pG6ReadIterator)
{
int exitCode = OK;
int charConfirmation = -1;
char charConfirmation = EOF;

char messageContents[MAXLINE + 1];

Expand All @@ -202,7 +132,7 @@ int _beginG6ReadIteration(G6ReadIterator *pG6ReadIterator)
}
else
{
charConfirmation = sf_ungetc(firstChar, g6Input);
charConfirmation = sf_ungetc((char)firstChar, g6Input);

if (charConfirmation != firstChar)
{
Expand All @@ -223,15 +153,15 @@ int _beginG6ReadIteration(G6ReadIterator *pG6ReadIterator)

int lineNum = 1;
firstChar = sf_getc(g6Input);
charConfirmation = sf_ungetc(firstChar, g6Input);
charConfirmation = sf_ungetc((char)firstChar, g6Input);

if (charConfirmation != firstChar)
{
ErrorMessage("Unable to ungetc first character.\n");
return NOTOK;
}

if (!_firstCharIsValid(firstChar, lineNum))
if (!_firstCharIsValid((char)firstChar, lineNum))
return NOTOK;

// Despite the general specification indicating that n \in [0, 68,719,476,735],
Expand Down Expand Up @@ -372,7 +302,7 @@ int _getGraphOrder(strOrFileP g6Input, int *graphOrder)
return NOTOK;
}

sf_ungetc(graphChar, g6Input);
sf_ungetc((char)graphChar, g6Input);

for (int i = 2; i >= 0; i--)
{
Expand Down Expand Up @@ -453,7 +383,7 @@ int readGraphUsingG6ReadIterator(G6ReadIterator *pG6ReadIterator)
// If the line was too long, then we would have placed the null terminator at the final
// index (where it already was; see strcpn docs), and the length of the string will be
// longer than the line should have been, i.e. orderOffset + numCharsForGraphRepr
if (strlen(currGraphBuff) != (((numGraphsRead == 1) ? 0 : numCharsForGraphOrder) + numCharsForGraphEncoding))
if ((int)strlen(currGraphBuff) != (((numGraphsRead == 1) ? 0 : numCharsForGraphOrder) + numCharsForGraphEncoding))
{
sprintf(messageContents, "Invalid line length read on line %d\n", numGraphsRead);
ErrorMessage(messageContents);
Expand Down Expand Up @@ -670,13 +600,7 @@ int endG6ReadIteration(G6ReadIterator *pG6ReadIterator)
if (pG6ReadIterator != NULL)
{
if (pG6ReadIterator->g6Input != NULL)
{
exitCode = sf_closeFile(pG6ReadIterator->g6Input);
if (exitCode != OK)
ErrorMessage("Unable to close g6Input file pointer.\n");

sf_Free(&(pG6ReadIterator->g6Input));
}

if (pG6ReadIterator->currGraphBuff != NULL)
{
Expand All @@ -695,13 +619,7 @@ int freeG6ReadIterator(G6ReadIterator **ppG6ReadIterator)
if (ppG6ReadIterator != NULL && (*ppG6ReadIterator) != NULL)
{
if ((*ppG6ReadIterator)->g6Input != NULL)
{
exitCode = sf_closeFile((*ppG6ReadIterator)->g6Input);
if (exitCode != OK)
ErrorMessage("Unable to close g6Input file pointer.\n");

sf_Free(&((*ppG6ReadIterator)->g6Input));
}

(*ppG6ReadIterator)->numGraphsRead = 0;
(*ppG6ReadIterator)->graphOrder = 0;
Expand All @@ -721,129 +639,71 @@ int freeG6ReadIterator(G6ReadIterator **ppG6ReadIterator)
return exitCode;
}

// Although _ReadGraphFromG6FilePath is almost identical to _ReadGraphFromG6FilePointer,
// these two helper functions are meant for demonstrative purposes and are unlikely
// to change. If you do modify this function, be sure to modify _ReadGraphFromG6FilePointer.
int _ReadGraphFromG6FilePath(graphP pGraphToRead, char *pathToG6File)
{
int exitCode = OK;

G6ReadIterator *pG6ReadIterator = NULL;
exitCode = allocateG6ReadIterator(&pG6ReadIterator, pGraphToRead);

if (exitCode != OK)
{
ErrorMessage("Unable to allocate G6ReadIterator.\n");
return exitCode;
}

exitCode = beginG6ReadIterationFromG6FilePath(pG6ReadIterator, pathToG6File);
char *messageFormat = NULL;
char messageContents[MAXLINE + 1];
messageContents[MAXLINE] = '\0';
int charsAvailForStr = 0;

if (exitCode != OK)
strOrFileP inputContainer = sf_New(NULL, pathToG6File, READTEXT);
if (inputContainer == NULL)
{
ErrorMessage("Unable to begin .g6 read iteration.\n");

exitCode = freeG6ReadIterator(&pG6ReadIterator);

if (exitCode != OK)
ErrorMessage("Unable to free G6ReadIterator.\n");
messageFormat = "Unable to allocate strOrFile container for infile \"%.*s\".\n";
charsAvailForStr = (int)(MAXLINE - strlen(messageFormat));
sprintf(messageContents, messageFormat, charsAvailForStr, pathToG6File);
ErrorMessage(messageContents);

return exitCode;
return NOTOK;
}

exitCode = readGraphUsingG6ReadIterator(pG6ReadIterator);
if (exitCode != OK)
ErrorMessage("Unable to read graph from .g6 read iterator.\n");

exitCode = endG6ReadIteration(pG6ReadIterator);
if (exitCode != OK)
ErrorMessage("Unable to end G6ReadIterator.\n");

exitCode = freeG6ReadIterator(&pG6ReadIterator);

if (exitCode != OK)
ErrorMessage("Unable to free G6ReadIterator.\n");

return exitCode;
return _ReadGraphFromG6StrOrFile(pGraphToRead, inputContainer);
}

// Although _ReadGraphFromG6FilePointer is almost identical to _ReadGraphFromG6FilePath,
// these two helper functions are meant for demonstrative purposes and are unlikely
// to change. If you do change this function, be sure to modify _ReadGraphFromG6FilePath.
int _ReadGraphFromG6FilePointer(graphP pGraphToRead, FILE *g6Infile)
int _ReadGraphFromG6String(graphP pGraphToRead, char *g6EncodedString)
{
int exitCode = OK;

G6ReadIterator *pG6ReadIterator = NULL;
exitCode = allocateG6ReadIterator(&pG6ReadIterator, pGraphToRead);

if (exitCode != OK)
if (g6EncodedString == NULL || strlen(g6EncodedString) == 0)
{
ErrorMessage("Unable to allocate G6ReadIterator.\n");
return exitCode;
ErrorMessage("Unable to proceed with empty .g6 input string.\n");
return NOTOK;
}

exitCode = beginG6ReadIterationFromG6FilePointer(pG6ReadIterator, g6Infile);

if (exitCode != OK)
strOrFileP inputContainer = sf_New(g6EncodedString, NULL, READTEXT);
if (inputContainer == NULL)
{
ErrorMessage("Unable to begin .g6 read iteration.\n");

exitCode = freeG6ReadIterator(&pG6ReadIterator);

if (exitCode != OK)
ErrorMessage("Unable to free G6ReadIterator.\n");

return exitCode;
ErrorMessage("Unable to allocate strOrFile container for .g6 input string.\n");
return NOTOK;
}

exitCode = readGraphUsingG6ReadIterator(pG6ReadIterator);
if (exitCode != OK)
ErrorMessage("Unable to read graph from .g6 read iterator.\n");

exitCode = endG6ReadIteration(pG6ReadIterator);
if (exitCode != OK)
ErrorMessage("Unable to end G6ReadIterator.\n");

exitCode = freeG6ReadIterator(&pG6ReadIterator);

if (exitCode != OK)
ErrorMessage("Unable to free G6ReadIterator.\n");

return exitCode;
return _ReadGraphFromG6StrOrFile(pGraphToRead, inputContainer);
}

int _ReadGraphFromG6String(graphP pGraphToRead, char *g6EncodedString)
int _ReadGraphFromG6StrOrFile(graphP pGraphToRead, strOrFileP g6InputContainer)
{
int exitCode = OK;

if (g6EncodedString == NULL || strlen(g6EncodedString) == 0)
G6ReadIterator *pG6ReadIterator = NULL;

if (sf_ValidateStrOrFile(g6InputContainer) != OK)
{
ErrorMessage("Input string is empty.\n");
ErrorMessage("Invalid G6 output container.\n");
return NOTOK;
}

G6ReadIterator *pG6ReadIterator = NULL;
exitCode = allocateG6ReadIterator(&pG6ReadIterator, pGraphToRead);

if (exitCode != OK)
if (allocateG6ReadIterator(&pG6ReadIterator, pGraphToRead) != OK)
{
ErrorMessage("Unable to allocate G6ReadIterator.\n");
return exitCode;
return NOTOK;
}

exitCode = beginG6ReadIterationFromG6String(pG6ReadIterator, g6EncodedString);

if (exitCode != OK)
if (beginG6ReadIterationFromG6StrOrFile(pG6ReadIterator, g6InputContainer) != OK)
{
ErrorMessage("Unable to begin .g6 read iteration.\n");

exitCode = freeG6ReadIterator(&pG6ReadIterator);

if (exitCode != OK)
if (freeG6ReadIterator(&pG6ReadIterator) != OK)
ErrorMessage("Unable to free G6ReadIterator.\n");

return exitCode;
return NOTOK;
}

exitCode = readGraphUsingG6ReadIterator(pG6ReadIterator);
Expand All @@ -855,7 +715,6 @@ int _ReadGraphFromG6String(graphP pGraphToRead, char *g6EncodedString)
ErrorMessage("Unable to end G6ReadIterator.\n");

exitCode = freeG6ReadIterator(&pG6ReadIterator);

if (exitCode != OK)
ErrorMessage("Unable to free G6ReadIterator.\n");

Expand Down
Loading