VStr VMemberBase::GetFullName() const { guardSlow(VMemberBase::GetFullName); if (Outer) return Outer->GetFullName() + "." + Name; return VStr(Name); unguardSlow; }
bool VStreamFileReader::Close() { guardSlow(VStreamFileReader::Close); if (File) fclose(File); File = NULL; return !bError; unguardSlow; }
bool VMemberBase::IsIn(VMemberBase* SomeOuter) const { guardSlow(VMemberBase::IsIn); for (VMemberBase* Tst = Outer; Tst; Tst = Tst->Outer) if (Tst == SomeOuter) return true; return !SomeOuter; unguardSlow; }
void VStreamFileReader::Serialise(void* V, int Length) { guardSlow(VStreamFileReader::Serialise); if (fread(V, Length, 1, File) != 1) { bError = true; Error->Logf("fread failed: Length=%i Error=%i", Length, ferror(File)); } unguardSlow; }
bool Close() { guardSlow(VStreamFileWriter::Close); if (File && fclose(File)) { bError = true; Error->Logf("fclose failed"); } File = NULL; return !bError; unguardSlow; }
void appCopyFilename(char *dest, const char *src, int len) { guardSlow(appCopyFilename); char c; // copy name with replacing '\' -> '/' and lowercasing const char *s = src; char *d = dest; while (len--) { c = *s++; if (c == '\\') c = '/'; else if (c >= 'A' && c <= 'Z') c += 32; *d++ = c; if (!c) break; } if (len < 0) *(--d) = 0; s = d = dest; len = 0; do { c = *s++; if (c == '/') { // replace '//' -> '/' (may be when "path/" + "/name") when not at start (allow win32 network path) if (len) while (*s == '/') s++; if (s[0] == '.' && s[1] == '.' && s[2] == '/'&& len && *(s-2) != '.') // cut "dir/../", but leave "../.." { do { d--; len--; } while (len && *d != '/'); if (*d == '/') { d++; len++; } c = s[3]; s += 4; } else if (s[0] == '.' && s[1] == '/') // cut "/./" s += 2; } *d++ = c; len++; } while (c); unguardSlow; }
int appSprintf(char *dest, int size, const char *fmt, ...) { guardSlow(appSprintf); va_list argptr; va_start(argptr, fmt); int len = vsnprintf(dest, size, fmt, argptr); va_end(argptr); if (len < 0 || len >= size - 1) appWPrintf("appSprintf: overflow of %d (called by \"%s\")\n", size, appSymbolName(GET_RETADDR(dest))); return len; unguardSlow; }
// name of this function is a short form of "VarArgs" const char *va(const char *format, ...) { guardSlow(va); static char buf[VA_BUFSIZE]; static int bufPos = 0; // wrap buffer if (bufPos >= VA_BUFSIZE - VA_GOODSIZE) bufPos = 0; va_list argptr; va_start(argptr, format); // print char *str = buf + bufPos; int len = vsnprintf(str, VA_BUFSIZE - bufPos, format, argptr); if (len < 0 && bufPos > 0) { // buffer overflow - try again with printing to buffer start bufPos = 0; str = buf; len = vsnprintf(buf, VA_BUFSIZE, format, argptr); } va_end(argptr); if (len < 0) // not enough buffer space { const char suffix[] = " ... (overflow)"; // it is better, than return empty string memcpy(buf + VA_BUFSIZE - sizeof(suffix), suffix, sizeof(suffix)); return str; } bufPos += len + 1; return str; unguardSlow; }
void VField::CopyFieldValue(const vuint8* Src, vuint8* Dst, const VFieldType& Type) { guardSlow(VField::CopyFieldValue); switch (Type.Type) { case TYPE_Int: *(vint32*)Dst = *(const vint32*)Src; break; case TYPE_Byte: *(vuint8*)Dst = *(const vuint8*)Src; break; case TYPE_Bool: if (*(const vuint32*)Src & Type.BitMask) *(vuint32*)Dst |= Type.BitMask; else *(vuint32*)Dst &= ~Type.BitMask; break; case TYPE_Float: *(float*)Dst = *(const float*)Src; break; case TYPE_Vector: *(TVec*)Dst = *(const TVec*)Src; break; case TYPE_Name: *(VName*)Dst = *(const VName*)Src; break; case TYPE_String: *(VStr*)Dst = *(const VStr*)Src; break; case TYPE_Pointer: *(void**)Dst = *(void*const*)Src; break; case TYPE_Reference: *(VObject**)Dst = *(VObject*const*)Src; break; case TYPE_Class: *(VClass**)Dst = *(VClass*const*)Src; break; case TYPE_State: *(VState**)Dst = *(VState*const*)Src; break; case TYPE_Delegate: *(VObjectDelegate*)Dst = *(const VObjectDelegate*)Src; break; case TYPE_Struct: Type.Struct->CopyObject(Src, Dst); break; case TYPE_Array: { VFieldType IntType = Type; IntType.Type = Type.ArrayInnerType; int InnerSize = IntType.GetSize(); for (int i = 0; i < Type.ArrayDim; i++) { CopyFieldValue(Src + i * InnerSize, Dst + i * InnerSize, IntType); } } break; case TYPE_DynamicArray: { VScriptArray& ASrc = *(VScriptArray*)Src; VScriptArray& ADst = *(VScriptArray*)Dst; VFieldType IntType = Type; IntType.Type = Type.ArrayInnerType; int InnerSize = IntType.GetSize(); ADst.SetNum(ASrc.Num(), IntType); for (int i = 0; i < ASrc.Num(); i++) { CopyFieldValue(ASrc.Ptr() + i * InnerSize, ADst.Ptr() + i * InnerSize, IntType); } } break; } unguardSlow; }
// Mask variants: // 1) * - any file // 2) *.* - any file // 3) *rest - name ends with "rest" (for example, ".ext") // 4) start* - name starts with "start" // 4) text - name equals "text" // Comparision is case-sensitive, when ignoreCase == false (default) // A few masks can be separated with ',' bool appMatchWildcard(const char *name, const char *mask, bool ignoreCase) { guardSlow(appMatchWildcard); if (!name[0] && !mask[0]) return true; // empty strings matched TString<256> MaskCopy, NameCopy; if (ignoreCase) { NameCopy.toLower(name); name = NameCopy; MaskCopy.toLower(mask); } else MaskCopy = mask; int namelen = strlen(name); // can use TStringSplitter here const char *next; for (mask = MaskCopy; mask; mask = next) { // find next wildcard (comma-separated) next = strchr(mask, ','); int masklen; if (next) { masklen = next - mask; next++; // skip ',' } else masklen = strlen(mask); if (!masklen) { // used something like "mask1,,mask3" (2nd mask is empty) //?? Com_DPrintf("appMatchWildcard: skip empty mask in \"%s\"\n", mask); continue; } // check for a trivial wildcard if (mask[0] == '*') { if (masklen == 1 || (masklen == 3 && mask[1] == '.' && mask[2] == '*')) return true; // "*" or "*.*" -- any name valid } // "*text*" mask if (masklen >= 3 && mask[0] == '*' && mask[masklen-1] == '*') { int i; mask++; masklen -= 2; for (i = 0; i <= namelen - masklen; i++) if (!memcmp(&name[i], mask, masklen)) return true; } else { // "*text" or "text*" mask const char *suff = strchr(mask, '*'); if (next && suff >= next) suff = NULL; // suff can be in next wildcard if (suff) { int preflen = suff - mask; int sufflen = masklen - preflen - 1; suff++; if (namelen < preflen + sufflen) continue; // name is not long enough if (preflen && memcmp(name, mask, preflen)) continue; // different prefix if (sufflen && memcmp(name + namelen - sufflen, suff, sufflen)) continue; // different suffix return true; } // exact match ("text") if (namelen == masklen && !memcmp(name, mask, namelen)) return true; } } return false; unguardSlow; }