Pointwise Plugin SDK
pwpPlatform.cxx
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * runtime Plugin platform dependent function calls
4  *
5  * Proprietary software product of Pointwise, Inc.
6  * Copyright (c) 1995-2018 Pointwise, Inc.
7  * All rights reserved.
8  *
9  ***************************************************************************/
10 
11 #include <string.h>
12 #include <sys/stat.h>
13 
14 #if defined(WINDOWS)
15 # include <io.h>
16 # include <direct.h>
17 # include <malloc.h>
18 #else
19 # include <stdlib.h>
20 #endif /* WINDOWS */
21 
22 // apiUtils.h included for ASSERT_COMPILE() macros.
23 // TODO: Consider isolating ASSERT macros to their own header "apiAssert.h"?
24 #include "apiUtils.h"
25 #include "pwpPlatform.h"
26 
27 
28 #if defined(WINDOWS)
29 
30 # define sysTextMode 't'
31 # define sysBinaryMode 'b'
32 # define sysFileno(fp) _fileno(fp)
33 
34 # define sysFstat _fstat64
35 typedef struct _stat64 sysStatBuf;
36 
37 #else /* *nix or mac */
38 
39 # define sysTextMode '\0'
40 # define sysBinaryMode 'b'
41 # define sysFileno(fp) fileno(fp)
42 
43 # define sysFstat fstat
44 typedef struct stat sysStatBuf;
45 
46 #endif /* WINDOWS */
47 
48 
49 #define strOK(ss) ((ss) && (ss[0]))
50 #define chrAPPEND(p,c) ((p && c) ? (*p++ = c) : 0)
51 
52 #define isMODE(allBits,modeBits) (((allBits) & (modeBits)) == modeBits)
53 
54 #if !defined(FILENAME_MAX)
55 # define FILENAME_MAX 512
56 #endif
57 
58 
59 #ifdef WINDOWS
60 
61 
62 static wchar_t *
63 utf8ToU16(const char *s)
64 {
65  wchar_t *result = 0;
66  size_t element = 0;
67  if (0 != s) {
68  size_t len;
69  len = ::strlen(s) + 1;
70  result = (wchar_t *)::malloc(len * sizeof(wchar_t));
71  //
72  // UTF-8 is a specific scheme for mapping a sequence of 1-4 bytes to a
73  // number from 0x000000 to 0x10FFFF:
74  //
75  // 00000000 -- 0000007F: 0xxxxxxx
76  // 00000080 -- 000007FF: 110xxxxx 10xxxxxx
77  // 00000800 -- 0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
78  // 00010000 -- 001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
79  //
80  // where the x's are the bits to be extracted from the sequence and
81  // combined to form the final value.
82  //
83  while ('\0' != *s) {
84  unsigned char c = (unsigned char)*s;
85  switch (0xF0 & c) {
86  // No indicator, so just convert
87  default:
88  result[element] = (wchar_t)c;
89  ++s;
90  break;
91  // Possible two byte utf8 character
92  case 0xC0:
93  case 0xD0:
94  // Two byte character 110xxxxx 10xxxxxx
95  if (0x80 == (*(s + 1) & 0xC0)) {
96  result[element] = (wchar_t)(
97  ((c & 0x1F) << 6) | (*(s + 1) & 0x3F));
98  s += 2;
99  }
100  // Doesn't have the second byte correct, so leave as is
101  else {
102  result[element] = (wchar_t)c;
103  ++s;
104  }
105  break;
106  // Possible three byte utf8 character
107  case 0xE0:
108  // Three byte character 1110xxxx 10xxxxxx 10xxxxxx
109  if (0x80 == (*(s + 1) & 0xC0) && 0x80 == (*(s + 2) & 0xC0)) {
110  result[element] = (wchar_t)(((c & 0x0F) << 12) |
111  ((*(s + 1) & 0x3F) << 6) | (*(s + 2) & 0x3F));
112  s += 3;
113  }
114  // Doesn't have the second and third byte correct, so leave as
115  // is
116  else {
117  result[element] = (wchar_t)c;
118  ++s;
119  }
120  break;
121  // Four byte case which can't be compressed into 16 bits, so just
122  // convert the bytes as is
123  case 0xF0:
124  result[element] = (wchar_t)c;
125  ++s;
126  break;
127  }
128  ++element;
129  }
130  }
131  else {
132  result = (wchar_t *)::malloc(sizeof(wchar_t));
133  }
134  result[element] = 0;
135  return result;
136 }
137 
138 
139 #ifdef NOT_NEEDED
140 static wchar_t *
141 utf8ToU16Old(const char *s)
142 {
143  wchar_t *result = 0;
144  size_t len;
145  size_t element = 0;
146  if (0 != s) {
147  len = ::strlen(s) + 1;
148  result = (wchar_t *)::malloc(len * sizeof(wchar_t));
149  //
150  // UTF-8 is a specific scheme for mapping a sequence of 1-4 bytes to a
151  // number from 0x000000 to 0x10FFFF:
152  //
153  // 00000000 -- 0000007F: 0xxxxxxx
154  // 00000080 -- 000007FF: 110xxxxx 10xxxxxx
155  // 00000800 -- 0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
156  // 00010000 -- 001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
157  //
158  // where the x's are the bits to be extracted from the sequence and
159  // combined to form the final value.
160  //
161  while ('\0' != *s) {
162  unsigned char c = (unsigned char)*s;
163  // Not an encoded character.
164  if (0xC0 > c) {
165  result[element] = (wchar_t)c;
166  ++s;
167  }
168  // Possible 2-byte utf-8 character
169  else if (0xE0 > c) {
170  // Two byte character 110xxxxx 10xxxxxx
171  if (0x80 == (*(s + 1) & 0xC0)) {
172  result[element] = (wchar_t)(
173  (c & 0x1F) << 6 | (*(s + 1) & 0x3F));
174  s += 2;
175  }
176  // Doesn't have the second byte correct, so leave as is
177  else {
178  result[element] = (wchar_t)c;
179  ++s;
180  }
181  }
182  // Possible 3-byte utf-8 character
183  else if (0xF0 > c) {
184  // Three byte character 1110xxxx 10xxxxxx 10xxxxxx
185  if (0x80 == (*(s + 1) & 0xC0) && 0x80 == (*(s + 2) & 0xC)) {
186  result[element] = (wchar_t)(((c & 0x0F) << 12) |
187  ((*(s + 1) & 0x3F) << 6) | (*(s + 2) & 0x3F));
188  s += 3;
189  }
190  // Doesn't have the second and third byte correct, so leave as
191  // is
192  else {
193  result[element] = (wchar_t)c;
194  ++s;
195  }
196  }
197  // Can't convert a 4-byte sequence down to 16 bits so just treat
198  // each byte as is
199  else {
200  result[element] = (wchar_t)c;
201  ++s;
202  }
203  ++element;
204  }
205  }
206  else {
207  result = (wchar_t *)::malloc(sizeof(wchar_t));
208  }
209  result[element] = 0;
210  return result;
211 }
212 #endif /* NOT_NEEDED */
213 #endif /* WINDOWS */
214 
215 
216 FILE *
217 pwpFileOpen(const char *filename, int mode)
218 {
219  FILE *ret = 0;
220  while (strOK(filename)) {
221  char modeStr[4] = {0,0,0,0};
222  char *p = modeStr;
223  // get base mode
224  if (isMODE(mode, pwpRead)) {
225  chrAPPEND(p, 'r');
226  }
227  else if (isMODE(mode, pwpWrite)) {
228  chrAPPEND(p, 'w');
229  }
230  else if (isMODE(mode, pwpAppend)) {
231  chrAPPEND(p, 'a');
232  }
233  else {
234  break; // error
235  }
236 
237  // get extended mode
238  if (isMODE(mode, pwpPlus_)) {
239  chrAPPEND(p, '+');
240  }
241 
242  // get format
243  if (isMODE(mode, pwpBinary) || isMODE(mode, pwpUnformatted)) {
245  }
246  else if (isMODE(mode, pwpFormatted) || isMODE(mode, pwpAscii)) {
248  }
249  else {
250  break; // error
251  }
252 
253 #ifdef WINDOWS
254  wchar_t *wname = utf8ToU16(filename);
255  wchar_t *wmode = utf8ToU16(modeStr);
256  if (wname && wmode) {
257  ret = ::_wfopen(wname, wmode);
258  ::free(wname);
259  ::free(wmode);
260  }
261  else {
262  ret = 0;
263  }
264 #else
265  ret = fopen(filename, modeStr);
266 #endif /* WINDOWS */
267  break; // force exit from while()
268  }
269  return ret;
270 }
271 
272 
273 int
274 pwpFileClose(FILE *fp)
275 {
276  int ret = sysEOF;
277  if (fp) {
278  ret = fclose(fp);
279  }
280  return ret;
281 }
282 
283 
284 int
285 pwpFileEof(FILE *fp)
286 {
287  return fp ? feof(fp) : 0;
288 }
289 
290 
291 int
292 pwpFileFlush(FILE *fp)
293 {
294  return fp ? fflush(fp) : -1;
295 }
296 
297 
298 int
299 pwpFileGetpos(FILE *fp, sysFILEPOS *pos)
300 {
301  int ret = -1;
302  if (fp && pos) {
303  ret = fgetpos(fp, pos);
304  }
305  return ret;
306 }
307 
308 
309 int
310 pwpFileSetpos(FILE *fp, const sysFILEPOS *pos)
311 {
312  int ret = -1;
313  if (fp && pos) {
314  ret = fsetpos(fp, pos);
315  }
316  return ret;
317 }
318 
319 
320 int
321 pwpFileGetSize(FILE *fp, size_t *size)
322 {
323  sysStatBuf buf;
324  // make sure files over 2GB are supported
325  ASSERT_COMPILE(sizeof(buf.st_size) == sizeof(size_t));
326  int ret = 0;
327  if (0 == fp || 0 == size) {
328  ret = -1;
329  }
330  else if (0 != sysFstat(sysFileno(fp), &buf)) {
331  *size = 0;
332  ret = -1;
333  }
334  else {
335  *size = (size_t)buf.st_size;
336  }
337  return ret;
338 }
339 
340 
341 int
342 pwpFilenameGetSize(const char *filename, size_t *size)
343 {
344  int ret = 0;
345  if (0 == filename || 0 == size) {
346  ret = -1;
347  }
348  else {
349 #ifdef WINDOWS
350  struct _stat64 buf;
351  wchar_t *wname = utf8ToU16(filename);
352  if (0 == wname) {
353  ret = -1;
354  }
355  else {
356  if (0 != ::_wstat64(wname, &buf)) {
357  *size = 0;
358  ret = -1;
359  }
360  else {
361  *size = (size_t)buf.st_size;
362  }
363  ::free(wname);
364  }
365 #else
366  struct stat buf;
367  if (0 != stat(filename, &buf)) {
368  *size = 0;
369  ret = -1;
370  }
371  else {
372  *size = (size_t)buf.st_size;
373  }
374 #endif /* WINDOWS */
375  }
376  return ret;
377 }
378 
379 
380 size_t
381 pwpFileRead(void *buf, size_t size, size_t count, FILE *fp)
382 {
383  size_t ret = 0;
384  if (buf && size && count && fp) {
385  ret = fread(buf, size, count, fp);
386  }
387  return ret;
388 }
389 
390 
391 size_t
392 pwpFileWrite(const void *buf, size_t size, size_t count, FILE *fp)
393 {
394  size_t ret = 0;
395  if (buf && size && count && fp) {
396  ret = fwrite(buf, size, count, fp);
397  }
398  return ret;
399 }
400 
401 
402 size_t
403 pwpFileWriteStr(const char *str, FILE *fp)
404 {
405  return str ? pwpFileWrite(str, strlen(str), 1, fp) : 0;
406 }
407 
408 
409 void
410 pwpFileRewind(FILE *fp)
411 {
412  if (fp) {
413  rewind(fp);
414  }
415 }
416 
417 
418 int
419 pwpFileDelete(const char *filename)
420 {
421  int ret = 0;
422  if (strOK(filename)) {
423 #ifdef WINDOWS
424  wchar_t *wname = utf8ToU16(filename);
425  if (0 == wname) {
426  ret = -1;
427  }
428  else {
429  ret = ::_wunlink(wname);
430  ::free(wname);
431  }
432 #else
433  ret = unlink(filename);
434 #endif /* WINDOWS */
435  }
436  return ret;
437 }
438 
439 
440 #define MAXSTACK 50
441 #ifdef WINDOWS
442 static wchar_t * dirStack[MAXSTACK+1] = { 0 };
443 #else
444 static char * dirStack[MAXSTACK+1] = { 0 };
445 #endif /* WINDOWS */
446 
447 static int stackCnt = 0;
448 
449 
450 int
451 pwpCwdPush(const char *dir)
452 {
453  int ret = -1;
454  if (dir && dir[0] && (stackCnt < MAXSTACK)) {
455 #ifdef WINDOWS
456  wchar_t *pCwd = ::_wgetcwd(0, FILENAME_MAX);
457  if (pCwd) {
458  wchar_t *wdir = utf8ToU16(dir);
459  if (wdir) {
460  if (0 == ::_wchdir(wdir)) {
461  dirStack[stackCnt++] = pCwd;
462  ret = 0;
463  }
464  else {
465  free(pCwd);
466  }
467  }
468  else {
469  free(pCwd);
470  }
471  }
472 #else
473  char *pCwd = getcwd(0, FILENAME_MAX);
474  if (pCwd) {
475  if (0 == chdir(dir)) {
476  dirStack[stackCnt++] = pCwd;
477  ret = 0;
478  }
479  else {
480  free(pCwd);
481  }
482  }
483 #endif /* WINDOWS */
484  }
485  return ret;
486 }
487 
488 
489 int
491 {
492  int ret = -1;
493  if ((0 < stackCnt) && (0 != dirStack[--stackCnt])) {
494 #ifdef WINDOWS
495  ret = ::_wchdir(dirStack[stackCnt]);
496 #else
497  ret = chdir(dirStack[stackCnt]);
498 #endif /* WINDOWS */
499  free(dirStack[stackCnt]);
500  dirStack[stackCnt] = 0;
501  }
502  return ret;
503 }
int pwpFileEof(FILE *fp)
Queries end-of-file status.
static int stackCnt
int pwpFileClose(FILE *fp)
Closes a file opened with pwpFileOpen().
size_t pwpFileWriteStr(const char *str, FILE *fp)
Write a null-terminated string to a file.
#define MAXSTACK
int pwpFileSetpos(FILE *fp, const sysFILEPOS *pos)
Set the current file position.
FILE * pwpFileOpen(const char *filename, int mode)
Opens a file for I/O.
#define sysFstat
Definition: pwpPlatform.cxx:43
size_t pwpFileRead(void *buf, size_t size, size_t count, FILE *fp)
Read an collection of data items from a file.
fpos_t sysFILEPOS
File position data type.
Definition: pwpPlatform.h:53
static char * dirStack[50+1]
#define sysFileno(fp)
Definition: pwpPlatform.cxx:41
Base plugin utilities.
Cross Platform Functions.
#define sysTextMode
Definition: pwpPlatform.cxx:39
int pwpFileFlush(FILE *fp)
Flush a file to disk.
int pwpCwdPop(void)
Restore the current directory.
int pwpFileGetpos(FILE *fp, sysFILEPOS *pos)
Query the current file position.
#define sysEOF
End-of-file value.
Definition: pwpPlatform.h:52
#define isMODE(allBits, modeBits)
Definition: pwpPlatform.cxx:52
size_t pwpFileWrite(const void *buf, size_t size, size_t count, FILE *fp)
Write an collection of data items to a file.
#define chrAPPEND(p, c)
Definition: pwpPlatform.cxx:50
void pwpFileRewind(FILE *fp)
Reset position to the beginning of the file.
int pwpFileDelete(const char *filename)
Delete a file.
struct stat sysStatBuf
Definition: pwpPlatform.cxx:44
int pwpFilenameGetSize(const char *filename, size_t *size)
Get the file&#39;s size in bytes.
#define FILENAME_MAX
Definition: pwpPlatform.cxx:55
#define ASSERT_COMPILE(x)
Compile time assert macro.
Definition: apiUtils.h:236
int pwpCwdPush(const char *dir)
Change the current directory.
#define strOK(ss)
Definition: pwpPlatform.cxx:49
#define sysBinaryMode
Definition: pwpPlatform.cxx:40
int pwpFileGetSize(FILE *fp, size_t *size)
Get the file&#39;s size in bytes.