void C4ValueMapData::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) { bool deserializing = pComp->isDeserializer(); C4ValueMapNames *pOldNames = pNames; if (deserializing) Reset(); // Compile item count int32_t iValueCnt; if (!deserializing) iValueCnt = pNames ? pNames->iSize : 0; pComp->Value(mkDefaultAdapt(iValueCnt, 0)); // nuthing 2do for no items if (!iValueCnt) return; // Separator (';') pComp->Separator(StdCompiler::SEP_SEP2); // Data char **ppNames = !deserializing ? pNames->pNames : new char * [iValueCnt]; if (deserializing) for (int32_t i = 0; i < iValueCnt; i++) ppNames[i] = nullptr; C4Value *pValues = !deserializing ? pData : new C4Value [iValueCnt]; // Compile try { for (int32_t i = 0; i < iValueCnt; i++) { // Separate if (i) pComp->Separator(); // Name StdStrBuf Name; if (!deserializing) Name.Ref(ppNames[i]); pComp->Value(mkParAdapt(Name, StdCompiler::RCT_Idtf)); if (deserializing) ppNames[i] = Name.GrabPointer(); // Separator ('=') pComp->Separator(StdCompiler::SEP_SET); // Value pComp->Value(mkParAdapt(pValues[i], numbers)); } } catch (...) { // make sure no mem is leaked on compiler error in name list if (deserializing) { for (int32_t i = 0; i < iValueCnt; i++) if (ppNames[i]) free(ppNames[i]); delete [] ppNames; delete [] pValues; } throw; } // Set if (deserializing) { // Set CreateTempNameList(); pNames->SetNameArray(const_cast<const char **>(ppNames), iValueCnt); for (int32_t i = 0; i < iValueCnt; i++) free(ppNames[i]); delete [] ppNames; delete [] pData; pData = pValues; // Assign old name list if (pOldNames) SetNameList(pOldNames); } }
bool C4InteractiveThread::ThreadLogDebug(const char *szMessage, ...) { // format message va_list lst; va_start(lst, szMessage); StdStrBuf Msg = FormatStringV(szMessage, lst); // send to main thread return PushEvent(Ev_LogDebug, Msg.GrabPointer()); }
bool C4Network2Res::SetByCore(const C4Network2ResCore &nCore, bool fSilent, const char *szAsFilename, int32_t iRecursion) // by main thread { StdStrBuf sFilename; // try open local file const char *szFilename = szAsFilename ? szAsFilename : GetC4Filename(nCore.getFileName()); if (SetByFile(szFilename, false, nCore.getType(), nCore.getID(), nCore.getFileName(), fSilent)) { // check contents checksum if (Core.getContentsCRC() == nCore.getContentsCRC()) { // set core fDirty = true; Core = nCore; // ok then return true; } } // get and search for filename without specified folder (e.g., Castle.ocs when the opened game is Easy.ocf\Castle.ocs) const char *szFilenameOnly = GetFilename(szFilename); const char *szFilenameC4 = GetC4Filename(szFilename); if (szFilenameOnly != szFilenameC4) { sFilename.Copy(szFilename, SLen(szFilename) - SLen(szFilenameC4)); sFilename.Append(szFilenameOnly); if (SetByCore(nCore, fSilent, szFilenameOnly, Config.Network.MaxResSearchRecursion)) return true; } // if it could still not be set, try within all folders of root (ignoring special folders), and try as file outside the folder // but do not recurse any deeper than set by config (default: One folder) if (iRecursion >= Config.Network.MaxResSearchRecursion) return false; StdStrBuf sSearchPath; const char *szSearchPath; if (!iRecursion) szSearchPath = Config.General.ExePath.getData(); else { sSearchPath.Copy(szFilename, SLen(szFilename) - SLen(szFilenameC4)); szSearchPath = sSearchPath.getData(); } StdStrBuf sNetPath; sNetPath.Copy(Config.Network.WorkPath); char *szNetPath = sNetPath.GrabPointer(); TruncateBackslash(szNetPath); sNetPath.Take(szNetPath); for (DirectoryIterator i(szSearchPath); *i; ++i) if (DirectoryExists(*i)) if (!*GetExtension(*i)) // directories without extension only if (!szNetPath || !*szNetPath || !ItemIdentical(*i, szNetPath)) // ignore network path { // search for complete name at subpath (e.g. MyFolder\Easy.ocf\Castle.ocs) sFilename.Format("%s%c%s", *i, DirectorySeparator, szFilenameC4); if (SetByCore(nCore, fSilent, sFilename.getData(), iRecursion + 1)) return true; } // file could not be found locally return false; }
BOOL C4Scenario::Decompile(char **ppOutput, int32_t *ipSize, bool fSaveSection) { try { // Decompile StdStrBuf Buf = DecompileToBuf<StdCompilerINIWrite>(mkParAdapt(*this, fSaveSection)); // Return *ppOutput = Buf.GrabPointer(); *ipSize = Buf.getSize(); } catch(StdCompiler::Exception *) { return FALSE; } return TRUE; }
bool C4ObjectInfoCore::Decompile(char **ppOutput, size_t *ipSize) { StdStrBuf Buf; if (!DecompileToBuf_Log<StdCompilerINIWrite>( mkNamingAdapt(*this, "ObjectInfo"), &Buf, "ObjectInfo")) { if (ppOutput) *ppOutput = NULL; if (ipSize) *ipSize = 0; return false; } if (ppOutput) *ppOutput = Buf.GrabPointer(); if (ipSize) *ipSize = Buf.getSize(); return true; }
C4FileSelDlg::DefaultListItem::DefaultListItem(const char *szFilename, bool fTruncateExtension, bool fCheckbox, bool fGrayed, C4GUI::Icons eIcon) : C4FileSelDlg::ListItem(szFilename), pLbl(NULL), pCheck(NULL), pKeyCheck(NULL), fGrayed(fGrayed) { StdStrBuf sLabel; if (szFilename) sLabel.Ref(::GetFilename(szFilename)); else sLabel.Ref(LoadResStr("IDS_CTL_NONE")); if (szFilename && fTruncateExtension) { sLabel.Copy(); char *szFilename = sLabel.GrabPointer(); RemoveExtension(szFilename); sLabel.Take(szFilename); } rcBounds.Hgt = C4GUI::GetRes()->TextFont.GetLineHeight(); UpdateSize(); C4GUI::ComponentAligner caMain(GetContainedClientRect(), 0, 0); int32_t iHeight = caMain.GetInnerHeight(); if (fCheckbox) { pCheck = new C4GUI::CheckBox(caMain.GetFromLeft(iHeight), NULL, false); if (fGrayed) pCheck->SetEnabled(false); AddElement(pCheck); pKeyCheck = new C4KeyBinding( C4KeyCodeEx(K_SPACE), "FileSelToggleFileActive", KEYSCOPE_Gui, new C4GUI::ControlKeyCB<ListItem>(*this, &ListItem::UserToggleCheck), C4CustomKey::PRIO_Ctrl); } C4GUI::Icon *pIco = new C4GUI::Icon(caMain.GetFromLeft(iHeight), eIcon); AddElement(pIco); pLbl = new C4GUI::Label( sLabel.getData(), caMain.GetAll(), ALeft, fGrayed ? C4GUI_CheckboxDisabledFontClr : C4GUI_CheckboxFontClr); AddElement(pLbl); }
bool C4Network2IO::HandlePacket(const C4NetIOPacket &rPacket, C4Network2IOConnection *pConn, bool fThread) { // security: add connection reference if (!pConn) return false; pConn->AddRef(); // accept only PID_Conn and PID_Ping on non-accepted connections if(!pConn->isHalfAccepted()) if(rPacket.getStatus() != PID_Conn && rPacket.getStatus() != PID_Ping && rPacket.getStatus() != PID_ConnRe) return false; // unpack packet (yet another no-idea-why-it's-needed-cast) C4IDPacket Pkt; C4PacketBase &PktB = Pkt; try { PktB.unpack(rPacket); } catch (StdCompiler::Exception *pExc) { Application.InteractiveThread.ThreadLog("Network: error: Failed to unpack packet id %02x: %s", rPacket.getStatus(), pExc->Msg.getData()); delete pExc; #ifndef _DEBUG pConn->Close(); #endif return false; } // dump packet (network thread only) #if(C4NET2IO_DUMP_LEVEL > 0) if (Config.Network.PacketLogging && fThread && Pkt.getPktType() != PID_Ping && Pkt.getPktType() != PID_Pong && Pkt.getPktType() != PID_NetResData) { // StdStrBuf PacketDump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdaptrPacket); StdStrBuf PacketHeader = FormatString("HandlePacket: %s by %s:%d (%lu bytes, counter %d)", C4TimeMilliseconds::Now().AsString().getData(), inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port), static_cast<unsigned long>(rPacket.getSize()), pConn->getInPacketCounter()); StdStrBuf Dump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(Pkt, PacketHeader.getData())); // Put it directly. The standard functions behind StdBuf.Format seem to choke when you pass them too much data. Application.InteractiveThread.PushEvent(Ev_LogSilent, Dump.GrabPointer()); } #endif // search packet handling data bool fSendToMainThread = false, fHandled = false; for (const C4PktHandlingData *pHData = PktHandlingData; pHData->ID != PID_None; pHData++) if (pHData->ID == rPacket.getStatus()) { // correct thread? if (!pHData->ProcByThread == !fThread) { // connection accepted? if (pHData->AcceptedOnly || pConn->isAccepted() || pConn->isClosed()) { fHandled = true; #if(C4NET2IO_DUMP_LEVEL > 2) C4TimeMilliseconds tStart = C4TimeMilliseconds::Now(); #endif // call handler(s) CallHandlers(pHData->HandlerID, &Pkt, pConn, fThread); #if(C4NET2IO_DUMP_LEVEL > 2) uint32_t iBlockedTime = C4TimeMilliseconds::Now() - tStart; if (fThread && iBlockedTime > 100) { Application.InteractiveThread.ThreadLogS("HandlePacket: ... blocked for %u ms!", iBlockedTime); } #endif } } // transfer to main thread? else if (!pHData->ProcByThread && fThread) { fHandled = true; fSendToMainThread = true; } } // send to main thread? if (fSendToMainThread) { // create data NetEvPacketData *pEvData = new NetEvPacketData; pEvData->Packet.Take(rPacket.Duplicate()); pEvData->Conn = pConn; pConn->AddRef(); // trigger event if (!Application.InteractiveThread.PushEvent(Ev_Net_Packet, pEvData)) Application.InteractiveThread.ThreadLogS("...push event "); } // unhandled? if (!fHandled && !pConn->isClosed()) Application.InteractiveThread.ThreadLog("Network: Unhandled packet (status %02x)", rPacket.getStatus()); // remove connection reference pConn->DelRef(); return fHandled; }