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