diff --git a/Docs/FTObjectLibraryProject.md b/Docs/FTObjectLibraryProject.md index 47c976ea..3eb9547e 100644 --- a/Docs/FTObjectLibraryProject.md +++ b/Docs/FTObjectLibraryProject.md @@ -1,23 +1,24 @@ project: FTObjectLibrary src_dir: ../Source output_dir: ./HTMLdocs +page_dir: ./pages summary: A Fortran library for reference counted object and container classes. author: David A. Kopriva author_description: Department of Mathematics, The Florida State University email: kopriva@math.fsu.edu website: https://www.math.fsu.edu/~kopriva -graph: true +graph: true project_github: https://github.com/trixi-framework/FTObjectLibrary source: false predocmark:> # Overview - FTObjectLibrary provides a collection of reference counted Fortran 2003 classes to + FTObjectLibrary provides a collection of reference counted Fortran 2003 classes to facilitate writing generic object oriented Fortran programs. Reference counting is implemented to assist with memory management so that the lifespans of objects are properly maintained and are so that objects are deleted only when no other references are made to them. - + The library includes three categories of classes: * Value classes @@ -36,7 +37,7 @@ Included in the library are the following standard container classes: - FTStack is a subclass of FTLinkedList that adds the usual push, pop, and peek routines. - FTSparseMatrix associates a double index (i,j) to an FTObject. Basically this is a two dimensional sparse matrix of pointers to FTObjects. - FTMultiIndexTable associates an integer array keys(:) to an FTObject. Basically this is an m--dimensional sparse matrix of pointers to FTObjects. -- FTDictionary is an ``associative container'', that associates a string to another FTObject. +- FTDictionary is an ``associative container'', that associates a string to another FTObject. - FTValueDictionary is a subclass of FTDictionary that has additional methods to store and retrieve values. - FTMutableObjectArray is a mutable one-dimensional array class that can store any FTObject @@ -46,11 +47,11 @@ values. # Documentation -Documentation can be found in the [user's guide](UsersGuide.md). +Documentation can be found in the [user's guide](page/UsersGuide.html). # Examples -Examples can be found in the [Examples](../Examples) directory and in the [Testing](../Testing) directory. The examples include a simple reverse Polish calculator using a stack, and another showing the use of a linked list. The testing directory includes tests that can be run on the library, which themselves serve as examples of the use of all of the classes. +Examples can be found in the [Examples](https://github.com/trixi-framework/FTObjectLibrary/tree/main/Examples) directory and in the [Testing](https://github.com/trixi-framework/FTObjectLibrary/tree/main/Testing) directory. The examples include a simple reverse Polish calculator using a stack, and another showing the use of a linked list. The testing directory includes tests that can be run on the library, which themselves serve as examples of the use of all of the classes. # Building the Library @@ -73,3 +74,7 @@ make ``` That will create the necessary files in that directory, which can be moved to somewhere else as desired. + +# News + +Notable additions are documented in the [News](page/News.html) \ No newline at end of file diff --git a/Docs/News.md b/Docs/pages/News.md similarity index 81% rename from Docs/News.md rename to Docs/pages/News.md index 278a7417..df6fd167 100644 --- a/Docs/News.md +++ b/Docs/pages/News.md @@ -1,9 +1,15 @@ +--- +title: News +--- + +[Back to the main documentation](../index.html) + # News -July 29, 2026 +## July 29, 2026 FTOL now has two versions, as necessary for procedures that need to distinguish between objects declared as TYPE and those declared as CLASS. See the documentation and the tests for examples. -May 11, 2025 +## May 11, 2025 The stringValue() and stringValueForKey() functions now use allocated strings, so the requestedLength argument is no longer necessary. Existing code can continue to use the older versions, but those versions are deprecated and undocumented. \ No newline at end of file diff --git a/Docs/UsersGuide.md b/Docs/pages/UsersGuide.md similarity index 96% rename from Docs/UsersGuide.md rename to Docs/pages/UsersGuide.md index a4bc1e53..1c1760cd 100644 --- a/Docs/UsersGuide.md +++ b/Docs/pages/UsersGuide.md @@ -1,3 +1,9 @@ +--- +title: User's Guide +--- + +[Back to the main documentation](../index.html) + # Introduction FTObjectLibrary provides a collection of reference counted Fortran 2003 @@ -14,7 +20,7 @@ The library includes three categories of classes: - Error reporting and testing classes -### Value Classes +### Value Classes Value classes include the base class, FTObject and at the current time, a subclass, FTValue. @@ -36,7 +42,7 @@ a subclass, FTValue. You can create your own value classes by extending FTObject and store instances of those classes in the containers. -### Container Classes +### Container Classes Container classes let you store any subclass of the base class FTObject in them. This makes it easy to store, for instance, a linked list of @@ -97,16 +103,16 @@ added to the dictionary. CLASS(FTDictionary), POINTER :: dict CLASS(FTObject) , POINTER :: obj CLASS(FTValue) , POINTER :: v - + ALLOCATE(dict) CALL dict % initWithSize(64) - + ALLOCATE(v) CALL v % initWithValue(3.14159) obj => v CALL dict % addObjectForKey(obj,``Pi'') CALL releaseFTValueClass(v) - + ALLOCATE(v) CALL v % initWithValue(``Ratio of circumference to diameter'') obj => v @@ -135,10 +141,10 @@ We use the dictionary as shown in the next snippet of code: CLASS(FTValue) , POINTER :: v REAL :: pi CALL constructDictionary(dict) - + v => valueFromObject(dict % objectForKey("Pi")) pi = v % realValue() - + v => valueFromObject(dict % objectForKey(``definition'')) PRINT *, "The num pi = ", pi," is defined as", TRIM(v % stringValue()) CALL releaseFTDictionaryClass(dict) @@ -203,13 +209,13 @@ the point object to the linked list. CLASS(FTLinkedList), POINTER :: list ! Subclass of FTObject CLASS(Point) , POINTER :: pnt ! Subclass of FTObject CLASS(FTObject) , POINTER :: obj - + ALLOCATE(list) CALL list % init() ! main now owns the list - + ALLOCATE(pnt) CALL pnt % initWithXYZ(0.0,0.0,0.0) ! main now owns pnt - + obj => pnt CALL list % add(obj) !list also owns pnt CALL releasePointClass(pnt) ! main gives up ownership to pnt @@ -218,7 +224,7 @@ the point object to the linked list. . ! we're done with the list, it will deallocate pnt since the list is the last owner. ! It will also deallocate itself since main is the last owner. - CALL releaseFTLinkedListClass(list) + CALL releaseFTLinkedListClass(list) END PROGRAM main @@ -295,10 +301,10 @@ Subclasses that override init() *must* include a call to the super class method. For example, if "Subclass" EXTENDS(FTObject), overriding init() looks like - SUBROUTINE initSubclass(self) + SUBROUTINE initSubclass(self) IMPLICIT NONE CLASS(Subclass) :: self - + CALL self % FTObject % init() Allocate and initialize all member objects ... Other Subclass specific code @@ -311,10 +317,10 @@ It is also the only one that includes the call to the super class init procedure. For example, the designated initializer for a "point" class would be the one that takes the (x,y,z) values. - SUBROUTINE initPointWithXYZ(self,x,y,z) + SUBROUTINE initPointWithXYZ(self,x,y,z) IMPLICIT NONE CLASS(Subclass) :: self - + CALL self % FTObject % init() self % x = x self % y = y @@ -326,20 +332,20 @@ an array of length three. They will do nothing but call the designated initializer. The default initializer sets the location to the origin, or some other reasonable value. - SUBROUTINE initPoint(self) + SUBROUTINE initPoint(self) IMPLICIT NONE CLASS(Subclass) :: self - + call self % initPointWithXYZ(0.0,0.0,0.0) END SUBROUTINE initPoint The array initializer is - SUBROUTINE initPointWithArray(self,w) + SUBROUTINE initPointWithArray(self,w) IMPLICIT NONE CLASS(Subclass) :: self REAL :: w(3) - + CALL self % initPointWithXYZ(w(1),w(2),w(3)) END SUBROUTINE initPointWithArray @@ -349,7 +355,7 @@ The destructor reverses the operations done in the init() procedure. It releases and deallocates any pointers that it owns. For example, if "Subclass" EXTENDS(FTObject) then overriding destruct looks like - SUBROUTINE destructSubclass(self) + SUBROUTINE destructSubclass(self) IMPLICIT NONE TYPE(Subclass) :: self . @@ -373,15 +379,15 @@ The release subroutine will call the base class releaseFTObject which will, in turn, release all objects that it owns. If the object itself is no longer referenced, it will deallocate itself. Due to fortran's rules, create one as below with the pointer TYPEed, and another with CLASS, usually with the word Class appended, e.g. releaseXXXClass(self). - SUBROUTINE releaseSubclass(self) + SUBROUTINE releaseSubclass(self) IMPLICIT NONE TYPE(Subclass) , POINTER :: self CLASS(FTObject), POINTER :: obj obj => self CALL releaseFTObject(self = obj) IF ( .NOT. ASSOCIATED(obj) ) THEN - self => NULL() - END IF + self => NULL() + END IF END SUBROUTINE releaseSubclass It is best to name the release procedures consistently. For instance, @@ -398,7 +404,7 @@ routine to do this as painlessly as possible. Each subclass should include a function like this: FUNCTION subclassFromSuperclass(obj) RESULT(cast) - IMPLICIT NONE + IMPLICIT NONE CLASS(FTObject), POINTER :: obj CLASS(Subclass), POINTER :: cast cast => NULL() @@ -504,7 +510,7 @@ inherits from FTObjectClass. CLASS(FTLinkedList), POINTER :: list CLASS(FTObject) , POINTER :: obj - + obj => r ! r is subclass of FTObject CALL list % Add(obj) ! Pointer is retained by list CALL release(r) ! If control is no longer wanted in this scope. @@ -523,7 +529,7 @@ inherits from FTObjectClass. CLASS(FTLinkedList) , POINTER :: list CLASS(FTObject) , POINTER :: obj CLASS(FTLinkedListRecord), POINTER :: record - + obj => r ! r is subclass of FTObject CALL list % insertObjectAfterRecord(obj,record) ! Pointer is retained by list CALL release(r) ! If caller wants to reliquish ownership @@ -533,7 +539,7 @@ inherits from FTObjectClass. CLASS(FTLinkedList) , POINTER :: list CLASS(FTObject) , POINTER :: obj, otherObject CLASS(FTLinkedListRecord), POINTER :: record - + obj => r ! r is subclass of FTObject CALL list % insertObjectAfterObject(obj,otherObject) ! Pointer is retained by list CALL release(r) ! If caller wants to reliquish ownership @@ -558,7 +564,7 @@ inherits from FTObjectClass. - Checking to see if a linked list circular or not - LOGICAL :: c + LOGICAL :: c c = list % isCircular() - Counting the number of objects in the list @@ -622,7 +628,7 @@ stepping through (iterating) a linked list to access its entries. DO WHILE (.NOT.iterator % isAtEnd()) obj => iterator % object() ! if the object is wanted recordPtr => iterator % currentRecord() ! if the record is wanted - + !Do something with object or record CALL iterator % moveToNext() ! FORGET THIS CALL AND YOU GET AN INFINITE LOOP! @@ -795,7 +801,7 @@ table. For example, ! Cast obj to something useful ELSE ! Perform some kind of error recovery - END IF + END IF ### FTSparseMatrix @@ -1089,7 +1095,7 @@ assertions have been made with the two enquiry functions You can get a summary of the assertions by calling the subroutine - SUBROUTINE SummarizeFTAssertions(title,iUnit) + SUBROUTINE SummarizeFTAssertions(title,iUnit) IMPLICIT NONE CHARACTER(LEN=*) :: title INTEGER :: iUnit @@ -1102,7 +1108,7 @@ So how do you make assertions? FTObjectLibrary supplies two subroutines that post failures to the sharedAssertionsManager. The first takes a LOGICAL variable - SUBROUTINE assert(test,msg) + SUBROUTINE assert(test,msg) IMPLICIT NONE CHARACTER(LEN=*), OPTIONAL :: msg LOGICAL :: test @@ -1126,63 +1132,63 @@ which allows a variety of argument type listed below: The individual calls have the signatures - SUBROUTINE assertEqualTwoIntegers(expectedValue,actualValue,msg) - IMPLICIT NONE + SUBROUTINE assertEqualTwoIntegers(expectedValue,actualValue,msg) + IMPLICIT NONE INTEGER, INTENT(in) :: expectedValue,actualValue CHARACTER(LEN=*), OPTIONAL :: msg - - SUBROUTINE assertEqualTwoIntegerArrays1D(expectedValue,actualValue) - IMPLICIT NONE + + SUBROUTINE assertEqualTwoIntegerArrays1D(expectedValue,actualValue) + IMPLICIT NONE INTEGER, INTENT(in) , DIMENSION(:) :: expectedValue,actualValue - - SUBROUTINE assertEqualTwoIntegerArrays2D(expectedValue,actualValue) - IMPLICIT NONE + + SUBROUTINE assertEqualTwoIntegerArrays2D(expectedValue,actualValue) + IMPLICIT NONE INTEGER, INTENT(in) , DIMENSION(:,:) :: expectedValue,actualValue - - SUBROUTINE assertWithinToleranceTwoReal(x,y,tol,absTol,msg) - IMPLICIT NONE + + SUBROUTINE assertWithinToleranceTwoReal(x,y,tol,absTol,msg) + IMPLICIT NONE REAL, INTENT(in) :: x,y,tol REAL, INTENT(IN), OPTIONAL :: absTol CHARACTER(LEN=*), OPTIONAL :: msg - - SUBROUTINE assertWithinToleranceTwoRealArrays1D(expectedValue,actualValue,tol,absTol,msg) - IMPLICIT NONE + + SUBROUTINE assertWithinToleranceTwoRealArrays1D(expectedValue,actualValue,tol,absTol,msg) + IMPLICIT NONE REAL, INTENT(IN), DIMENSION(:) :: expectedValue,actualValue REAL, INTENT(IN) :: tol REAL, INTENT(IN), OPTIONAL :: absTol CHARACTER(LEN=*), OPTIONAL :: msg - - SUBROUTINE assertWithinToleranceTwoRealArrays2D(expectedValue,actualValue,tol) - IMPLICIT NONE + + SUBROUTINE assertWithinToleranceTwoRealArrays2D(expectedValue,actualValue,tol) + IMPLICIT NONE REAL, INTENT(IN), DIMENSION(:,:) :: expectedValue,actualValue REAL, INTENT(IN) :: tol - - SUBROUTINE assertWithinToleranceTwoDouble(expectedValue,actualValue,tol,absTol,msg) - IMPLICIT NONE + + SUBROUTINE assertWithinToleranceTwoDouble(expectedValue,actualValue,tol,absTol,msg) + IMPLICIT NONE DOUBLE PRECISION, INTENT(in) :: expectedValue,actualValue,tol REAL, INTENT(IN), OPTIONAL :: absTol CHARACTER(LEN=*), OPTIONAL :: msg - - SUBROUTINE assertWithinToleranceTwoDoubleArrays1D(expectedValue,actualValue,tol,absTol,msg) - IMPLICIT NONE + + SUBROUTINE assertWithinToleranceTwoDoubleArrays1D(expectedValue,actualValue,tol,absTol,msg) + IMPLICIT NONE DOUBLE PRECISION, INTENT(IN), DIMENSION(:) :: expectedValue,actualValue DOUBLE PRECISION, INTENT(IN) :: tol REAL, INTENT(IN), OPTIONAL :: absTol CHARACTER(LEN=*), OPTIONAL :: msg - - SUBROUTINE assertWithinToleranceTwoDoubleArrays2D(expectedValue,actualValue,tol,abstol) - IMPLICIT NONE + + SUBROUTINE assertWithinToleranceTwoDoubleArrays2D(expectedValue,actualValue,tol,abstol) + IMPLICIT NONE DOUBLE PRECISION, INTENT(IN), DIMENSION(:,:) :: expectedValue,actualValue DOUBLE PRECISION, INTENT(IN) :: tol REAL, INTENT(IN), OPTIONAL :: absTol - + SUBROUTINE assertEqualString(expectedValue,actualValue,msg) IMPLICIT NONE CHARACTER(LEN=*) :: expectedValue,actualValue CHARACTER(LEN=*), OPTIONAL :: msg - - SUBROUTINE assertEqualTwoLogicals(expectedValue,actualValue,msg) - IMPLICIT NONE + + SUBROUTINE assertEqualTwoLogicals(expectedValue,actualValue,msg) + IMPLICIT NONE LOGICAL, INTENT(in) :: expectedValue,actualValue CHARACTER(LEN=*), OPTIONAL :: msg @@ -1207,7 +1213,7 @@ used with minimal fuss. You An example of running a suite of tests is the following: TYPE(TestSuiteManager) :: testSuite - + EXTERNAL :: FTDictionaryClassTests EXTERNAL :: FTExceptionClassTests EXTERNAL :: FTValueClassTests @@ -1218,7 +1224,7 @@ An example of running a suite of tests is the following: EXTERNAL :: HashTableTests CALL testSuite % init() - + CALL testSuite % addTestSubroutineWithName(FTValueClassTests,"FTValueClass Tests") CALL testSuite % addTestSubroutineWithName(FTDictionaryClassTests,"FTDictionaryClass Tests") CALL testSuite % addTestSubroutineWithName(FTValueDictionaryClassTests,"FTValueDictionaryClass Tests") @@ -1234,7 +1240,7 @@ The test subroutines have no arguments or include optional data. The interface i ABSTRACT INTERFACE SUBROUTINE testSuiteFunction(optData) - CHARACTER(LEN=1), POINTER, OPTIONAL :: optData(:) + CHARACTER(LEN=1), POINTER, OPTIONAL :: optData(:) END SUBROUTINE testSuiteFunction END INTERFACE @@ -1256,7 +1262,7 @@ Reporting is managed by the testSuiteManager at the end of performTests. Look at ABSTRACT INTERFACE SUBROUTINE testSuiteFunction(optData) - CHARACTER(LEN=1), POINTER, OPTIONAL :: optData(:) + CHARACTER(LEN=1), POINTER, OPTIONAL :: optData(:) END SUBROUTINE testSuiteFunction END INTERFACE @@ -1312,7 +1318,7 @@ Defined constants: e % initFTException(severity,exceptionName,infoDictionary) - Plus the convenience initializers, which automatically + Plus the convenience initializers, which automatically create a FTValueDictionary with a single key called "message": e % initWarningException(msg = "message") diff --git a/Docs/pages/index.md b/Docs/pages/index.md new file mode 100644 index 00000000..26d0188e --- /dev/null +++ b/Docs/pages/index.md @@ -0,0 +1,11 @@ +--- +title: Documentation +--- + +# Documentation + +[Back to main documentation](../index.html) + +[User's Guide](UsersGuide.html) + +[News](News.html) \ No newline at end of file