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