Bug 454376 add -lCrun -lCstd for Solaris OS_LIBS, r=bsmedberg
[wine-gecko.git] / modules / plugin / tools / tester / common / pplib.cpp
blob17de3dacddbb086fd53fa7607c3e654bca2ef3f3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /****************************************************/
39 /* */
40 /* Private profile library */
41 /* */
42 /* Attempt to write a cross-platform library for */
43 /* dealing with Windows style .INI profiles. */
44 /* */
45 /* For API see pplib.h */
46 /* */
47 /* 11.26.97 - av started */
48 /* */
49 /* Current limitations: */
50 /* - profile must NOT contain space chars */
51 /* - colon indicating comments must be in the */
52 /* first position */
53 /* */
54 /****************************************************/
56 #include "xp.h"
58 static BOOL isCurrentLineCommentedOut(char * pBuf, char * pPosition)
60 for(;;)
62 if((*pPosition == ';') && ((pPosition - 1 < pBuf) || (*(pPosition - 1) == '\n') || (*(pPosition - 1) == '\r')))
63 return TRUE;
64 pPosition--;
65 if(pPosition < pBuf)
66 return FALSE;
67 if((*pPosition == '\n') || (*pPosition == '\r'))
68 return FALSE;
72 /*******************************************************************/
73 /* */
74 /* Note: For a section header to be found, the [ must be the first */
75 /* character on the line. This prevents the [Options] string in */
76 /* the comments of the Sample.pts script from being found as the */
77 /* top of the Options section. -pollmann */
78 /* */
79 /*******************************************************************/
80 static char * goToSectionBody(char * pBuf, char * szSection)
82 if((pBuf == NULL) || (szSection == NULL))
83 return NULL;
84 char szSectionString[256];
85 strcpy(szSectionString, "\n"); /* Line feed before [ */
86 strcat(szSectionString, "[");
87 strcat(szSectionString, szSection);
88 strcat(szSectionString, "]");
89 char * p = strstr(pBuf, szSectionString);
90 if(p == NULL) {
91 szSectionString[0] = '\r'; /* Carriage return before [ */
92 char * p = strstr(pBuf, szSectionString);
93 if(p == NULL)
94 return NULL;
96 p += strlen(szSectionString) + 1; // 1 is for new line character
97 return p;
100 static int getSectionLength(char * pBuf, char * szSection)
102 int iRet = 0;
104 char * pSectionStart = goToSectionBody(pBuf, szSection);
106 if(pSectionStart == NULL)
107 return 0;
109 char * pNextSection = strstr(pSectionStart, "[");
111 if(pNextSection != NULL)
112 iRet = (int)(pNextSection - pSectionStart);
113 else
114 iRet = (int)(pBuf + strlen(pBuf) - pSectionStart);
116 return iRet;
119 static char * goToKeyBody(char * pSectionStart, int iSectionLength, char * szKey)
121 if((pSectionStart == NULL) || (szKey == NULL))
122 return NULL;
123 if((int)strlen(szKey) >= iSectionLength)
124 return NULL;
125 char szKeyString[256];
126 strcpy(szKeyString, szKey);
127 strcat(szKeyString, "=");
128 char chBackup = pSectionStart[iSectionLength];
129 pSectionStart[iSectionLength] = '\0';
130 char * p = strstr(pSectionStart, szKeyString);
131 if(p == NULL)
133 pSectionStart[iSectionLength] = chBackup;
134 return NULL;
136 p = strstr(p, "=");
137 if(p == NULL)
139 pSectionStart[iSectionLength] = chBackup;
140 return NULL;
142 p++;
143 pSectionStart[iSectionLength] = chBackup;
144 if(isCurrentLineCommentedOut(pSectionStart, p))
145 return NULL;
146 else
147 return p;
150 static int getKeyLength(char * pSectionStart, int iSectionLength, char * szKey)
152 int iRet = 0;
154 char * pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
156 if(pKeyStart == NULL)
157 return 0;
159 char * pFirstCarriageReturn = strchr(pKeyStart, '\r');
160 char * pFirstNewLine = strchr(pKeyStart, '\n');
162 if((pFirstCarriageReturn == NULL) && (pFirstNewLine == NULL))
163 return iSectionLength;
165 char * p = NULL;
167 if((pFirstCarriageReturn != NULL) && (pFirstNewLine != NULL))
168 p = (pFirstCarriageReturn < pFirstNewLine) ? pFirstCarriageReturn : pFirstNewLine;
169 else
170 p = (pFirstCarriageReturn != NULL) ? pFirstCarriageReturn : pFirstNewLine;
172 p--;
174 // cut off ending spaces and tabs
175 while((*p == ' ') || (*p == '\t'))
176 p--;
178 p++;
180 iRet = (int)(p - pKeyStart);
182 return iRet;
185 static char * readFileToNewAllocatedZeroTerminatedBuffer(XP_HFILE hFile)
187 if(hFile == NULL)
188 return NULL;
190 int iSize;
192 #ifdef XP_MAC
193 iSize = 32000; /* HACK for the MAC */
194 #else
195 #if defined(XP_UNIX) || defined(XP_OS2)
196 struct stat buf;
197 fstat(fileno(hFile), &buf);
198 iSize = buf.st_size;
199 #else
200 iSize = (int)_filelength(/*_fileno*/(hFile));
201 #endif
202 #endif
204 if(iSize <= 0)
205 return NULL;
207 char * pBuf = new char[iSize + 1];
208 if(pBuf == NULL)
209 return NULL;
211 fseek((FILE *)hFile, 0L, SEEK_SET);
212 fread((void *)pBuf, iSize, 1, (FILE *)hFile);
214 // cut off strange stuff at the end and reallocate
215 char * p = pBuf + iSize - 1;
216 for(;;)
218 BOOL bNormalChar = ((int)*p > 0) && (isprint(*p) != 0);
219 if(bNormalChar || (*p == '\n') || (*p == '\r') || (p < pBuf))
220 break;
221 p--;
223 p++;
224 *p = '\0';
226 iSize = strlen(pBuf);
227 char * pBufFinal = new char[iSize + 1];
228 memcpy((void *)pBufFinal, (void *)pBuf, iSize);
229 pBufFinal[iSize] = '\0';
230 delete [] pBuf;
231 return pBufFinal;
234 DWORD PP_GetString(char * szSection, char * szKey, char * szDefault, char * szString, DWORD dwSize, XP_HFILE hFile)
236 char * pBuf = NULL;
237 char * pSectionStart = NULL;
238 int iSectionLength = 0;
239 int iSize = 0;
241 pBuf = readFileToNewAllocatedZeroTerminatedBuffer(hFile);
243 if(pBuf == NULL)
244 goto ReturnDefault;
246 iSize = strlen(pBuf);
249 // first consider two special cases: szSection = NULL and szKey = NULL
251 if(szSection == NULL) // find all sections and return
253 char * pNextSection = NULL;
254 char * pSource = pBuf;
255 char * pDest = szString;
256 int iBytes = 0;
258 for(;;)
260 pSource = strstr(pSource, "[");
261 if(pSource == NULL)
262 break;
264 pNextSection = pSource + 1;
265 char * pEnd = strstr(pSource, "]");
266 int iLength = pEnd - pNextSection;
268 if(!isCurrentLineCommentedOut(pBuf, pSource))
270 if(iBytes + iLength + 2 < (int)dwSize)
271 memcpy((void *)pDest, (void *)pNextSection, iLength);
272 else
273 break;
275 pDest += iLength;
276 *pDest = '\0';
277 pDest++;
278 iBytes += iLength + 1; // for '\0'
279 if(iBytes >= iSize)
280 break;
282 pSource += iLength + 2; // for "[" and "]"
285 *pDest = '\0';
286 iBytes++; // for this '\0'
287 delete [] pBuf;
288 return (DWORD)iBytes;
291 pSectionStart = goToSectionBody(pBuf, szSection);
293 if(pSectionStart == NULL)
294 goto ReturnDefault;
296 iSectionLength = getSectionLength(pBuf, szSection);
298 if(iSectionLength == 0)
299 goto ReturnDefault;
301 if(szKey == NULL) // find all keys and return
303 int iBytes = 0;
304 char * pSource = pSectionStart - 1; // point to previous new line char
305 char * pDest = szString;
307 for(;;)
309 char * pEqualSign = strstr(pSource, "=");
311 if(pEqualSign > pSectionStart + iSectionLength)
312 break;
314 *pEqualSign = '\0';
316 char * pLastCarriageReturn = strrchr(pSource, '\r');
317 char * pLastNewLine = strrchr(pSource, '\n');
319 if((pLastCarriageReturn == NULL) && (pLastNewLine == NULL))
321 pSource = pEqualSign + 1;
322 continue;
325 char * pKey = (pLastCarriageReturn > pLastNewLine) ? pLastCarriageReturn : pLastNewLine;
326 pKey++;
327 int iLength = strlen(pKey);
329 if(!isCurrentLineCommentedOut(pBuf, pKey))
331 if(iBytes + iLength + 2 < (int)dwSize)
332 memcpy((void *)pDest, (void *)pKey, iLength);
333 else
334 break;
336 pDest += iLength;
337 *pDest = '\0';
338 pDest++;
339 iBytes += iLength + 1; // for '\0'
340 if(iBytes >= iSize)
341 break;
343 pSource = pEqualSign + 1;
346 *pDest = '\0';
347 iBytes++; // for this '\0'
348 delete [] pBuf;
349 return (DWORD)iBytes;
353 // Now the real thing
356 char * pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
357 if(pKeyStart == NULL)
358 goto ReturnDefault;
359 int iKeyLength = getKeyLength(pSectionStart, iSectionLength, szKey);
360 int iLength = (iKeyLength < (int)dwSize - 1) ? iKeyLength : (int)dwSize - 1;
361 memcpy((void *)szString, (void *)pKeyStart, iLength);
362 szString[iLength] = '\0';
363 delete [] pBuf;
364 return (DWORD)iLength;
367 ReturnDefault:
369 if(pBuf != NULL)
370 delete [] pBuf;
371 if((szDefault != NULL) && (szString != NULL))
372 strcpy(szString, szDefault);
373 return (DWORD)strlen(szString);
376 static BOOL replaceBytesInReallocatedBufferAfter(
377 char ** ppBuf, // address of buffer pointer
378 char * szString, // string to make a replacement with
379 int iPosition, // byte after which to insert the string
380 int iBytesToReplace) // number of bytes to replace
382 if(ppBuf == NULL)
383 return FALSE;
384 char * pBuf = *ppBuf;
385 if(pBuf == NULL)
386 return FALSE;
388 int iNewLength = strlen(pBuf) - iBytesToReplace + strlen(szString);
389 char * pBufNew = new char[iNewLength + 1]; // 1 - for zero termination
390 if(pBufNew == NULL)
391 return FALSE;
392 if(iPosition > 0)
393 memcpy((void *)pBufNew, (void *)pBuf, iPosition);
394 char * p = pBufNew + iPosition;
395 memcpy((void *)p, (void *)szString, strlen(szString));
396 p += strlen(szString);
397 memcpy((void *)p, (void *)(pBuf + iPosition + iBytesToReplace), strlen(pBuf) - iPosition - iBytesToReplace);
398 p += strlen(pBuf) - iPosition - iBytesToReplace;
399 *p = '\0';
400 delete [] pBuf;
401 *ppBuf = pBufNew;
402 return TRUE;
405 BOOL PP_WriteString(char * szSection, char * szKey, char * szString, XP_HFILE hFile)
407 if((szSection == NULL) || (szKey == NULL) || (szString == NULL) || (hFile == NULL))
408 return FALSE;
410 char * pBuf = readFileToNewAllocatedZeroTerminatedBuffer(hFile);
412 if(pBuf == NULL)
413 return FALSE;
415 #if !(defined XP_MAC || defined XP_UNIX || defined XP_OS2)
416 long lOldSize = (long)strlen(pBuf);
417 #endif
419 char * pSectionStart = goToSectionBody(pBuf, szSection);
421 // add section if not present
422 if(pSectionStart == NULL)
424 char szNewSection[256];
425 strcpy(szNewSection, "[");
426 strcat(szNewSection, szSection);
427 strcat(szNewSection, "]");
428 strcat(szNewSection, "\n");
429 strcat(szNewSection, "\n");
430 if(!replaceBytesInReallocatedBufferAfter(&pBuf, szNewSection, 0, 0))
432 if(pBuf != NULL)
433 delete [] pBuf;
434 return FALSE;
436 pSectionStart = goToSectionBody(pBuf, szSection);
439 if(pSectionStart == NULL)
440 return FALSE;
442 int iSectionLength = getSectionLength(pBuf, szSection);
443 char * pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
445 // add key if not present
446 if(pKeyStart == NULL)
448 char szNewKey[256];
449 strcpy(szNewKey, szKey);
450 strcat(szNewKey, "=");
451 strcat(szNewKey, "\n");
452 int iPos = pSectionStart - pBuf;
453 if(!replaceBytesInReallocatedBufferAfter(&pBuf, szNewKey, iPos, 0))
455 if(pBuf != NULL)
456 delete [] pBuf;
457 return FALSE;
459 pSectionStart = goToSectionBody(pBuf, szSection);
460 iSectionLength = getSectionLength(pBuf, szSection);
461 pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
464 if(pKeyStart == NULL)
465 return FALSE;
467 int iKeyLength = getKeyLength(pSectionStart, iSectionLength, szKey);
468 int iPos = pKeyStart - pBuf;
469 if(!replaceBytesInReallocatedBufferAfter(&pBuf, szString, iPos, iKeyLength))
471 if(pBuf != NULL)
472 delete [] pBuf;
473 return FALSE;
476 #if (defined XP_MAC || defined XP_UNIX || defined XP_OS2)
477 rewind(hFile);
478 #else
479 // change file size
480 long lNewSize = (long)strlen(pBuf);
481 long lSizeChange = lNewSize - lOldSize;
482 if(lSizeChange != 0L)
484 long lOldFileSize = (long)_filelength(/*_fileno*/(hFile));
485 long lNewFileSize = lOldFileSize + lSizeChange;
486 _chsize(/*_fileno*/(hFile), lNewFileSize);
489 fseek((FILE *)hFile, 0L, SEEK_SET);
490 #endif
492 fwrite(pBuf, strlen(pBuf), 1, (FILE *)hFile);
494 delete [] pBuf;
496 return TRUE;