1 2 #include <petsc/private/viewerimpl.h> /*I "petscsys.h" I*/ 3 4 typedef struct { 5 char *string; /* string where info is stored */ 6 char *head; /* pointer to beginning of unused portion */ 7 size_t curlen, maxlen; 8 PetscBool ownstring; /* string viewer is responsable for freeing the string */ 9 } PetscViewer_String; 10 11 static PetscErrorCode PetscViewerDestroy_String(PetscViewer viewer) { 12 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 13 14 PetscFunctionBegin; 15 if (vstr->ownstring) PetscCall(PetscFree(vstr->string)); 16 PetscCall(PetscFree(vstr)); 17 PetscFunctionReturn(0); 18 } 19 20 /*@C 21 PetscViewerStringSPrintf - Prints information to a `PETSCVIEWERSTRING` `PetscViewer` object 22 23 Logically Collective on viewer 24 25 Input Parameters: 26 + v - a string `PetscViewer`, formed by `PetscViewerStringOpen()` 27 - format - the format of the input 28 29 Level: developer 30 31 Note: 32 Though this is collective each MPI rank maintains a separate string 33 34 Fortran Note: 35 This routine is not supported in Fortran. 36 37 .seealso: `PETSCVIEWERSTRING`, `PetscViewerStringOpen()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()` 38 @*/ 39 PetscErrorCode PetscViewerStringSPrintf(PetscViewer viewer, const char format[], ...) { 40 va_list Argp; 41 size_t fullLength; 42 size_t shift, cshift; 43 PetscBool isstring; 44 char tmp[4096]; 45 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 46 47 PetscFunctionBegin; 48 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 49 PetscValidCharPointer(format, 2); 50 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 51 if (!isstring) PetscFunctionReturn(0); 52 PetscCheck(vstr->string, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerStringSetString() before using"); 53 54 va_start(Argp, format); 55 PetscCall(PetscVSNPrintf(tmp, 4096, format, &fullLength, Argp)); 56 va_end(Argp); 57 PetscCall(PetscStrlen(tmp, &shift)); 58 cshift = shift + 1; 59 if (cshift >= vstr->maxlen - vstr->curlen - 1) cshift = vstr->maxlen - vstr->curlen - 1; 60 PetscCall(PetscStrncpy(vstr->head, tmp, cshift)); 61 vstr->head += shift; 62 vstr->curlen += shift; 63 PetscFunctionReturn(0); 64 } 65 66 /*@C 67 PetscViewerStringOpen - Opens a string as a `PETSCVIEWERSTRING` `PetscViewer`. This is a very 68 simple `PetscViewer`; information on the object is simply stored into 69 the string in a fairly nice way. 70 71 Collective 72 73 Input Parameters: 74 + comm - the communicator 75 . string - the string to use 76 - len - the string length 77 78 Output Parameter: 79 . lab - the `PetscViewer` 80 81 Level: advanced 82 83 Fortran Note: 84 This routine is not supported in Fortran. 85 86 .seealso: `PETSCVIEWERSTRING`, `PetscViewerDestroy()`, `PetscViewerStringSPrintf()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()` 87 @*/ 88 PetscErrorCode PetscViewerStringOpen(MPI_Comm comm, char string[], size_t len, PetscViewer *lab) { 89 PetscFunctionBegin; 90 PetscCall(PetscViewerCreate(comm, lab)); 91 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSTRING)); 92 PetscCall(PetscViewerStringSetString(*lab, string, len)); 93 PetscFunctionReturn(0); 94 } 95 96 PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) { 97 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 98 99 PetscFunctionBegin; 100 PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer)); 101 PetscFunctionReturn(0); 102 } 103 104 PetscErrorCode PetscViewerRestoreSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) { 105 PetscViewer_String *iviewer = (PetscViewer_String *)(*sviewer)->data; 106 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 107 108 PetscFunctionBegin; 109 vstr->head = iviewer->head; 110 vstr->curlen += iviewer->curlen; 111 PetscCall(PetscViewerDestroy(sviewer)); 112 PetscFunctionReturn(0); 113 } 114 115 /*MC 116 PETSCVIEWERSTRING - A viewer that writes to a string 117 118 Level: beginner 119 120 .seealso: `PetscViewerStringOpen()`, `PetscViewerStringSPrintf()`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSCVIEWERSOCKET`, 121 `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`, 122 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, 123 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 124 M*/ 125 126 PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v) { 127 PetscViewer_String *vstr; 128 129 PetscFunctionBegin; 130 v->ops->destroy = PetscViewerDestroy_String; 131 v->ops->view = NULL; 132 v->ops->flush = NULL; 133 v->ops->getsubviewer = PetscViewerGetSubViewer_String; 134 v->ops->restoresubviewer = PetscViewerRestoreSubViewer_String; 135 PetscCall(PetscNewLog(v, &vstr)); 136 v->data = (void *)vstr; 137 vstr->string = NULL; 138 PetscFunctionReturn(0); 139 } 140 141 /*@C 142 143 PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses 144 145 Logically Collective on viewer 146 147 Input Parameter: 148 . viewer - `PETSCVIEWERSTRING` viewer 149 150 Output Parameters: 151 + string - the string, optional use NULL if you do not need 152 - len - the length of the string, optional use NULL if you do 153 154 Note: 155 Do not write to the string nor free it 156 157 Level: advanced 158 159 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`, 160 `PetscViewerStringSetOwnString()` 161 @*/ 162 PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len) { 163 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 164 PetscBool isstring; 165 166 PetscFunctionBegin; 167 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 168 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 169 PetscCheck(isstring, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Only for PETSCVIEWERSTRING"); 170 if (string) *string = vstr->string; 171 if (len) *len = vstr->maxlen; 172 PetscFunctionReturn(0); 173 } 174 175 /*@C 176 177 PetscViewerStringSetString - sets the string that a string viewer will print to 178 179 Logically Collective on viewer 180 181 Input Parameters: 182 + viewer - string viewer you wish to attach string to 183 . string - the string to print data into 184 - len - the length of the string 185 186 Note: The function does not copy the string, it uses it directly therefore you cannot free 187 the string until the viewer is destroyed. If you call `PetscViewerStringSetOwnString()` the ownership 188 passes to the viewer and it will be responsable for freeing it. In this case the string must be 189 obtained with `PetscMalloc()`. 190 191 Level: advanced 192 193 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`, 194 `PetscViewerStringSetOwnString()` 195 @*/ 196 PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len) { 197 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 198 PetscBool isstring; 199 200 PetscFunctionBegin; 201 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 202 PetscValidCharPointer(string, 2); 203 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 204 if (!isstring) PetscFunctionReturn(0); 205 PetscCheck(len > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "String must have length at least 2"); 206 207 PetscCall(PetscArrayzero(string, len)); 208 vstr->string = string; 209 vstr->head = string; 210 vstr->curlen = 0; 211 vstr->maxlen = len; 212 PetscFunctionReturn(0); 213 } 214 215 /*@C 216 217 PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it 218 219 Logically Collective on viewer 220 221 Input Parameters: 222 . viewer - string viewer 223 224 Note: 225 If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string 226 227 Level: advanced 228 229 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`, 230 `PetscViewerStringSetString()` 231 @*/ 232 PetscErrorCode PetscViewerStringSetOwnString(PetscViewer viewer) { 233 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 234 PetscBool isstring; 235 236 PetscFunctionBegin; 237 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 238 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 239 if (!isstring) PetscFunctionReturn(0); 240 241 vstr->ownstring = PETSC_TRUE; 242 PetscFunctionReturn(0); 243 } 244