/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "common/file.h" #include "bagel/boflib/misc.h" #include "bagel/boflib/cache.h" #include "bagel/bagel.h" #include "bagel/boflib/string_functions.h" namespace Bagel { #define MAX_LINE_LEN 100 static uint32 lStart; void timerStart() { lStart = g_system->getMillis(); } uint32 timerStop() { return g_system->getMillis() - lStart; } uint32 getTimer() { return g_system->getMillis(); } void bofSleep(uint32 milli) { g_system->delayMillis(milli); } #define ALLOC_FAIL_RETRIES 2 void *bofMemAlloc(uint32 nSize, const char *pFile, int nLine, bool bClear) { // For now, until I fix it, pFile MUST be valid. assert(pFile != nullptr); assert(nSize != 0); // Assume failure void *pNewBlock = nullptr; // Try a few times to allocate the desired amount of memory. // Flush objects from Cache is necessary. for (int nRetries = 0; nRetries < ALLOC_FAIL_RETRIES; nRetries++) { pNewBlock = (void *)malloc(nSize); // If allocation was successful, then we're outta here if (pNewBlock != nullptr) { if (bClear) memset((byte *)pNewBlock, 0, nSize); break; } // Otherwise, we need to free up some memory by flushing old // objects from the Cache. CCache::optimize(nSize + 2 * sizeof(uint16) + sizeof(uint32)); } if (pNewBlock == nullptr) CBofError::fatalError(ERR_MEMORY, "Could not allocate %u bytes, file %s, line %d", nSize, pFile, nLine); return pNewBlock; } void bofMemFree(void *pBuf) { free(pBuf); } Fixed fixedMultiply(Fixed Multiplicand, Fixed Multiplier) { int64 nTmpNum = (int64)Multiplicand * Multiplier; Fixed fixResult = (Fixed)(nTmpNum >> 16); return fixResult; } Fixed fixedDivide(Fixed Dividend, Fixed Divisor) { int64 nBigNum = (int64)Dividend << 16; Fixed fixResult = (Fixed)(nBigNum / Divisor); return fixResult; } void bofMemSet(void *pSrc, byte chByte, int32 lBytes) { assert(pSrc != nullptr); byte *pBuf = (byte *)pSrc; while (lBytes-- != 0) *pBuf++ = chByte; } void bofMemCopy(void *pDst, const void *pSrc, int32 lLength) { assert(pDst != nullptr); assert(pSrc != nullptr); assert(lLength >= 0); byte *p1 = (byte *)pDst; const byte *p2 = (const byte *)pSrc; while (lLength-- != 0) { *p1++ = *p2++; } } bool readLine(Common::SeekableReadStream *fp, char *pszBuf) { if (fp->eos()) return false; Common::String line = fp->readLine(); Common::strcpy_s(pszBuf, MAX_LINE_LEN, line.c_str()); strreplaceChar(pszBuf, '\n', '\0'); return true; } void encrypt(void *pBuf, int32 size, const char *pszPassword) { assert(pBuf != nullptr); const char *pStart = pszPassword; if (!pszPassword || strlen(pszPassword) == 0) { pStart = "\0\0"; } byte *p = (byte *)pBuf; const char *pPW = pStart; while (--size >= 0) { *p ^= (byte)(0xD2 + size + *pPW); p++; if (*pPW++ == '\0') { pPW = pStart; } } } void encryptPartial(void *pBuf, int32 fullSize, int32 lBytes, const char *pszPassword) { assert(pBuf != nullptr); const char *pStart = pszPassword; if (!pszPassword || strlen(pszPassword) == 0) { pStart = "\0\0"; } byte *p = (byte *)pBuf; const char *pPW = pStart; while (--lBytes >= 0) { fullSize--; *p ^= (byte)(0xD2 + fullSize + *pPW); p++; if (*pPW++ == '\0') { pPW = pStart; } } } int mapWindowsPointSize(int pointSize) { return pointSize; } void ErrorLog(const char *logFile, const char *format, ...) { // No implementation } int StrFreqMatch(const char *mask, const char *test) { static int nCount[256]; int i, divergence; /* can't access null pointers */ assert(mask != nullptr); assert(test != nullptr); /* assume no match by making the divergence really high */ divergence = 100; /* * the first letter has to match before we even think about continuing */ if (*mask == *test) { /* reset the frequency count */ memset(nCount, 0, sizeof(int) * 256); /* count the frequency of the chars in 'mask' */ while (*mask != '\0') nCount[(int)*mask++] += 1; /* subtract off the frequency of the chars in 'test' */ while (*test != '\0') nCount[(int)*test++] -= 1; /* * total all of the frequencies */ divergence = 0; for (i = 0; i <= 255; i++) divergence += abs(nCount[i]); } /* returning a 0 or 1 means that the strings are almost identical */ return (divergence); } bool StrCompare(const char *pszStr1, const char *pszStr2, unsigned int nSize) { char *s1, *p, string1[256]; /* replace this stack hog with malloc */ char *s2, *sp, string2[256]; /* replace this stack hog with malloc */ int i, n, inc; bool bMatch; /* can't access null pointers */ assert(pszStr1 != nullptr); assert(pszStr2 != nullptr); /* make sure that we are not going to blow the stack */ assert(strlen(pszStr1) < 256); assert(strlen(pszStr2) < 256); p = s1 = string1; s2 = string2; /* * Reset these buffers to garuntee the strings will terminate */ memset(s1, 0, 256); memset(s2, 0, 256); /* make local copies of the strings */ Common::sprintf_s(s1, 256, " %s", pszStr1); Common::sprintf_s(s2, 256, " %s", pszStr2); /* * make "THE", "AN", and "A" be special tokens - make them uppercase while * all other words are lowercase. */ strLower(s1); StrUprStr(s1, " the "); StrUprStr(s1, " an "); StrUprStr(s1, " a "); if ((sp = strstr(s2, " THE ")) != nullptr) { memmove(sp, sp + 5, strlen(sp + 5) + 1); } /* * strip out all unwanted characters */ /* strip out all spaces */ StrStripChar(s1, ' '); StrStripChar(s2, ' '); /* strip out any apostrophes */ StrStripChar(s1, 39); StrStripChar(s2, 39); /* strip out any commas */ StrStripChar(s1, ','); StrStripChar(s2, ','); /* strip out any dashes */ StrStripChar(s1, '-'); StrStripChar(s2, '-'); /* * add a buffer zone to the end of both strings * (this might now be obsolete) */ Common::strcat_s(s1, 256, " "); Common::strcat_s(s2, 256, " "); /* * compare the 2 strings, if we get a "THE", "A", or "AN" (case sensative) * then do a special compare */ /* assume they match */ bMatch = true; i = 0; n = strlen(s1); while (i++ < n) { /* * handle special tokens */ if ((*s1 == 'T') || (*s1 == 'A')) { inc = 3; if (*s1 == 'A') { inc = 1; if (*(s1 + 1) == 'N') { inc = 2; } } p = s1; if (toupper(*s1) != toupper(*s2)) { s1 += inc; i += inc; } else { p = s1 + inc; i += inc; } } if ((toupper(*s1) != toupper(*s2)) && (toupper(*p) != toupper(*s2))) { bMatch = false; break; } s1++; s2++; p++; } return (bMatch); } /***************************************************************************** * * StrCharCount - Counts number of occurences of a specified char in String * * DESCRIPTION: Counts the number of times the specified character occurs * in the given string. * * SAMPLE USAGE: * n = StrCharCount(str, c); * const char *str; pointer to string to parse * char c; character to count in str * * RETURNS: int = number of times character c occurs in string str * *****************************************************************************/ int StrCharCount(const char *str, char c) { int n; assert(str != nullptr); assert(strlen(str) <= 255); n = 0; while (*str != '\0') { if (*str++ == c) n++; } return (n); } /** * name StriStr - same as strstr() except ignores case * * synopsis s = StriStr(s1, s2) * const char *s1 string to parse * const char *s2 substring to find in s1 * * purpose To search for a string inside another string while ignoring case * * * returns pointer to substring s2 in s1 or nullptr if not found * **/ char *StriStr(char *s1, const char *s2) { char *p, str1[80]; char str2[80]; /* can't access null pointers */ assert(s1 != nullptr); assert(s2 != nullptr); /* make sure we don't blow the stack */ assert(strlen(s1) < 80); assert(strlen(s2) < 80); /* copy to local buffers */ Common::strcpy_s(str1, s1); Common::strcpy_s(str2, s2); /* convert to upper case */ strUpper(str1); strUpper(str2); /* find str2 in str1 */ p = strstr(str1, str2); /* re-point to original string s1 */ if (p != nullptr) { p = s1 + (p - str1); } return (p); } void StrUprStr(char *s1, const char *s2) { char *p; int i, n; /* can't access null pointers */ assert(s1 != nullptr); assert(s2 != nullptr); p = s1; while ((p = StriStr(p, s2)) != nullptr) { n = strlen(s2); for (i = 0; i < n; i++) { *p = (char)toupper(*p); p++; } } } /** * name StrCpyStripChar - Same as Common::strcpy_s() except specified character * will be stripped from the destination string. * * synopsis StrCpyStripChar(dest, source, c) * char *dest destinaton string * const char *source source string * char c character to strip from dest * * purpose To strip out a specified character while copying 1 string to another * * * returns Nothing * **/ void StrCpyStripChar(char *dest, const char *source, char c) { /* can't access null pointers */ assert(dest != nullptr); assert(source != nullptr); /* source and destination cannot be the same */ assert(dest != source); do { if ((*dest = *source) != c) dest++; } while (*source++ != '\0'); } char *StrStripChar(char *str, char c) { char *p = str; /* can't acces a null pointer */ assert(str != nullptr); /* if c was '\0' then this function would do nothing */ assert(c != '\0'); while (*p != '\0') { if (*p == c) { /* move the string left 1 byte (including the terminator) */ memmove(p, p + 1, strlen(p + 1) + 1); } p++; } return (str); } char *StrReplaceChar(char *str, char cOld, char cNew) { char *p = str; /* can't acces a null pointer */ assert(str != nullptr); /* if cOld was '\0' then this function would do nothing */ assert(cOld != '\0'); while (*p != '\0') { if (*p == cOld) { *p = cNew; } p++; } return (str); } /** * name ProbableTrue * synopsis - return a true / false based on the probability given * int nProbability the probability of returning a true * * purpose to return a true of the tine * * * returns bool * **/ bool ProbableTrue(int nProbability) { int nRand = brand() % 100; return (nRand < nProbability); } } // namespace Bagel