├── .gitattributes ├── .gitignore ├── AddF9card.cmake ├── CMakeLists.txt ├── DotNET ├── fon9api.cs ├── fon9dllName.cs ├── fon9fmkt.cs ├── fon9io.cs ├── fon9rc.cs ├── fon9sv.cs └── fon9sv_md.cs ├── LICENSE ├── Overview ├── AlNum.md ├── Bitv.md ├── Filing.md ├── Logging.md ├── Manage.md ├── Misc.md ├── Prepare.md ├── Subr.md ├── ThreadTools.md └── Trie.md ├── README.md ├── TODO.md ├── build ├── cmake │ ├── Fon9Co.sh │ ├── build.sh │ ├── infinity_test.sh │ ├── t_FileRevRead.sh │ ├── t_FixReceiver.sh │ └── unit_test_all.sh └── vs2015 │ ├── Fon9Co │ ├── Fon9Co.vcxproj │ └── Fon9Co.vcxproj.filters │ ├── _UnitTests │ ├── AQueue_UT.vcxproj │ ├── AQueue_UT.vcxproj.filters │ ├── AuthMgr_UT.vcxproj │ ├── AuthMgr_UT.vcxproj.filters │ ├── Base64_UT.vcxproj │ ├── Base64_UT.vcxproj.filters │ ├── Bitv_UT.vcxproj │ ├── Bitv_UT.vcxproj.filters │ ├── Buffer_UT.vcxproj │ ├── Buffer_UT.vcxproj.filters │ ├── CharVector_UT.vcxproj │ ├── CharVector_UT.vcxproj.filters │ ├── ConfigLoader_UT.vcxproj │ ├── ConfigLoader_UT.vcxproj.filters │ ├── Crypto_UT.vcxproj │ ├── Crypto_UT.vcxproj.filters │ ├── Endian_UT.vcxproj │ ├── Endian_UT.vcxproj.filters │ ├── FileRevRead_UT.vcxproj │ ├── FileRevRead_UT.vcxproj.filters │ ├── File_UT.vcxproj │ ├── File_UT.vcxproj.filters │ ├── FixFeeder_UT.vcxproj │ ├── FixFeeder_UT.vcxproj.filters │ ├── FixParser_UT.vcxproj │ ├── FixParser_UT.vcxproj.filters │ ├── FixReceiver_UT.vcxproj │ ├── FixReceiver_UT.vcxproj.filters │ ├── FixRecorder_UT.vcxproj │ ├── FixRecorder_UT.vcxproj.filters │ ├── FixSender_UT.vcxproj │ ├── FixSender_UT.vcxproj.filters │ ├── FlowControl_UT.vcxproj │ ├── FlowControl_UT.vcxproj.filters │ ├── FmktTools_UT.vcxproj │ ├── FmktTools_UT.vcxproj.filters │ ├── InnApf_UT.vcxproj │ ├── InnApf_UT.vcxproj.filters │ ├── InnDbf_UT.vcxproj │ ├── InnDbf_UT.vcxproj.filters │ ├── InnFile_UT.vcxproj │ ├── InnFile_UT.vcxproj.filters │ ├── IoDev_UT.vcxproj │ ├── IoDev_UT.vcxproj.filters │ ├── IoFixSession_UT.vcxproj │ ├── IoFixSession_UT.vcxproj.filters │ ├── LogFile_UT.vcxproj │ ├── LogFile_UT.vcxproj.filters │ ├── MemBlock_UT.vcxproj │ ├── MemBlock_UT.vcxproj.filters │ ├── ObjSupplier_UT.vcxproj │ ├── ObjSupplier_UT.vcxproj.filters │ ├── PackBcd_UT.vcxproj │ ├── PackBcd_UT.vcxproj.filters │ ├── PkCont_UT.vcxproj │ ├── PkCont_UT.vcxproj.filters │ ├── RcSv_UT.vcxproj │ ├── RcSv_UT.vcxproj.filters │ ├── Rc_UT.vcxproj │ ├── Rc_UT.vcxproj.filters │ ├── RevPrint_UT.vcxproj │ ├── RevPrint_UT.vcxproj.filters │ ├── SchTask_UT.vcxproj │ ├── SchTask_UT.vcxproj.filters │ ├── Seed_UT.vcxproj │ ├── Seed_UT.vcxproj.filters │ ├── Socket_UT.vcxproj │ ├── Socket_UT.vcxproj.filters │ ├── StrTo_UT.vcxproj │ ├── StrTo_UT.vcxproj.filters │ ├── StrView_UT.vcxproj │ ├── StrView_UT.vcxproj.filters │ ├── Subr_UT.vcxproj │ ├── Subr_UT.vcxproj.filters │ ├── Symb_UT.vcxproj │ ├── Symb_UT.vcxproj.filters │ ├── ThreadController_UT.vcxproj │ ├── ThreadController_UT.vcxproj.filters │ ├── TimeStamp_UT.vcxproj │ ├── TimeStamp_UT.vcxproj.filters │ ├── TimedFileName_UT.vcxproj │ ├── TimedFileName_UT.vcxproj.filters │ ├── Timer_UT.vcxproj │ ├── Timer_UT.vcxproj.filters │ ├── ToStr_UT.vcxproj │ ├── ToStr_UT.vcxproj.filters │ ├── Tree_UT.vcxproj │ ├── Tree_UT.vcxproj.filters │ ├── Trie_UT.vcxproj │ └── Trie_UT.vcxproj.filters │ ├── f9twf │ ├── f9twfExgMkt_UT.vcxproj │ ├── f9twfExgMkt_UT.vcxproj.filters │ ├── f9twf_SymbId_UT.vcxproj │ ├── f9twf_SymbId_UT.vcxproj.filters │ ├── libf9twf.vcxproj │ └── libf9twf.vcxproj.filters │ ├── f9tws │ ├── f9twsExgMkt_UT.vcxproj │ ├── f9twsExgMkt_UT.vcxproj.filters │ ├── f9twsTrade_UT.vcxproj │ ├── f9twsTrade_UT.vcxproj.filters │ ├── libf9tws.vcxproj │ └── libf9tws.vcxproj.filters │ ├── fon9.sln │ ├── libf9extests │ ├── libf9extests.vcxproj │ └── libf9extests.vcxproj.filters │ └── libfon9 │ ├── libfon9.vcxproj │ └── libfon9.vcxproj.filters ├── ext ├── logvs │ ├── NanoLog.cpp │ ├── NanoLog.hpp │ ├── README.md │ ├── lock-free-test.txt │ ├── logvs.cpp │ ├── makefile │ ├── mpsc_slist.hpp │ ├── vs.sh │ └── vsall.sh ├── sigslot │ ├── README.md │ ├── benchmark_f9s.cpp │ ├── benchmark_f9s.hpp │ ├── benchmark_f9u.cpp │ └── benchmark_f9u.hpp └── yas │ ├── main.cpp │ └── run.sh ├── f9extests ├── CMakeLists.txt ├── Config.h ├── ExgMktTester.cpp ├── ExgMktTester.hpp ├── README.md ├── SymbDyTest.cpp ├── SymbIn.cpp └── SymbIn.hpp ├── f9twf ├── CMakeLists.txt ├── Config.h ├── ExgLineTmpArgs.cpp ├── ExgLineTmpArgs.hpp ├── ExgLineTmpFactory.cpp ├── ExgLineTmpFactory.hpp ├── ExgLineTmpLog.cpp ├── ExgLineTmpLog.hpp ├── ExgLineTmpSession.cpp ├── ExgLineTmpSession.hpp ├── ExgMapFcmId.cpp ├── ExgMapFcmId.hpp ├── ExgMapMgr.cpp ├── ExgMapMgr.hpp ├── ExgMapSessionDn.cpp ├── ExgMapSessionDn.hpp ├── ExgMcChannel.cpp ├── ExgMcChannel.hpp ├── ExgMcChannelTunnel.cpp ├── ExgMcChannelTunnel.hpp ├── ExgMcFmtSS.hpp ├── ExgMcFmtSSToRts.cpp ├── ExgMcFmtSSToRts.hpp ├── ExgMcGroup.cpp ├── ExgMcGroup.hpp ├── ExgMcReceiver.cpp ├── ExgMcReceiver.hpp ├── ExgMcReceiverFactory.cpp ├── ExgMcReceiverFactory.hpp ├── ExgMcToMiConv.cpp ├── ExgMcToMiConv.hpp ├── ExgMdContracts.cpp ├── ExgMdContracts.hpp ├── ExgMdFmt.hpp ├── ExgMdFmtBS.hpp ├── ExgMdFmtBSToRts.cpp ├── ExgMdFmtBSToRts.hpp ├── ExgMdFmtBaseContract.hpp ├── ExgMdFmtBasicInfo.hpp ├── ExgMdFmtBasicInfoToRts.cpp ├── ExgMdFmtBasicInfoToRts.hpp ├── ExgMdFmtClosing.hpp ├── ExgMdFmtClosingToRts.cpp ├── ExgMdFmtClosingToRts.hpp ├── ExgMdFmtHL.hpp ├── ExgMdFmtI060.hpp ├── ExgMdFmtMatch.hpp ├── ExgMdFmtMatchToRts.cpp ├── ExgMdFmtMatchToRts.hpp ├── ExgMdFmtParsers.cpp ├── ExgMdFmtParsers.hpp ├── ExgMdFmtQuoteReq.hpp ├── ExgMdFmtQuoteReqToRts.cpp ├── ExgMdFmtQuoteReqToRts.hpp ├── ExgMdFmtSysInfo.hpp ├── ExgMdFmtSysInfoToRts.cpp ├── ExgMdFmtSysInfoToRts.hpp ├── ExgMdPkReceiver.cpp ├── ExgMdPkReceiver.hpp ├── ExgMdSymbs.cpp ├── ExgMdSymbs.hpp ├── ExgMiReceiver.cpp ├── ExgMiReceiver.hpp ├── ExgMiSystemBase.cpp ├── ExgMiSystemBase.hpp ├── ExgMkt_UT.cpp ├── ExgMrFmt.hpp ├── ExgMrRecover.cpp ├── ExgMrRecover.hpp ├── ExgTmpLinkSys.hpp ├── ExgTmpTradingR1.hpp ├── ExgTmpTradingR7.hpp ├── ExgTmpTradingR9.hpp ├── ExgTmpTypes.cpp ├── ExgTmpTypes.hpp ├── ExgTradingLineMgr.cpp ├── ExgTradingLineMgr.hpp ├── ExgTypes.hpp ├── TwfSymbRef.cpp ├── TwfSymbRef.hpp ├── TwfTickSize.cfg ├── TwfTickSize.cpp ├── TwfTickSize.hpp └── f9twf_SymbId_UT.cpp ├── f9tws ├── CMakeLists.txt ├── Config.h ├── ExgLineArgs.cpp ├── ExgLineArgs.hpp ├── ExgLineFactory.cpp ├── ExgLineFactory.hpp ├── ExgLineTmp.cpp ├── ExgLineTmp.hpp ├── ExgLineTmpFactory.cpp ├── ExgLineTmpFactory.hpp ├── ExgMdFmt.hpp ├── ExgMdFmt1.hpp ├── ExgMdFmt13.hpp ├── ExgMdFmt13Handler.cpp ├── ExgMdFmt13Handler.hpp ├── ExgMdFmt19.hpp ├── ExgMdFmt19Handler.cpp ├── ExgMdFmt19Handler.hpp ├── ExgMdFmt1Handler.cpp ├── ExgMdFmt1Handler.hpp ├── ExgMdFmt22.hpp ├── ExgMdFmt22Handler.cpp ├── ExgMdFmt22Handler.hpp ├── ExgMdFmt23.hpp ├── ExgMdFmt23Handler.cpp ├── ExgMdFmt23Handler.hpp ├── ExgMdFmt6.hpp ├── ExgMdFmt6Handler.cpp ├── ExgMdFmt6Handler.hpp ├── ExgMdFmt9.hpp ├── ExgMdFmt9Handler.cpp ├── ExgMdFmt9Handler.hpp ├── ExgMdFmtIx.hpp ├── ExgMdFmtIxHandler.cpp ├── ExgMdFmtIxHandler.hpp ├── ExgMdFmtIxNoList.cpp ├── ExgMdFmtIxNoList.hpp ├── ExgMdIndices.cpp ├── ExgMdIndices.hpp ├── ExgMdPkReceiver.cpp ├── ExgMdPkReceiver.hpp ├── ExgMdPlayer.cpp ├── ExgMdReceiverFactory.cpp ├── ExgMdReceiverFactory.hpp ├── ExgMdReceiverSession.cpp ├── ExgMdReceiverSession.hpp ├── ExgMdSymbs.cpp ├── ExgMdSymbs.hpp ├── ExgMdSystem.cpp ├── ExgMdSystem.hpp ├── ExgMdSystemBase.cpp ├── ExgMdSystemBase.hpp ├── ExgMkt_UT.cpp ├── ExgTradingLineFix.cpp ├── ExgTradingLineFix.hpp ├── ExgTradingLineFixFactory.cpp ├── ExgTradingLineFixFactory.hpp ├── ExgTradingLineMgr.cpp ├── ExgTradingLineMgr.hpp ├── ExgTypes.hpp ├── README.md ├── TwsTools.cpp ├── TwsTools.hpp ├── TwsTypes.h └── f9twsTrade_UT.cpp ├── fon9 ├── AQueue.hpp ├── AQueue_UT.cpp ├── Appender.cpp ├── Appender.hpp ├── Archive.hpp ├── Assert.c ├── Assert.h ├── Base64.cpp ├── Base64.hpp ├── Base64_UT.cpp ├── Bitv.h ├── BitvArchive.hpp ├── BitvDecode.cpp ├── BitvDecode.hpp ├── BitvEncode.cpp ├── BitvEncode.hpp ├── BitvFixedInt.hpp ├── Bitv_UT.cpp ├── Blob.c ├── Blob.h ├── ByteVector.cpp ├── ByteVector.hpp ├── CMakeLists.txt ├── CStrView.h ├── CTools.c ├── CTools.h ├── CharAry.hpp ├── CharAryL.hpp ├── CharVector.hpp ├── CharVector_UT.cpp ├── CmdArgs.cpp ├── CmdArgs.hpp ├── Comparable.hpp ├── ConfigFileBinder.cpp ├── ConfigFileBinder.hpp ├── ConfigLoader.cpp ├── ConfigLoader.hpp ├── ConfigLoader_UT.cpp ├── ConfigParser.cpp ├── ConfigParser.hpp ├── ConfigUtils.cpp ├── ConfigUtils.hpp ├── ConsoleIO.cpp ├── ConsoleIO.h ├── CountDownLatch.cpp ├── CountDownLatch.hpp ├── CtrlBreakHandler.c ├── CtrlBreakHandler.h ├── CyclicBarrier.cpp ├── CyclicBarrier.hpp ├── DecBase.cpp ├── DecBase.hpp ├── Decimal.hpp ├── DefaultThreadPool.cpp ├── DefaultThreadPool.hpp ├── DllHandle.cpp ├── DllHandle.hpp ├── DummyMutex.hpp ├── DyObj.hpp ├── Endian.hpp ├── Endian_UT.cpp ├── ErrC.cpp ├── ErrC.hpp ├── Exception.hpp ├── F9cardDevel.h ├── Fdr.hpp ├── FdrNotify.cpp ├── FdrNotify.hpp ├── File.cpp ├── File.hpp ├── FileAppender.cpp ├── FileAppender.hpp ├── FilePath.cpp ├── FilePath.hpp ├── FileReadAll.cpp ├── FileReadAll.hpp ├── FileRevRead.cpp ├── FileRevRead.hpp ├── FileRevRead_UT.cpp ├── File_UT.cpp ├── FlowControlCalc.cpp ├── FlowControlCalc.hpp ├── FlowControl_UT.cpp ├── FlowCounter.cpp ├── FlowCounter.hpp ├── FmtDef.cpp ├── FmtDef.hpp ├── FwdPrint.hpp ├── HistoryArray.hpp ├── HostId.cpp ├── HostId.hpp ├── InnApf.cpp ├── InnApf.hpp ├── InnApf_UT.cpp ├── InnDbf.cpp ├── InnDbf.hpp ├── InnDbfRoom.hpp ├── InnDbfTable.hpp ├── InnDbf_UT.cpp ├── InnFile.cpp ├── InnFile.hpp ├── InnFile_UT.cpp ├── InnStream.cpp ├── InnStream.hpp ├── InnSyncKey.hpp ├── InnSyncer.cpp ├── InnSyncer.hpp ├── InnSyncerFile.cpp ├── InnSyncerFile.hpp ├── IntSel.hpp ├── LevelArray.hpp ├── Log.cpp ├── Log.hpp ├── LogFile.cpp ├── LogFile.hpp ├── LogFile_UT.cpp ├── MessageQueue.hpp ├── MustLock.hpp ├── Named.cpp ├── Named.hpp ├── NamedIx.hpp ├── ObjPool.hpp ├── ObjSupplier.cpp ├── ObjSupplier.hpp ├── ObjSupplier_UT.cpp ├── Outcome.cpp ├── Outcome.hpp ├── PackBcd.hpp ├── PackBcd_UT.cpp ├── PassKey.cpp ├── PassKey.hpp ├── PkCont.cpp ├── PkCont.hpp ├── PkCont_UT.cpp ├── PkReceiver.cpp ├── PkReceiver.hpp ├── Random.cpp ├── Random.hpp ├── RevFormat.cpp ├── RevFormat.hpp ├── RevPrint.hpp ├── RevPrint_UT.cpp ├── RevPut.hpp ├── SchTask.cpp ├── SchTask.hpp ├── SchTask_UT.cpp ├── SimpleFactory.cpp ├── SimpleFactory.hpp ├── SinglyLinkedList.hpp ├── SleepPolicy.hpp ├── SortedVector.hpp ├── SpinMutex.hpp ├── StaticPtr.hpp ├── StrPicAux.hpp ├── StrTo.cpp ├── StrTo.hpp ├── StrTo_UT.cpp ├── StrTools.cpp ├── StrTools.hpp ├── StrView.hpp ├── StrView_UT.cpp ├── StrVref.hpp ├── Subr.hpp ├── Subr_UT.cpp ├── TestTools.hpp ├── TestTools_MemUsed.hpp ├── ThreadController.hpp ├── ThreadController_UT.cpp ├── ThreadId.cpp ├── ThreadId.hpp ├── ThreadTools.cpp ├── ThreadTools.hpp ├── TimeInterval.cpp ├── TimeInterval.hpp ├── TimeStamp.cpp ├── TimeStamp.hpp ├── TimeStamp_UT.cpp ├── TimedFileName.cpp ├── TimedFileName.hpp ├── TimedFileName_UT.cpp ├── Timer.cpp ├── Timer.hpp ├── Timer_UT.cpp ├── ToStr.cpp ├── ToStr.hpp ├── ToStrFmt.cpp ├── ToStrFmt.hpp ├── ToStr_UT.cpp ├── Tools.cpp ├── Tools.hpp ├── Trie.hpp ├── Trie_UT.cpp ├── TsAppend.cpp ├── TsAppend.hpp ├── TsReceiver.cpp ├── TsReceiver.hpp ├── TypeName.hpp ├── Unaligned.hpp ├── Utility.hpp ├── WaitPolicy.hpp ├── Worker.hpp ├── auth │ ├── AuthBase.h │ ├── AuthBase.hpp │ ├── AuthMgr.cpp │ ├── AuthMgr.hpp │ ├── AuthMgr_UT.cpp │ ├── PassIdMgr.cpp │ ├── PassIdMgr.hpp │ ├── PoDupLogon.cpp │ ├── PoDupLogon.hpp │ ├── PolicyAcl.cpp │ ├── PolicyAcl.hpp │ ├── PolicyAgent.hpp │ ├── PolicyMaster.cpp │ ├── PolicyMaster.hpp │ ├── PolicySocketFrom.cpp │ ├── PolicySocketFrom.hpp │ ├── PolicyTable.cpp │ ├── PolicyTable.hpp │ ├── PolicyTree.cpp │ ├── PolicyTree.hpp │ ├── RoleMgr.cpp │ ├── RoleMgr.hpp │ ├── SaslClient.cpp │ ├── SaslClient.hpp │ ├── SaslScram.hpp │ ├── SaslScramServer.cpp │ ├── SaslScramServer.hpp │ ├── SaslScramSha256.cpp │ ├── SaslScramSha256.hpp │ ├── SaslScramSha256Client.cpp │ ├── SaslScramSha256Client.hpp │ ├── SaslScramSha256Server.cpp │ ├── SaslScramSha256Server.hpp │ ├── UserMgr.cpp │ └── UserMgr.hpp ├── buffer │ ├── BufferList.cpp │ ├── BufferList.hpp │ ├── BufferListBuilder.hpp │ ├── BufferNode.cpp │ ├── BufferNode.hpp │ ├── BufferNodeWaiter.cpp │ ├── BufferNodeWaiter.hpp │ ├── Buffer_UT.cpp │ ├── DcQueue.cpp │ ├── DcQueue.hpp │ ├── DcQueueList.cpp │ ├── DcQueueList.hpp │ ├── FwdBuffer.hpp │ ├── FwdBufferList.hpp │ ├── MemBlock.cpp │ ├── MemBlock.hpp │ ├── MemBlockImpl.hpp │ ├── MemBlock_UT.cpp │ ├── README.md │ ├── RevBuffer.cpp │ ├── RevBuffer.hpp │ ├── RevBufferList.cpp │ └── RevBufferList.hpp ├── crypto │ ├── CryptoTools.hpp │ ├── Crypto_UT.cpp │ ├── Sha1.cpp │ ├── Sha1.hpp │ ├── Sha256.cpp │ └── Sha256.hpp ├── fix │ ├── FixAdminDef.hpp │ ├── FixAdminMsg.cpp │ ├── FixAdminMsg.hpp │ ├── FixApDef.hpp │ ├── FixBase.cpp │ ├── FixBase.hpp │ ├── FixBuilder.cpp │ ├── FixBuilder.hpp │ ├── FixBusinessReject.cpp │ ├── FixBusinessReject.hpp │ ├── FixCompID.cpp │ ├── FixCompID.hpp │ ├── FixConfig.cpp │ ├── FixConfig.hpp │ ├── FixFeeder.cpp │ ├── FixFeeder.hpp │ ├── FixFeeder_UT.cpp │ ├── FixParser.cpp │ ├── FixParser.hpp │ ├── FixParser_UT.cpp │ ├── FixReceiver.cpp │ ├── FixReceiver.hpp │ ├── FixReceiver_UT.cpp │ ├── FixReceiver_UT_Case.txt │ ├── FixReceiver_UT_Result.txt │ ├── FixRecorder.cpp │ ├── FixRecorder.hpp │ ├── FixRecorder_Searcher.cpp │ ├── FixRecorder_Searcher.hpp │ ├── FixRecorder_UT.cpp │ ├── FixSender.cpp │ ├── FixSender.hpp │ ├── FixSender_UT.cpp │ ├── FixSession.cpp │ ├── FixSession.hpp │ ├── IoFixSender.cpp │ ├── IoFixSender.hpp │ ├── IoFixSession.cpp │ ├── IoFixSession.hpp │ ├── IoFixSession_UT.cpp │ └── README.md ├── fmkt │ ├── FmdRtsPackType.h │ ├── FmdRtsPackType.txt │ ├── FmdTypes.h │ ├── FmdTypes.hpp │ ├── FmktTools.cpp │ ├── FmktTools.hpp │ ├── FmktTools_UT.cpp │ ├── FmktTypes.h │ ├── FmktTypes.hpp │ ├── MdRtStream.cpp │ ├── MdRtStream.hpp │ ├── MdRtStreamInn.cpp │ ├── MdRtStreamInn.hpp │ ├── MdRtsTypes.cpp │ ├── MdRtsTypes.hpp │ ├── MdSymbs.cpp │ ├── MdSymbs.hpp │ ├── MdSystem.cpp │ ├── MdSystem.hpp │ ├── README.md │ ├── Symb.cpp │ ├── Symb.hpp │ ├── SymbBS.cpp │ ├── SymbBS.hpp │ ├── SymbBSData.hpp │ ├── SymbBreakSt.cpp │ ├── SymbBreakSt.hpp │ ├── SymbDeal.cpp │ ├── SymbDeal.hpp │ ├── SymbDealData.hpp │ ├── SymbDy.cpp │ ├── SymbDy.hpp │ ├── SymbDynBand.cpp │ ├── SymbDynBand.hpp │ ├── SymbFuoClosing.cpp │ ├── SymbFuoClosing.hpp │ ├── SymbQuoteReq.cpp │ ├── SymbQuoteReq.hpp │ ├── SymbRef.cpp │ ├── SymbRef.hpp │ ├── SymbTabNames.h │ ├── SymbTimePri.cpp │ ├── SymbTimePri.hpp │ ├── SymbTree.cpp │ ├── SymbTree.hpp │ ├── SymbTwa.cpp │ ├── SymbTwa.hpp │ ├── SymbTwaBase.cpp │ ├── SymbTwaBase.hpp │ ├── SymbTwf.cpp │ ├── SymbTwf.hpp │ ├── SymbTwfBase.cpp │ ├── SymbTwfBase.hpp │ ├── SymbTws.cpp │ ├── SymbTws.hpp │ ├── SymbTwsBase.cpp │ ├── SymbTwsBase.hpp │ ├── Symb_UT.cpp │ ├── TradingLine.cpp │ ├── TradingLine.hpp │ ├── TradingLineGroup.cpp │ ├── TradingLineGroup.hpp │ ├── TradingLineHelper1.cpp │ ├── TradingLineHelper1.hpp │ ├── TradingLineManagerSeed.cpp │ ├── TradingLineManagerSeed.hpp │ ├── TradingRequest.cpp │ ├── TradingRequest.hpp │ └── TwExgMdTime.hpp ├── framework │ ├── Fon9CoRun.cpp │ ├── Fon9Co_main.cpp │ ├── Framework.cpp │ ├── Framework.hpp │ ├── FrameworkFlag.cpp │ ├── FrameworkFlag.hpp │ ├── IoFactory.cpp │ ├── IoFactory.hpp │ ├── IoFactoryDgram.cpp │ ├── IoFactoryFileIO.cpp │ ├── IoFactoryTcpClient.cpp │ ├── IoFactoryTcpServer.cpp │ ├── IoFactoryTcpServerAB.cpp │ ├── IoManager.cpp │ ├── IoManager.hpp │ ├── IoManagerTree.cpp │ ├── IoManagerTree.hpp │ ├── NamedIoManager.cpp │ ├── SeedImporter.cpp │ ├── SeedSession.cpp │ ├── SeedSession.hpp │ ├── SessionFactoryConfigWithAuthMgr.cpp │ └── SessionFactoryConfigWithAuthMgr.hpp ├── intrusive_ptr.hpp ├── intrusive_ref_counter.hpp ├── io │ ├── Device.cpp │ ├── Device.hpp │ ├── DeviceAsyncOp.hpp │ ├── DeviceParseConfig.hpp │ ├── DeviceRecvEvent.hpp │ ├── DeviceStartSend.hpp │ ├── DgramBase.cpp │ ├── DgramBase.hpp │ ├── FdrDgram.cpp │ ├── FdrDgram.hpp │ ├── FdrService.cpp │ ├── FdrService.hpp │ ├── FdrServiceEpoll.cpp │ ├── FdrServiceEpoll.hpp │ ├── FdrSocket.cpp │ ├── FdrSocket.hpp │ ├── FdrSocketClient.cpp │ ├── FdrSocketClient.hpp │ ├── FdrTcpClient.cpp │ ├── FdrTcpClient.hpp │ ├── FdrTcpServer.cpp │ ├── FdrTcpServer.hpp │ ├── FileIO.cpp │ ├── FileIO.hpp │ ├── IoBase.cpp │ ├── IoBase.hpp │ ├── IoDev_UT.cpp │ ├── IoServiceArgs.cpp │ ├── IoServiceArgs.hpp │ ├── IoState.h │ ├── Manager.cpp │ ├── Manager.hpp │ ├── README.md │ ├── RecvBuffer.cpp │ ├── RecvBuffer.hpp │ ├── SendBuffer.cpp │ ├── SendBuffer.hpp │ ├── Server.cpp │ ├── Server.hpp │ ├── Session.cpp │ ├── Session.hpp │ ├── SimpleManager.hpp │ ├── Socket.cpp │ ├── Socket.hpp │ ├── SocketAddress.cpp │ ├── SocketAddress.hpp │ ├── SocketAddressDN.cpp │ ├── SocketAddressDN.hpp │ ├── SocketClientConfig.cpp │ ├── SocketClientConfig.hpp │ ├── SocketClientDevice.cpp │ ├── SocketClientDevice.hpp │ ├── SocketConfig.cpp │ ├── SocketConfig.hpp │ ├── SocketServer.cpp │ ├── SocketServer.hpp │ ├── Socket_UT.cpp │ ├── TcpClientBase.cpp │ ├── TcpClientBase.hpp │ ├── TcpServerBase.cpp │ ├── TcpServerBase.hpp │ ├── TestDevice.hpp │ └── win │ │ ├── IocpDgram.cpp │ │ ├── IocpDgram.hpp │ │ ├── IocpService.cpp │ │ ├── IocpService.hpp │ │ ├── IocpSocket.cpp │ │ ├── IocpSocket.hpp │ │ ├── IocpSocketClient.cpp │ │ ├── IocpSocketClient.hpp │ │ ├── IocpTcpClient.cpp │ │ ├── IocpTcpClient.hpp │ │ ├── IocpTcpServer.cpp │ │ └── IocpTcpServer.hpp ├── rc │ ├── README.md │ ├── Rc.cpp │ ├── Rc.h │ ├── Rc.hpp │ ├── RcClientApi.cpp │ ├── RcClientApi.h │ ├── RcClientSession.cpp │ ├── RcClientSession.hpp │ ├── RcFuncConn.cpp │ ├── RcFuncConn.hpp │ ├── RcFuncConnClient.cpp │ ├── RcFuncConnServer.cpp │ ├── RcFuncConnServer.hpp │ ├── RcMdRtsDecoder.cpp │ ├── RcMdRtsDecoder.h │ ├── RcMdRtsDecoder.hpp │ ├── RcSeedVisitor.cpp │ ├── RcSeedVisitor.h │ ├── RcSeedVisitor.hpp │ ├── RcSeedVisitorClient.cpp │ ├── RcSeedVisitorClient.hpp │ ├── RcSeedVisitorClientCAPI.cpp │ ├── RcSeedVisitorServer.cpp │ ├── RcSeedVisitorServer.hpp │ ├── RcSession.cpp │ ├── RcSession.hpp │ ├── RcSvStreamDecoder.cpp │ ├── RcSvStreamDecoder.hpp │ ├── RcSv_UT.cpp │ ├── RcSvc.cpp │ ├── RcSvc.hpp │ ├── RcSvcAck.cpp │ ├── RcSvcAck.hpp │ ├── RcSvcReq.cpp │ ├── RcSvcReq.hpp │ ├── RcSvcReqSeed.cpp │ ├── RcSvcReqSubr.cpp │ ├── RcSvsTicket.cpp │ ├── RcSvsTicket.hpp │ └── Rc_UT.cpp ├── seed │ ├── CloneTree.cpp │ ├── CloneTree.hpp │ ├── ConfigGridView.cpp │ ├── ConfigGridView.hpp │ ├── Field.cpp │ ├── Field.hpp │ ├── FieldBytes.cpp │ ├── FieldBytes.hpp │ ├── FieldChars.cpp │ ├── FieldChars.hpp │ ├── FieldCharsL.cpp │ ├── FieldCharsL.hpp │ ├── FieldDecimal.hpp │ ├── FieldDyBlob.cpp │ ├── FieldDyBlob.hpp │ ├── FieldInt.hpp │ ├── FieldMaker.cpp │ ├── FieldMaker.hpp │ ├── FieldSchCfgStr.cpp │ ├── FieldSchCfgStr.hpp │ ├── FieldString.hpp │ ├── FieldTimeStamp.hpp │ ├── FieldType.h │ ├── FieldValueFmt.hpp │ ├── FileImpTree.cpp │ ├── FileImpTree.hpp │ ├── Layout.cpp │ ├── Layout.hpp │ ├── MaConfigTree.cpp │ ├── MaConfigTree.hpp │ ├── MaTree.cpp │ ├── MaTree.hpp │ ├── NamedPark.cpp │ ├── NamedPark.hpp │ ├── Plugins.cpp │ ├── Plugins.hpp │ ├── PluginsMgr.cpp │ ├── PluginsMgr.hpp │ ├── PodOp.cpp │ ├── PodOp.hpp │ ├── README.md │ ├── Raw.cpp │ ├── Raw.hpp │ ├── RawRd.hpp │ ├── RawWr.hpp │ ├── SeedAcl.cpp │ ├── SeedAcl.hpp │ ├── SeedAclTree.cpp │ ├── SeedBase.cpp │ ├── SeedBase.hpp │ ├── SeedFairy.cpp │ ├── SeedFairy.hpp │ ├── SeedSearcher.cpp │ ├── SeedSearcher.hpp │ ├── SeedSubr.cpp │ ├── SeedSubr.hpp │ ├── SeedVisitor.cpp │ ├── SeedVisitor.hpp │ ├── Seed_UT.cpp │ ├── SysEnv.cpp │ ├── SysEnv.hpp │ ├── Tab.cpp │ ├── Tab.hpp │ ├── TabTreeOp.cpp │ ├── TabTreeOp.hpp │ ├── Tree.cpp │ ├── Tree.hpp │ ├── TreeLockContainerT.hpp │ ├── TreeOp.cpp │ ├── TreeOp.hpp │ └── Tree_UT.cpp ├── sys │ ├── Config.h │ ├── Config.hpp │ ├── FilePOSIX.hpp │ ├── FileWin32.hpp │ ├── OnWindowsMainExit.cpp │ └── OnWindowsMainExit.hpp └── web │ ├── HtmlEncoder.cpp │ ├── HtmlEncoder.hpp │ ├── HttpDate.cpp │ ├── HttpDate.hpp │ ├── HttpHandler.cpp │ ├── HttpHandler.hpp │ ├── HttpHandlerStatic.cpp │ ├── HttpHandlerStatic.hpp │ ├── HttpMessage.cpp │ ├── HttpMessage.hpp │ ├── HttpParser.cpp │ ├── HttpParser.hpp │ ├── HttpPlugins.cpp │ ├── HttpSession.cpp │ ├── HttpSession.hpp │ ├── HttpStatic.cfg │ ├── StartupHttpMa.md │ ├── UrlCodec.cpp │ ├── UrlCodec.hpp │ ├── WebSocket.cpp │ ├── WebSocket.hpp │ ├── WebSocketAuther.cpp │ ├── WebSocketAuther.hpp │ ├── WsSeedVisitor.cpp │ ├── WsSeedVisitor.hpp │ └── ma │ ├── crypto.js │ ├── fon9.css │ ├── fon9chgpass.html │ ├── fon9ma.html │ ├── fon9seed.html │ ├── fon9signon.html │ ├── gv.css │ ├── gvTable.js │ ├── logo-40.png │ ├── sasl-scram-ut.html │ ├── sasl-scram.js │ ├── sasl-ws-ut.html │ ├── sasl-ws.js │ ├── utils-seed.js │ └── utils.js ├── make_proj_verinfo.bat ├── make_proj_verinfo.sh └── make_static_o.sh /AddF9card.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # 在 CMakeLists.txt, 檢查是否有支援 f9card 的 source code. 3 | # 要在 add_subdirectory(fon9) 之前使用 include() 加入此檔, 4 | # 避免在多個路徑下皆有 f9/ 造成 libf9_s 重複定義; 5 | # 6 | # include(fon9/AddF9card.cmake) 7 | # add_subdirectory(fon9) 8 | # 9 | if(NOT DEFINED F9PATH) 10 | set(F9PATH "${CMAKE_CURRENT_SOURCE_DIR}/f9") 11 | if(EXISTS "${F9PATH}/net" AND IS_DIRECTORY "${F9PATH}/net") 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DF9CARD") 13 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DF9CARD") 14 | set(f9_s_lib "f9_s") 15 | add_subdirectory(f9) 16 | else() 17 | unset(F9PATH) 18 | endif() 19 | endif() 20 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(fon9) 3 | 4 | if(NOT CMAKE_BUILD_TYPE) 5 | set(CMAKE_BUILD_TYPE "Release") 6 | endif() 7 | 8 | set(CXX_FLAGS 9 | -g 10 | -Wall 11 | -Wextra 12 | -Wconversion 13 | -Wold-style-cast 14 | -Woverloaded-virtual 15 | -Wpointer-arith 16 | -Wshadow 17 | -Wwrite-strings 18 | -fexec-charset=UTF-8 19 | -std=c++11 20 | ${FON9_CXX_FLAGS} 21 | ) 22 | string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") 23 | 24 | set(C_FLAGS 25 | -g 26 | -Wall 27 | -Wextra 28 | -Wconversion 29 | -Wpointer-arith 30 | -Wshadow 31 | -Wwrite-strings 32 | -fexec-charset=UTF-8 33 | ${FON9_C_FLAGS} 34 | ) 35 | string(REPLACE ";" " " CMAKE_C_FLAGS "${C_FLAGS}") 36 | # --- 37 | include(AddF9card.cmake) 38 | # --- 39 | include_directories(.) 40 | 41 | add_subdirectory(fon9) 42 | 43 | if(CMAKE_FON9_BUILD_UNIT_TEST) 44 | add_subdirectory(f9extests) 45 | endif() 46 | 47 | add_subdirectory(f9tws) 48 | add_subdirectory(f9twf) 49 | -------------------------------------------------------------------------------- /DotNET/fon9dllName.cs: -------------------------------------------------------------------------------- 1 | namespace fon9 2 | { 3 | static class DotNetApi 4 | { 5 | public const string kDllName = "libfon9.dll"; 6 | } 7 | } -------------------------------------------------------------------------------- /DotNET/fon9io.cs: -------------------------------------------------------------------------------- 1 | namespace f9io 2 | { 3 | public enum State 4 | { 5 | /// 初始化尚未完成: Device 建構之後的初始狀態. 6 | Initializing, 7 | /// 建構 Device 的人必須主動呼叫 Device::Initialize() 才會進入此狀態. 8 | Initialized, 9 | 10 | /// Device::OpImpl_Open() 因設定錯誤的開啟失敗。 11 | /// 無法使用相同 cfgstr 再次開啟. 12 | ConfigError, 13 | /// 開啟中: 開啟尚未完成. 14 | /// 若開啟完成, 則進入底下3種可能的狀態, 視不同的 Device Style 而定: 15 | /// - WaitingLinkIn 16 | /// - Linking 17 | /// - Listening 18 | Opening, 19 | 20 | /// 連入等候中: 例如一個 USB port, 正在等候 USB 設備的插入. 21 | WaitingLinkIn, 22 | /// 連線建立中: 例如 TcpClient 呼叫了 connect(). 23 | Linking, 24 | /// 連線建立失敗: 例如 TcpClient 呼叫 connect() 之後沒有連線成功. 25 | LinkError, 26 | /// 連線成功: 可以開始收送資料. 27 | /// - WaitingLinkIn, Linking 之後, 連線成功的狀態. 28 | LinkReady, 29 | /// 連線中斷. 30 | /// - **LinkReady 之後** , 連線中斷了! 31 | LinkBroken, 32 | 33 | /// Listening(例如: TcpServer) 34 | Listening, 35 | /// Listening之後被中斷: reset 網卡/IP? 36 | ListenBroken, 37 | 38 | /// 逗留中, 等資料送完後關閉. 39 | Lingering, 40 | /// 關閉中. 41 | Closing, 42 | /// 已關閉. 43 | Closed, 44 | 45 | /// 即將解構, Device 已不可再使用! 46 | /// 當收到此狀態, 您應該盡快將 Device 釋放. 47 | Disposing, 48 | /// 在 Device::~Device() 最後的解構狀態. 49 | Destructing, 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Overview/Prepare.md: -------------------------------------------------------------------------------- 1 | fon9 library - prepare 2 | ======================= 3 | 4 | ## 主要開發工具及版本 5 | * Windows: VS 2015 6 | * `./build/vs2015/fon9.sln` 7 | * Linux: 8 | * cmake version 3.5.1 9 | * gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 10 | * `./build/cmake/build.sh` 11 | * 開啟 compiler 全部的警告訊息:警告訊息的重要性,相信不用再提醒了。 12 | * 警告訊息 -- 零容忍。 13 | 14 | ## 預設路徑結構 15 | ``` 16 | ~/devel/ 我的開發環境根目錄 17 | |-- external/ third-party libraries 18 | | 19 | |-- output/fon9/ libfon9 的輸出路徑,「輸出路徑」移到原始程式路徑之外,可以更容易「乾淨備份」。 20 | | |-- 64/Release/ 預設 Windows 的 fon9.sln 輸出路徑 21 | | \-- release/fon9/ 預設 Linux 輸出路徑 22 | | 23 | \-- fon9/ 24 | |-- fon9/ header(.hpp & .h) & source(.cpp & .c) 放在一起,更容易找到所需的檔案。 25 | | \-- sys/ 平台、Compiler 相關 26 | | 27 | |-- ext/ 配合 third-party 寫的測試或 benchmark 28 | | |-- sigslot/ signal-slot-benchmarks 29 | | \-- logvs/ logging 測試與比較 30 | | 31 | \-- build/ 32 | |-- cmake/ build shell for cmake 33 | \-- vs2015/ VS2015 project & solution files 34 | ``` 35 | -------------------------------------------------------------------------------- /build/cmake/Fon9Co.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # fon9/build/cmake/Fon9Co.sh 4 | # 5 | 6 | ulimit -c unlimited 7 | 8 | set -x 9 | set -e 10 | 11 | ~/devel/output/fon9/release/fon9/Fon9Co --workdir ~/devel/output/fon9 12 | -------------------------------------------------------------------------------- /build/cmake/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # fon9/build/cmake/build.sh 4 | # 5 | 6 | fon9path=`pwd`"$0" 7 | fon9path="${fon9path%/*}" 8 | fon9path="${fon9path%/*}" 9 | fon9path="${fon9path%/*}" 10 | develpath="${fon9path%/*}" 11 | 12 | set -x 13 | 14 | SOURCE_DIR=${fon9path} 15 | BUILD_DIR=${BUILD_DIR:-${develpath}/output/fon9} 16 | BUILD_TYPE=${BUILD_TYPE:-release} 17 | INSTALL_DIR=${INSTALL_DIR:-${develpath}/${BUILD_TYPE}} 18 | FON9_BUILD_UNIT_TEST=${FON9_BUILD_UNIT_TEST:-1} 19 | 20 | mkdir -p $BUILD_DIR/$BUILD_TYPE \ 21 | && cd $BUILD_DIR/$BUILD_TYPE \ 22 | && cmake \ 23 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 24 | -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \ 25 | -DCMAKE_FON9_BUILD_UNIT_TEST=$FON9_BUILD_UNIT_TEST \ 26 | $SOURCE_DIR \ 27 | && make $* 28 | -------------------------------------------------------------------------------- /build/cmake/infinity_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # fon9/build/cmake/infinity_test.sh 4 | # 5 | 6 | ulimit -c unlimited 7 | 8 | set -x 9 | set -e 10 | 11 | while true 12 | do 13 | $* 14 | done 15 | -------------------------------------------------------------------------------- /build/cmake/t_FileRevRead.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # fon9/build/cmake/t_FileRevRead.sh 4 | # 5 | 6 | fon9path=`pwd`"$0" 7 | fon9path="${fon9path%/*}" 8 | fon9path="${fon9path%/*}" 9 | fon9path="${fon9path%/*}" 10 | develpath="${fon9path%/*}" 11 | BUILD_DIR=${BUILD_DIR:-${develpath}/output/fon9} 12 | BUILD_TYPE=${BUILD_TYPE:-release} 13 | 14 | ulimit -c unlimited 15 | 16 | set -x 17 | set -e 18 | 19 | OUTPUT_DIR=${OUTPUT_DIR:-${BUILD_DIR}/${BUILD_TYPE}/fon9} 20 | 21 | $OUTPUT_DIR/FileRevRead_UT $1 outf 22 | tac $1 > outx 23 | diff outf outx 24 | 25 | if [ $? -eq 0 ] 26 | then 27 | echo "[OK ] FileRevRead_UT." 28 | else 29 | echo "[ERROR] FileRevRead_UT." 30 | fi 31 | -------------------------------------------------------------------------------- /build/cmake/t_FixReceiver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # fon9/build/cmake/t_FixReceiver.sh 4 | # 5 | 6 | fon9path=`pwd`"$0" 7 | fon9path="${fon9path%/*}" 8 | fon9path="${fon9path%/*}" 9 | fon9path="${fon9path%/*}" 10 | develpath="${fon9path%/*}" 11 | BUILD_DIR=${BUILD_DIR:-${develpath}/output/fon9} 12 | BUILD_TYPE=${BUILD_TYPE:-release} 13 | 14 | ulimit -c unlimited 15 | 16 | set -x 17 | set -e 18 | 19 | OUTPUT_DIR=${OUTPUT_DIR:-${BUILD_DIR}/${BUILD_TYPE}/fon9} 20 | 21 | rm -f fix.log 22 | $OUTPUT_DIR/FixReceiver_UT ./fix.log ../../fon9/fix/FixReceiver_UT_Case.txt 23 | 24 | # 移除紀錄的 timestamp. 25 | sed -E 's/(^. )[0-9]*\.[0-9]* /\1/' -i fix.log 26 | 27 | # 移除送出訊息的 52=SendingTime, 及 10=CheckSum: 因為每次測試這2個欄位都不會相同. 28 | sed -E 's/(^S .*52=)[0-9]*-[0-9]*:[0-9]*:[0-9]*\.[0-9]*(.*)10=[0-9]*.$/\1\2/' -i fix.log 29 | 30 | diff fix.log ../../fon9/fix/FixReceiver_UT_Result.txt 31 | if [ $? -eq 0 ] 32 | then 33 | echo "[OK ] FixReceiver_UT." 34 | else 35 | echo "[ERROR] FixReceiver_UT." 36 | fi 37 | -------------------------------------------------------------------------------- /build/vs2015/Fon9Co/Fon9Co.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {39a94389-0e79-4814-aebc-c95df75e1e14} 14 | 15 | 16 | 17 | 18 | Source Files 19 | 20 | 21 | Source Files 22 | 23 | 24 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/AQueue_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/AuthMgr_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Base64_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Buffer_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/CharVector_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/ConfigLoader_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Crypto_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Endian_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FileRevRead_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/File_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FixFeeder_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FixParser_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FixReceiver_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FixRecorder_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FixSender_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FlowControl_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/FmktTools_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | 19 | 20 | Source Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/InnApf_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/InnDbf_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/InnFile_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/IoDev_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/IoFixSession_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/LogFile_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/MemBlock_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/ObjSupplier_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | 19 | 20 | Source Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/PackBcd_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/PkCont_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/RcSv_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Rc_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/RevPrint_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | Header Files 25 | 26 | 27 | 28 | 29 | Source Files 30 | 31 | 32 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/SchTask_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Seed_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Socket_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/StrTo_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | Header Files 19 | 20 | 21 | 22 | 23 | Source Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Symb_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/ThreadController_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/TimeStamp_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/TimedFileName_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Timer_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/ToStr_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Tree_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/_UnitTests/Trie_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /build/vs2015/f9twf/f9twfExgMkt_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/f9twf/f9twf_SymbId_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/f9tws/f9twsExgMkt_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/vs2015/f9tws/f9twsTrade_UT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | -------------------------------------------------------------------------------- /ext/logvs/makefile: -------------------------------------------------------------------------------- 1 | INC=-I../../../external/mini-async-log/include -I../../../external/spdlog/include -I../.. 2 | LIB=-L../../../external/mini-async-log -lmini_async_log -L../../../output/fon9/release/fon9 -lfon9_s 3 | 4 | all: 5 | g++ -D NDEBUG -g -O3 -std=c++11 -pthread logvs.cpp NanoLog.cpp $(INC) $(LIB) -o logvs 6 | -------------------------------------------------------------------------------- /ext/logvs/vs.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | rm -rf /tmp/*.txt 3 | rm -rf /tmp/*.log 4 | echo ====================================================================== 5 | # for i in {1..5}; do /usr/bin/time -v ./logvs none $*; done 6 | # echo ---------------------------------------------------------------------- 7 | # for i in {1..5}; do /usr/bin/time -v ./logvs spdlog $*; done 8 | # echo ---------------------------------------------------------------------- 9 | for i in {1..5}; do /usr/bin/time -v ./logvs mal $*; done 10 | echo ---------------------------------------------------------------------- 11 | for i in {1..5}; do /usr/bin/time -v ./logvs fon9a $*; done 12 | echo ---------------------------------------------------------------------- 13 | for i in {1..5}; do /usr/bin/time -v ./logvs fon9lf $*; done 14 | echo ---------------------------------------------------------------------- 15 | for i in {1..5}; do /usr/bin/time -v ./logvs fon9 $*; done 16 | echo ====================================================================== 17 | #ls -l /tmp 18 | #tail /tmp/*txt /tmp/*log 19 | wc -l /tmp/*txt /tmp/*log 20 | rm -rf /tmp/*.txt 21 | rm -rf /tmp/*.log 22 | -------------------------------------------------------------------------------- /ext/logvs/vsall.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | rm -rf /tmp/*.txt 3 | rm -rf /tmp/*.log 4 | echo ====================================================================== 5 | /usr/bin/time -v ./logvs fon9 $* 6 | echo ---------------------------------------------------------------------- 7 | #/usr/bin/time -v ./logvs nanolog $* 8 | echo ---------------------------------------------------------------------- 9 | /usr/bin/time -v ./logvs spdlog $* 10 | echo ---------------------------------------------------------------------- 11 | /usr/bin/time -v ./logvs fon9fmt $* 12 | echo ---------------------------------------------------------------------- 13 | /usr/bin/time -v ./logvs mal $* 14 | echo ---------------------------------------------------------------------- 15 | #/usr/bin/time -v ./logvs fon9s $* 16 | echo ====================================================================== 17 | ls -l /tmp 18 | tail /tmp/*txt /tmp/*log 19 | wc -l /tmp/*txt /tmp/*log 20 | rm -rf /tmp/*.txt 21 | rm -rf /tmp/*.log 22 | -------------------------------------------------------------------------------- /ext/sigslot/benchmark_f9s.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmark_f9s.hpp" 2 | 3 | const char* f9s::LibraryName = "* fon9 Subr"; 4 | const char* f9s::Remark = "fon9::SortedVector"; 5 | 6 | NOINLINE(void f9s::validate_assert(std::size_t N)) 7 | { 8 | return Benchmark::validation_assert(N); 9 | } 10 | NOINLINE(double f9s::construction(std::size_t N)) 11 | { 12 | return Benchmark::construction(N); 13 | } 14 | NOINLINE(double f9s::destruction(std::size_t N)) 15 | { 16 | return Benchmark::destruction(N); 17 | } 18 | NOINLINE(double f9s::connection(std::size_t N)) 19 | { 20 | return Benchmark::connection(N); 21 | } 22 | NOINLINE(double f9s::emission(std::size_t N)) 23 | { 24 | return Benchmark::emission(N); 25 | } 26 | NOINLINE(double f9s::combined(std::size_t N)) 27 | { 28 | return Benchmark::combined(N); 29 | } 30 | NOINLINE(double f9s::threaded(std::size_t N)) 31 | { 32 | return Benchmark::threaded(N); 33 | } 34 | -------------------------------------------------------------------------------- /ext/sigslot/benchmark_f9u.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmark_f9u.hpp" 2 | 3 | const char* f9u::LibraryName = "fon9 Subr(unsafe)"; 4 | const char* f9u::Remark = "fon9::SortedVector"; 5 | 6 | NOINLINE(void f9u::validate_assert(std::size_t N)) 7 | { 8 | return Benchmark::validation_assert(N); 9 | } 10 | NOINLINE(double f9u::construction(std::size_t N)) 11 | { 12 | return Benchmark::construction(N); 13 | } 14 | NOINLINE(double f9u::destruction(std::size_t N)) 15 | { 16 | return Benchmark::destruction(N); 17 | } 18 | NOINLINE(double f9u::connection(std::size_t N)) 19 | { 20 | return Benchmark::connection(N); 21 | } 22 | NOINLINE(double f9u::emission(std::size_t N)) 23 | { 24 | return Benchmark::emission(N); 25 | } 26 | NOINLINE(double f9u::combined(std::size_t N)) 27 | { 28 | return Benchmark::combined(N); 29 | } 30 | NOINLINE(double f9u::threaded(std::size_t N)) 31 | { 32 | return 0.0; 33 | } 34 | -------------------------------------------------------------------------------- /ext/yas/run.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | set -e 3 | set -x 4 | g++ -O3 -DNDEBUG -std=c++11 main.cpp -I ~/devel/external/yas/include -I ~/devel/fon9 -L ~/devel/output/fon9/release/fon9 -lfon9_s -lpthread 5 | ./a.out 6 | 7 | -------------------------------------------------------------------------------- /f9extests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(f9extests_src 2 | SymbIn.cpp 3 | SymbDyTest.cpp 4 | ExgMktTester.cpp 5 | ) 6 | add_library(f9extests_s STATIC ${f9extests_src}) 7 | target_link_libraries(f9extests_s pthread fon9_s) 8 | 9 | add_library(f9extests SHARED ${f9extests_src}) 10 | target_link_libraries(f9extests pthread fon9) 11 | -------------------------------------------------------------------------------- /f9extests/Config.h: -------------------------------------------------------------------------------- 1 | /// \file f9extests/Config.h 2 | /// 3 | /// libfon9 C API 的一些基本設定. 4 | /// 5 | /// \author fonwinz@gmail.com 6 | #ifndef __f9extests_Config_h__ 7 | #define __f9extests_Config_h__ 8 | #include "fon9/sys/Config.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #if defined(f9extests_NODLL) 15 | #define f9extests_API 16 | #elif defined(f9extests_EXPORT) 17 | #define f9extests_API __declspec(dllexport) 18 | #elif defined(fon9_WINDOWS) 19 | #define f9extests_API __declspec(dllimport) 20 | #else//not defined: fon9_WINDOWS 21 | #define f9extests_API 22 | #endif 23 | 24 | 25 | #ifdef __cplusplus 26 | }//extern "C" 27 | #endif 28 | #endif//__f9extests_Config_h__ 29 | -------------------------------------------------------------------------------- /f9extests/README.md: -------------------------------------------------------------------------------- 1 | fon9 extests 2 | ============ 3 | 4 | 其他測試項目. 5 | * SymbIn: 一個商品資料直接包含 SymbRef、SymbDeal、SymbBS, 不使用動態建立。 -------------------------------------------------------------------------------- /f9twf/Config.h: -------------------------------------------------------------------------------- 1 | // \file f9twf/Config.h 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_Config_h__ 4 | #define __f9twf_Config_h__ 5 | #include "fon9/sys/Config.h" 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #if defined(fon9_WINDOWS) 11 | /// C API 的呼叫方式, Windows: __stdcall 12 | #define f9twf_CAPI_CALL __stdcall 13 | #else//#if WIN #else... 14 | /// C API 的呼叫方式, Windows: __stdcall, unix: 空白(不須額外定義). 15 | #define f9twf_CAPI_CALL 16 | #endif//#if WIN #else #endif 17 | 18 | /// 設定 f9twf_API: MSVC 的 DLL import/export. 19 | #if defined(f9twf_NODLL) 20 | #define f9twf_API 21 | #elif defined(f9twf_EXPORT) 22 | #define f9twf_API __declspec(dllexport) 23 | #elif defined(f9twf_WINDOWS) 24 | #define f9twf_API __declspec(dllimport) 25 | #else//not defined: fon9_WINDOWS 26 | #define f9twf_API 27 | #endif 28 | 29 | #ifdef __cplusplus 30 | }//extern "C" 31 | #endif 32 | #endif//__f9twf_Config_h__ 33 | -------------------------------------------------------------------------------- /f9twf/ExgMapFcmId.cpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMapFcmId.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9twf/ExgMapFcmId.hpp" 4 | #include "fon9/StrTo.hpp" 5 | 6 | namespace f9twf { 7 | 8 | void ExgMapBrkFcmId::AddItem(ExgBrkFcmId id) { 9 | const_cast(&this->BrkToFcm_.kfetch(id.BrkId_))->FcmId_ = id.FcmId_; 10 | const_cast(&this->FcmToBrk_.kfetch(id.FcmId_))->BrkId_ = id.BrkId_; 11 | } 12 | void ExgMapBrkFcmId::AddItem(const TmpP06& p06) { 13 | ExgBrkFcmId id; 14 | id.BrkId_ = p06.BrkId_; 15 | id.FcmId_ = fon9::StrTo(ToStrView(p06.FcmId_), FcmId{}); 16 | this->AddItem(id); 17 | } 18 | void ExgMapBrkFcmId::LoadP06(fon9::StrView fctx) { 19 | const TmpP06* p06 = reinterpret_cast(fctx.begin()); 20 | while (reinterpret_cast(&p06[1]) > fctx.end()) 21 | this->AddItem(*p06++); 22 | } 23 | 24 | } // namespaces 25 | -------------------------------------------------------------------------------- /f9twf/ExgMapSessionDn.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMapSessionDn.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMapSessionDn_hpp__ 4 | #define __f9twf_ExgMapSessionDn_hpp__ 5 | #include "f9twf/ExgMapFcmId.hpp" 6 | #include "f9twf/ExgLineTmpArgs.hpp" 7 | 8 | namespace f9twf { 9 | 10 | /// 期交所 P07、PA7: SessionId => dn:port 對照表. 11 | class f9twf_API ExgMapSessionDn { 12 | using ExgSessionKey = uint32_t; 13 | static_assert(sizeof(ExgSessionKey) >= sizeof(FcmId) + sizeof(SessionId), 14 | "ExgSessionKey too small."); 15 | using SesToDn = fon9::SortedVector; 16 | SesToDn SesToDn_; 17 | 18 | public: 19 | void reserve(size_t sz) { 20 | this->SesToDn_.reserve(sz); 21 | } 22 | void shrink_to_fit() { 23 | this->SesToDn_.shrink_to_fit(); 24 | } 25 | void swap(ExgMapSessionDn& rhs) { 26 | this->SesToDn_.swap(rhs.SesToDn_); 27 | } 28 | 29 | /// 載入期交所P07、PA7. 30 | void LoadP07(const ExgMapBrkFcmId& mapFcmId, fon9::StrView fctx); 31 | 32 | /// 設定一筆(一行) dn, 使用 P07 格式. 33 | bool FeedLine(const ExgMapBrkFcmId& mapFcmId, fon9::StrView ctxln); 34 | 35 | /// 在 devcfg 尾端加上 "|dn=..."; 36 | bool AppendDn(const ExgLineTmpArgs& lineArgs, std::string& devcfg) const; 37 | }; 38 | 39 | } // namespaces 40 | #endif//__f9twf_ExgMapSessionDn_hpp__ 41 | -------------------------------------------------------------------------------- /f9twf/ExgMcChannelTunnel.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMcChannelTunnel.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMcChannelTunnel_hpp__ 4 | #define __f9twf_ExgMcChannelTunnel_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | #include "fon9/framework/IoFactory.hpp" 7 | 8 | namespace f9twf { 9 | 10 | /// 台灣期交所逐筆行情「Channel訊息轉發程序」工廠. 11 | class f9twf_API ExgMcChannelTunnelFactory : public fon9::SessionFactory { 12 | fon9_NON_COPY_NON_MOVE(ExgMcChannelTunnelFactory); 13 | using base = fon9::SessionFactory; 14 | public: 15 | using base::base; 16 | fon9::io::SessionSP CreateSession(fon9::IoManager& ioMgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 17 | fon9::io::SessionServerSP CreateSessionServer(fon9::IoManager& ioMgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 18 | }; 19 | 20 | } // namespaces 21 | #endif//__f9twf_ExgMcChannelTunnel_hpp__ 22 | -------------------------------------------------------------------------------- /f9twf/ExgMcFmtSSToRts.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMcFmtSSToRts.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMcFmtSSToRts_hpp__ 4 | #define __f9twf_ExgMcFmtSSToRts_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | 7 | namespace f9twf { 8 | 9 | /// 解析 static_cast(&e.Pk_); 10 | /// - 透過 symb.MdRtStream_ 發行 & 儲存. 11 | /// - 轉發 I083 給 RealtimeChannel; 12 | /// - 若沒有儲存, 則盤中重啟後, Rti 儲存的「BS明細」, 13 | /// 可能無法正確處理接續的 UpdateBS; 14 | f9twf_API void I084SSParserToRts(ExgMcMessage& e); 15 | f9twf_API void I084SSParserToRtsV3(ExgMcMessage& e); 16 | 17 | } // namespaces 18 | #endif//__f9twf_ExgMcFmtSSToRts_hpp__ 19 | -------------------------------------------------------------------------------- /f9twf/ExgMcReceiverFactory.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMcReceiverFactory.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMcReceiverFactory_hpp__ 4 | #define __f9twf_ExgMcReceiverFactory_hpp__ 5 | #include "f9twf/Config.h" 6 | #include "fon9/framework/IoFactory.hpp" 7 | 8 | namespace f9twf { 9 | 10 | class f9twf_API ExgMcReceiverFactory : public fon9::SessionFactory { 11 | fon9_NON_COPY_NON_MOVE(ExgMcReceiverFactory); 12 | using base = fon9::SessionFactory; 13 | public: 14 | using base::base; 15 | 16 | fon9::io::SessionSP CreateSession(fon9::IoManager& ioMgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 17 | fon9::io::SessionServerSP CreateSessionServer(fon9::IoManager& ioMgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 18 | }; 19 | 20 | } // namespaces 21 | #endif//__f9twf_ExgMcReceiverFactory_hpp__ 22 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtBSToRts.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtBSToRts.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdFmtBSToRts_hpp__ 4 | #define __f9twf_ExgMdFmtBSToRts_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | 7 | namespace f9twf { 8 | 9 | /// 解析 static_cast(&e.Pk_); 10 | /// 並透過 symb.MdRtStream_ 發行. 11 | f9twf_API void I081BSParserToRts(ExgMcMessage& e); 12 | 13 | /// 解析 static_cast(&e.Pk_); 14 | /// 並透過 symb.MdRtStream_ 發行. 15 | f9twf_API void I083BSParserToRts(ExgMcMessage& e); 16 | 17 | } // namespaces 18 | #endif//__f9twf_ExgMdFmtBSToRts_hpp__ 19 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtBasicInfoToRts.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtBasicInfoToRts.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdFmtBasicInfoToRts_hpp__ 4 | #define __f9twf_ExgMdFmtBasicInfoToRts_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | 7 | namespace f9twf { 8 | 9 | /// 解析 static_cast(&e.Pk_); 10 | /// 並透過 symb.MdRtStream_ 發行. 11 | f9twf_API void I010BasicInfoParserToRts_V7(ExgMcMessage& e); 12 | f9twf_API void I010BasicInfoParserToRts_V8(ExgMcMessage& e); 13 | 14 | f9twf_API void I012BasePriLmts(ExgMcMessage& e); 15 | 16 | } // namespaces 17 | #endif//__f9twf_ExgMdFmtBasicInfoToRts_hpp__ 18 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtClosingToRts.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtClosingToRts.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdFmtClosingToRts_hpp__ 4 | #define __f9twf_ExgMdFmtClosingToRts_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | 7 | namespace f9twf { 8 | 9 | /// 解析 static_cast(&e.Pk_); 結算價. 10 | /// 並透過 symb.MdRtStream_ 發行. 11 | f9twf_API void I071ClosingParserToRts(ExgMcMessage& e); 12 | 13 | /// 解析 static_cast(&e.Pk_); 結算價. 14 | /// 並透過 symb.MdRtStream_ 發行. 15 | f9twf_API void I072ClosingParserToRts(ExgMcMessage& e); 16 | 17 | } // namespaces 18 | #endif//__f9twf_ExgMdFmtClosingToRts_hpp__ 19 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtHL.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtHL.hpp 2 | // 3 | // 台灣期交所行情格式: 盤中最(高)低價揭示. 4 | // 逐筆行情: I025; 5 | // 間隔行情: I021; 6 | // 7 | // \author fonwinz@gmail.com 8 | #ifndef __f9twf_ExgMdFmtHL_hpp__ 9 | #define __f9twf_ExgMdFmtHL_hpp__ 10 | #include "f9twf/ExgMdFmt.hpp" 11 | 12 | namespace f9twf { 13 | fon9_PACK(1); 14 | 15 | struct ExgMdDayHighLow { 16 | ExgMdSPrice DayHighPrice_; 17 | ExgMdSPrice DayLowPrice_; 18 | ExgMdHHMMSSu6 ShowTime_; 19 | }; 20 | //--------------------------------------------------------------------------// 21 | /// 逐筆行情 盤中最(高)低價揭示: Fut:(Tx='2'; Mg='E'); Opt:(Tx='5'; Mg='E'); Ver=1; 22 | struct ExgMcI025Head : public ExgMcHead { 23 | ExgMdProdId20 ProdId_; 24 | ExgMcProdMsgSeq ProdMsgSeq_; 25 | }; 26 | struct ExgMcI025 : public ExgMcI025Head 27 | , public ExgMdDayHighLow 28 | , public ExgMdTail { 29 | }; 30 | //--------------------------------------------------------------------------// 31 | /// 間隔行情 盤中最(高)低價揭示: Fut:(Tx='2'; Mg='5'); Opt:(Tx='5'; Mg='5'); Ver=3; 32 | struct ExgMiI021Head : public ExgMiHead { 33 | ExgMdProdId20 ProdId_; 34 | }; 35 | struct ExgMiI021 : public ExgMiI021Head 36 | , public ExgMdDayHighLow 37 | , public ExgMdTail { 38 | }; 39 | 40 | fon9_PACK_POP; 41 | } // namespaces 42 | #endif//__f9twf_ExgMdFmtHL_hpp__ 43 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtMatchToRts.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtMatchToRts.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdFmtMatchToRts_hpp__ 4 | #define __f9twf_ExgMdFmtMatchToRts_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | 7 | namespace f9twf { 8 | 9 | /// 解析 static_cast(&e.Pk_); 10 | /// 並透過 symb.MdRtStream_ 發行. 11 | f9twf_API void I024MatchParserToRts(ExgMcMessage& e); 12 | 13 | } // namespaces 14 | #endif//__f9twf_ExgMdFmtMatchToRts_hpp__ 15 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtQuoteReq.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtQuoteReq.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdFmtQuoteReq_hpp__ 4 | #define __f9twf_ExgMdFmtQuoteReq_hpp__ 5 | #include "f9twf/ExgMdFmt.hpp" 6 | 7 | namespace f9twf { 8 | fon9_PACK(1); 9 | 10 | struct ExgMdQuoteReq { 11 | ExgMdProdId10 ProdId_; 12 | ExgMdHHMMSSu6 DisclosureTime_; 13 | fon9::PackBcd<3> DurationSeconds_; 14 | }; 15 | //--------------------------------------------------------------------------// 16 | /// 逐筆行情 詢價要求揭示: Fut:(Tx='2'; Mg='4'); Opt:(Tx='5'; Mg='4'); Ver=2; 17 | struct ExgMcI100 : public ExgMcHead 18 | , public ExgMdQuoteReq 19 | , public ExgMdTail { 20 | }; 21 | //--------------------------------------------------------------------------// 22 | /// 間隔行情 詢價要求揭示: Fut:(Tx='2'; Mg='4'); Opt:(Tx='5'; Mg='4'); Ver=2; 23 | struct ExgMiI100 : public ExgMiHead 24 | , public ExgMdQuoteReq 25 | , public ExgMdTail { 26 | }; 27 | 28 | fon9_PACK_POP; 29 | } // namespaces 30 | #endif//__f9twf_ExgMdFmtQuoteReq_hpp__ 31 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtQuoteReqToRts.cpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtQuoteReqToRts.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9twf/ExgMdFmtQuoteReqToRts.hpp" 4 | #include "f9twf/ExgMdFmtQuoteReq.hpp" 5 | #include "f9twf/ExgMdFmtParsers.hpp" 6 | #include "fon9/fmkt/SymbTabNames.h" 7 | 8 | namespace f9twf { 9 | namespace f9fmkt = fon9::fmkt; 10 | 11 | f9twf_API void I100QuoteReqParserToRts(ExgMcMessage& e) { 12 | const auto& pk = *static_cast(&e.Pk_); 13 | f9fmkt::SymbQuoteReq_Data quoteReq; 14 | quoteReq.DisclosureTime_ = pk.DisclosureTime_.ToDayTime(); 15 | quoteReq.DurationSeconds_ = fon9::PackBcdTo(pk.DurationSeconds_); 16 | 17 | ExgMdLocker lk{e, pk.ProdId_}; 18 | auto& symb = *e.Symb_; 19 | if (symb.QuoteReq_.Data_ == quoteReq) 20 | return; 21 | symb.QuoteReq_.Data_ = quoteReq; 22 | fon9::RevBufferList rbuf{128}; 23 | auto* tabQuoteReq = lk.Symbs_.LayoutSP_->GetTab(fon9_kCSTR_TabName_QuoteReq); 24 | f9fmkt::MdRtsPackTabValues(rbuf, *tabQuoteReq, symb.QuoteReq_); 25 | symb.MdRtStream_.Publish(ToStrView(symb.SymbId_), 26 | f9sv_RtsPackType_TabValues_AndInfoTime, 27 | f9sv_MdRtsKind_QuoteReq, 28 | e.Pk_.InformationTime_.ToDayTime(), 29 | std::move(rbuf)); 30 | } 31 | 32 | } // namespaces 33 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtQuoteReqToRts.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtQuoteReqToRts.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdFmtQuoteReqToRts_hpp__ 4 | #define __f9twf_ExgMdFmtQuoteReqToRts_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | 7 | namespace f9twf { 8 | 9 | /// 解析 static_cast(&e.Pk_); 詢價訊息. 10 | /// 並透過 symb.MdRtStream_ 發行. 11 | f9twf_API void I100QuoteReqParserToRts(ExgMcMessage& e); 12 | 13 | } // namespaces 14 | #endif//__f9twf_ExgMdFmtQuoteReqToRts_hpp__ 15 | -------------------------------------------------------------------------------- /f9twf/ExgMdFmtSysInfoToRts.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdFmtSysInfoToRts.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdFmtSysInfoToRts_hpp__ 4 | #define __f9twf_ExgMdFmtSysInfoToRts_hpp__ 5 | #include "f9twf/ExgMcChannel.hpp" 6 | 7 | namespace f9twf { 8 | 9 | /// 解析 static_cast(&e.Pk_); 10 | /// 並透過 symb.MdRtStream_ 發行. 11 | f9twf_API void I140SysInfoParserToRts(ExgMcMessage& e); 12 | 13 | } // namespaces 14 | #endif//__f9twf_ExgMdFmtSysInfoToRts_hpp__ 15 | -------------------------------------------------------------------------------- /f9twf/ExgMdPkReceiver.cpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdPkReceiver.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9twf/ExgMdPkReceiver.hpp" 4 | 5 | namespace f9twf { 6 | 7 | ExgMiPkReceiver::~ExgMiPkReceiver() { 8 | } 9 | unsigned ExgMiPkReceiver::GetPkSize(const void* pkptr) { 10 | return GetPkSize_ExgMi(*reinterpret_cast(pkptr)); 11 | } 12 | 13 | ExgMcPkReceiver::~ExgMcPkReceiver() { 14 | } 15 | unsigned ExgMcPkReceiver::GetPkSize(const void* pkptr) { 16 | return GetPkSize_ExgMc(*reinterpret_cast(pkptr)); 17 | } 18 | 19 | } // namespaces 20 | -------------------------------------------------------------------------------- /f9twf/ExgMdPkReceiver.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgMdPkReceiver.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_ExgMdPkReceiver_hpp__ 4 | #define __f9twf_ExgMdPkReceiver_hpp__ 5 | #include "f9twf/ExgMdFmt.hpp" 6 | #include "fon9/PkReceiver.hpp" 7 | 8 | namespace f9twf { 9 | 10 | /// 解析台灣期交所「間隔行情」格式框架. 11 | class f9twf_API ExgMiPkReceiver : public fon9::PkReceiver { 12 | fon9_NON_COPY_NON_MOVE(ExgMiPkReceiver); 13 | using base = fon9::PkReceiver; 14 | public: 15 | ExgMiPkReceiver(bool isDgram = false) 16 | : base{sizeof(ExgMiHead), isDgram} { 17 | } 18 | virtual ~ExgMiPkReceiver(); 19 | 20 | unsigned GetPkSize(const void* pkptr) override; 21 | }; 22 | 23 | /// 解析台灣期交所「逐筆行情」格式框架. 24 | class f9twf_API ExgMcPkReceiver : public fon9::PkReceiver { 25 | fon9_NON_COPY_NON_MOVE(ExgMcPkReceiver); 26 | using base = fon9::PkReceiver; 27 | public: 28 | ExgMcPkReceiver (bool isDgram = false) 29 | : base{sizeof(ExgMcHead), isDgram} { 30 | } 31 | virtual ~ExgMcPkReceiver(); 32 | 33 | unsigned GetPkSize(const void* pkptr) override; 34 | }; 35 | 36 | } // namespaces 37 | #endif//__f9twf_ExgMdPkReceiver_hpp__ 38 | -------------------------------------------------------------------------------- /f9twf/ExgTmpTradingR9.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgTmpTradingR9.hpp 2 | // 3 | // TMP封包: 報價要求R09/R39; 報價回報使用: (R02/R32) * 2(Bid/Offer). 4 | // 5 | // \author fonwinz@gmail.com 6 | #ifndef __f9twf_ExgTmpTradingR9_hpp__ 7 | #define __f9twf_ExgTmpTradingR9_hpp__ 8 | #include "f9twf/ExgTmpTradingR1.hpp" 9 | 10 | namespace f9twf { 11 | 12 | struct TmpR9Front : public TmpHeader, public TmpR1BfSym { 13 | struct BackType { 14 | TmpPrice BidPx_; 15 | TmpPrice OfferPx_; 16 | TmpQty BidSize_; 17 | TmpQty OfferSize_; 18 | TmpIvacNo IvacNo_; 19 | TmpIvacFlag IvacFlag_; 20 | TmpTimeInForce TimeInForce_; 21 | TmpPosEff PosEff_; 22 | TmpSource Source_; 23 | TmpCheckSum CheckSum_; 24 | }; 25 | }; 26 | using TmpR9Back = TmpR9Front::BackType; 27 | using TmpR09 = TmpTriDef; 28 | using TmpR39 = TmpTriDef; 29 | 30 | static_assert(sizeof(TmpR09) == 84, "struct TmpR09; must pack?"); 31 | static_assert(sizeof(TmpR39) == 104, "struct TmpR39; must pack?"); 32 | 33 | } // namespaces 34 | #endif//__f9twf_ExgTmpTradingR9_hpp__ 35 | -------------------------------------------------------------------------------- /f9twf/ExgTradingLineMgr.cpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/ExgTradingLineMgr.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9twf/ExgTradingLineMgr.hpp" 4 | 5 | namespace f9twf { 6 | 7 | void ExgTradingLineMgr::OnParentSeedClear() { 8 | this->OnBeforeDestroy(); 9 | baseIo::OnParentSeedClear(); 10 | } 11 | void ExgTradingLineMgr::OnTDayChanged(fon9::TimeStamp tday, std::string cause) { 12 | (void)tday; 13 | this->DisposeAndReopen(std::move(cause)); 14 | } 15 | 16 | } // namespaces 17 | -------------------------------------------------------------------------------- /f9twf/TwfTickSize.hpp: -------------------------------------------------------------------------------- 1 | // \file f9twf/TwfTickSize.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9twf_TwfTickSize_hpp__ 4 | #define __f9twf_TwfTickSize_hpp__ 5 | #include "fon9/fmkt/FmktTools.hpp" 6 | #include "f9twf/ExgTypes.hpp" 7 | #include "f9twf/Config.h" 8 | 9 | namespace f9twf { 10 | 11 | /// 使用 ConfigLoader 載入 TickSize 設定. 12 | f9twf_API void Load_TwfTickSize(fon9::StrView defaultConfigPath = "", fon9::StrView cfgFileName = fon9::StrView("TwfTickSize.cfg")); 13 | 14 | f9twf_API const fon9::fmkt::LvPriStep* GetLvPriStep(ContractId contractId, f9fmkt_TradingMarket mkt, ExgContractType contractType); 15 | 16 | } // namespaces 17 | #endif//__f9twf_TwfTickSize_hpp__ 18 | -------------------------------------------------------------------------------- /f9tws/Config.h: -------------------------------------------------------------------------------- 1 | // \file f9tws/Config.h 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_Config_h__ 4 | #define __f9tws_Config_h__ 5 | #include "fon9/sys/Config.h" 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #if defined(fon9_WINDOWS) 11 | /// C API 的呼叫方式, Windows: __stdcall 12 | #define f9tws_CAPI_CALL __stdcall 13 | #else//#if WIN #else... 14 | /// C API 的呼叫方式, Windows: __stdcall, unix: 空白(不須額外定義). 15 | #define f9tws_CAPI_CALL 16 | #endif//#if WIN #else #endif 17 | 18 | /// 設定 f9tws_API: MSVC 的 DLL import/export. 19 | #if defined(f9tws_NODLL) 20 | #define f9tws_API 21 | #elif defined(f9tws_EXPORT) 22 | #define f9tws_API __declspec(dllexport) 23 | #elif defined(f9tws_WINDOWS) 24 | #define f9tws_API __declspec(dllimport) 25 | #else//not defined: fon9_WINDOWS 26 | #define f9tws_API 27 | #endif 28 | 29 | #ifdef __cplusplus 30 | }//extern "C" 31 | #endif 32 | #endif//__f9tws_Config_h__ 33 | -------------------------------------------------------------------------------- /f9tws/ExgLineArgs.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgLineArgs.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgLineArgs_hpp__ 4 | #define __f9tws_ExgLineArgs_hpp__ 5 | #include "f9tws/ExgTypes.hpp" 6 | #include "fon9/fmkt/FmktTypes.hpp" 7 | #include "fon9/CharAry.hpp" 8 | #include "fon9/ConfigParser.hpp" 9 | 10 | namespace f9tws { 11 | 12 | struct f9tws_API ExgLineArgs { 13 | f9fmkt_TradingMarket Market_; 14 | BrkId BrkId_; 15 | fon9::CharAryF<2> SocketId_; 16 | fon9::CharAry<15> PassKey_; 17 | uint16_t PassNum_; 18 | /// Hb 的間隔(單位:秒), 預設為 0, 由各 session 根據交易所規範, 自行決定預設值. 19 | uint16_t HbInterval_; 20 | 21 | void Clear(); 22 | 23 | /// 不改變 args.Market_ 您必須自行處理. 24 | /// - tag = "BrkId=|SocketId=|Pass=|HbInt="; 25 | /// - tag = "SocketId" 與 "PvcId" 相同, 都會填入 SocketId_; 26 | /// - tag = "PassKey" 則必須自定 FnGetPassNum; 27 | fon9::ConfigParser::Result OnTagValue(fon9::StrView tag, fon9::StrView& value); 28 | 29 | /// 檢查欄位是否正確. 30 | std::string Verify() const; 31 | 32 | uint16_t GetPassNum() const; 33 | }; 34 | 35 | } // namespaces 36 | #endif//__f9tws_ExgLineArgs_hpp__ 37 | -------------------------------------------------------------------------------- /f9tws/ExgLineFactory.cpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgLineFactory.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9tws/ExgLineFactory.hpp" 4 | 5 | namespace f9tws { 6 | 7 | ExgLineFactory::ExgLineFactory(std::string logPathFmt, Named&& name) 8 | : baseFactory{std::move(name)} 9 | , basePathMaker{std::move(logPathFmt)} { 10 | } 11 | fon9::io::SessionServerSP ExgLineFactory::CreateSessionServer(fon9::IoManager& mgr, const fon9::IoConfigItem& cfg, std::string& errReason) { 12 | (void)mgr; (void)cfg; 13 | errReason = "f9tws::ExgLineFactory|err=Not support Server."; 14 | return fon9::io::SessionServerSP{}; 15 | } 16 | fon9::io::SessionSP ExgLineFactory::CreateSession(fon9::IoManager& mgr, const fon9::IoConfigItem& cfg, std::string& errReason) { 17 | if (ExgTradingLineMgr* twsLineMgr = dynamic_cast(&mgr)) 18 | return this->CreateTradingLine(*twsLineMgr, cfg, errReason); 19 | errReason = "IoManager must be f9tws::ExgTradingLineMgr"; 20 | return fon9::io::SessionSP{}; 21 | } 22 | 23 | } // namespaces 24 | -------------------------------------------------------------------------------- /f9tws/ExgLineFactory.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgLineFactory.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgLineFactory_hpp__ 4 | #define __f9tws_ExgLineFactory_hpp__ 5 | #include "f9tws/ExgTradingLineMgr.hpp" 6 | #include "fon9/framework/IoFactory.hpp" 7 | 8 | namespace f9tws { 9 | 10 | class f9tws_API ExgLineFactory : public fon9::SessionFactory, public f9fmkt::TradingLineLogPathMaker { 11 | fon9_NON_COPY_NON_MOVE(ExgLineFactory); 12 | using baseFactory = fon9::SessionFactory; 13 | using basePathMaker = f9fmkt::TradingLineLogPathMaker; 14 | 15 | protected: 16 | virtual fon9::io::SessionSP CreateTradingLine(ExgTradingLineMgr& lineMgr, 17 | const fon9::IoConfigItem& cfg, 18 | std::string& errReason) = 0; 19 | 20 | public: 21 | ExgLineFactory(std::string logPathFmt, Named&& name); 22 | 23 | /// mgr 必須是 f9tws::ExgTradingLineMgr 24 | fon9::io::SessionSP CreateSession(fon9::IoManager& mgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 25 | /// 券商端, 不支援 SessionServer. 26 | fon9::io::SessionServerSP CreateSessionServer(fon9::IoManager& mgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 27 | }; 28 | 29 | } // namespaces 30 | #endif//__f9tws_ExgLineFactory_hpp__ 31 | -------------------------------------------------------------------------------- /f9tws/ExgLineTmpFactory.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgLineTmpFactory.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgLineTmpFactory_hpp__ 4 | #define __f9tws_ExgLineTmpFactory_hpp__ 5 | #include "f9tws/ExgLineFactory.hpp" 6 | 7 | namespace f9tws { 8 | 9 | class f9tws_API ExgLineTmpArgs; 10 | 11 | class f9tws_API ExgLineTmpFactory : public ExgLineFactory { 12 | fon9_NON_COPY_NON_MOVE(ExgLineTmpFactory); 13 | using base = ExgLineFactory; 14 | protected: 15 | fon9::io::SessionSP CreateTradingLine(ExgTradingLineMgr& lineMgr, 16 | const fon9::IoConfigItem& cfg, 17 | std::string& errReason) override; 18 | 19 | /// 由衍生者根據 args.ApCode_ 決定要建立哪種 Session. 20 | virtual fon9::io::SessionSP CreateLineTmp(ExgTradingLineMgr& lineMgr, 21 | const ExgLineTmpArgs& args, 22 | std::string& errReason, 23 | std::string logFileName) = 0; 24 | public: 25 | ExgLineTmpFactory(std::string logPathFmt, Named&& name); 26 | }; 27 | 28 | } // namespaces 29 | #endif//__f9tws_ExgLineTmpFactory_hpp__ 30 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt13.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt13.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmt13_hpp__ 4 | #define __f9tws_ExgMdFmt13_hpp__ 5 | #include "f9tws/ExgMdFmt.hpp" 6 | 7 | namespace f9tws { 8 | fon9_PACK(1); 9 | 10 | struct ExgMdFmt13v3 : public ExgMdHead { 11 | StkNo StkNo_; 12 | /// a.數值 < 143000 表示為試算揭示. 13 | /// b.數值 = 143000 表示為正式撮合成交揭示. 14 | /// c.數值 = 999999,StkNo_ = "000000" 表示當日零股交易撮合成交資料已全部送出。 15 | ExgMdHHMMSS Time_; 16 | bool IsLastDealSent() const { 17 | return this->Time_.HH_[0] == 0x99; 18 | } 19 | 20 | /// Bit 7-6 成交 00:一般成交或無成交 01:跌停成交 10:漲停成交. 21 | /// Bit 5-4 買進 00:一般買進或無買進價量 01:跌停買進 10:漲停買進. 22 | /// Bit 3-2 賣出 00:一般賣出或無賣出價量 01:跌停賣出 10:漲停賣出. 23 | /// Bit 1-0 保留位元. 24 | fon9::byte LmtMask_; 25 | 26 | fon9::PackBcd<9> TradingPriceV4_; 27 | /// 成交股數,單位為「股」. 28 | fon9::PackBcd<12> TradingVolume_; 29 | /// 揭示試算及正式撮合後未成交的最佳一檔買進價格,沒有未成交買進價格時傳送 0。 30 | fon9::PackBcd<9> BuyPriceV4_; 31 | /// 揭示試算及正式撮合後未成交的最佳一檔賣出價格,沒有未成交賣出價格時傳送 0。 32 | fon9::PackBcd<9> SellPriceV4_; 33 | }; 34 | fon9_PACK_POP; 35 | 36 | } // namespaces 37 | #endif//__f9tws_ExgMdFmt13_hpp__ 38 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt13Handler.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt13Handler.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmt13Handler_hpp__ 4 | #define __f9tws_ExgMdFmt13Handler_hpp__ 5 | #include "f9tws/ExgMdSystem.hpp" 6 | 7 | namespace f9tws { 8 | 9 | class f9tws_API ExgMdFmt13Handler : public ExgMdHandlerPkCont { 10 | fon9_NON_COPY_NON_MOVE(ExgMdFmt13Handler); 11 | void PkContOnReceived(const void* pk, unsigned pksz, SeqT seq) override; 12 | public: 13 | using ExgMdHandlerPkCont::ExgMdHandlerPkCont; 14 | virtual ~ExgMdFmt13Handler(); 15 | }; 16 | 17 | } // namespaces 18 | #endif//__f9tws_ExgMdFmt13Handler_hpp__ 19 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt19.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt19.hpp 2 | // 3 | // 格式19: 當日暫停/恢復交易股票資料. 4 | // 5 | // \author fonwinz@gmail.com 6 | #ifndef __f9tws_ExgMdFmt19_hpp__ 7 | #define __f9tws_ExgMdFmt19_hpp__ 8 | #include "f9tws/ExgMdFmt.hpp" 9 | 10 | namespace f9tws { 11 | fon9_PACK(1); 12 | 13 | struct ExgMdFmt19 : public ExgMdHead { 14 | StkNo StkNo_; 15 | /// 當日暫停交易時間. 16 | fon9::PackBcd<6> SuspendHHMMSS_; 17 | /// 當日恢復交易時間 . 18 | fon9::PackBcd<6> ResumeHHMMSS_; 19 | }; 20 | 21 | fon9_PACK_POP; 22 | } // namespaces 23 | #endif//__f9tws_ExgMdFmt19_hpp__ 24 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt19Handler.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt19Handler.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmt19Handler_hpp__ 4 | #define __f9tws_ExgMdFmt19Handler_hpp__ 5 | #include "f9tws/ExgMdSystem.hpp" 6 | 7 | namespace f9tws { 8 | 9 | class f9tws_API ExgMdFmt19Handler : public ExgMdHandlerAnySeq { 10 | fon9_NON_COPY_NON_MOVE(ExgMdFmt19Handler); 11 | void OnPkReceived(const ExgMdHead& pk, unsigned pksz) override; 12 | public: 13 | using ExgMdHandlerAnySeq::ExgMdHandlerAnySeq; 14 | virtual ~ExgMdFmt19Handler(); 15 | }; 16 | 17 | } // namespaces 18 | #endif//__f9tws_ExgMdFmt19Handler_hpp__ 19 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt22Handler.cpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt22Handler.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9tws/ExgMdFmt22Handler.hpp" 4 | #include "f9tws/ExgMdFmt1Handler.hpp" 5 | #include "f9tws/ExgMdFmt22.hpp" 6 | 7 | namespace f9tws { 8 | 9 | ExgMdFmt22Handler::~ExgMdFmt22Handler() { 10 | } 11 | void ExgMdFmt22Handler::OnPkReceived(const ExgMdHead& pkhdr, unsigned pksz) { 12 | const ExgMdFmt22v1& fmt22 = *static_cast(&pkhdr); 13 | EdgMdParseBaseInfo(fon9::PackBcdTo(pkhdr.Market_) == ExgMdMarket_TwTSE 14 | ? f9fmkt_TradingMarket_TwSEC : f9fmkt_TradingMarket_TwOTC, 15 | *this, *TwsMdSys(*this).SymbsOdd_, 16 | fmt22, pksz); 17 | } 18 | 19 | } // namespaces 20 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt22Handler.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt22Handler.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmt22Handler_hpp__ 4 | #define __f9tws_ExgMdFmt22Handler_hpp__ 5 | #include "f9tws/ExgMdSystem.hpp" 6 | 7 | namespace f9tws { 8 | 9 | class f9tws_API ExgMdFmt22Handler : public ExgMdHandlerAnySeq { 10 | fon9_NON_COPY_NON_MOVE(ExgMdFmt22Handler); 11 | void OnPkReceived(const ExgMdHead& pk, unsigned pksz) override; 12 | public: 13 | using ExgMdHandlerAnySeq::ExgMdHandlerAnySeq; 14 | virtual ~ExgMdFmt22Handler(); 15 | }; 16 | 17 | } // namespaces 18 | #endif//__f9tws_ExgMdFmt22Handler_hpp__ 19 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt23.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt23.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmt23_hpp__ 4 | #define __f9tws_ExgMdFmt23_hpp__ 5 | #include "f9tws/ExgMdFmt6.hpp" 6 | 7 | namespace f9tws { 8 | fon9_PACK(1); 9 | 10 | using ExgMdOddQty = fon9::PackBcd<12>; 11 | struct ExgMdOddPriQty { 12 | fon9::PackBcd<9> PriV4_; 13 | ExgMdOddQty Qty_; 14 | 15 | void AssignTo(fon9::fmkt::PriQty& dst) const { 16 | dst.Pri_.Assign<4>(fon9::PackBcdTo(this->PriV4_)); 17 | dst.Qty_ = fon9::PackBcdTo(this->Qty_); 18 | } 19 | }; 20 | 21 | struct ExgMdFmt23v1 : public ExgMdFmtRtBase { 22 | ExgMdOddQty TotalQty_; 23 | ExgMdOddPriQty PQs_[1]; 24 | 25 | bool HasBS() const { 26 | // 盤中零股採用集合競價,每次的 Fmt23 揭示都包含「買賣報價」, 27 | // 如果市場上確實沒有買賣,則 (this->ItemMask_ & 0x7e) 為 0; 28 | // 所以 Fmt23 的 HasBS() 總是為 true; 表示有提供買賣報價(有可能檔數為 0); 29 | // return (this->ItemMask_ & 0x7e) != 0; 30 | return true; 31 | 32 | // 格式6,採用逐筆撮合,有額外的旗標,用來標示該次 Fmt6 是否包含買賣報價。 33 | // return (this->ItemMask_ & 0x7e) || (this->ItemMask_ & 1) == 0; 34 | } 35 | }; 36 | fon9_PACK_POP; 37 | 38 | } // namespaces 39 | #endif//__f9tws_ExgMdFmt23_hpp__ 40 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt23Handler.cpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt23Handler.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9tws/ExgMdFmt23Handler.hpp" 4 | #include "f9tws/ExgMdFmt6Handler.hpp" 5 | #include "f9tws/ExgMdFmt23.hpp" 6 | 7 | namespace f9tws { 8 | 9 | ExgMdFmt23Handler::~ExgMdFmt23Handler() { 10 | } 11 | //--------------------------------------------------------------------------// 12 | void ExgMdFmt23Handler::PkContOnReceived(const void* pkptr, unsigned pksz, SeqT seq) { 13 | FmtRt_PkContOnReceived( 14 | *this, *TwsMdSys(*this).SymbsOdd_, 15 | *static_cast(pkptr), pksz, seq); 16 | } 17 | 18 | } // namespaces 19 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt23Handler.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt23Handler.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmt23Handler_hpp__ 4 | #define __f9tws_ExgMdFmt23Handler_hpp__ 5 | #include "f9tws/ExgMdSystem.hpp" 6 | 7 | namespace f9tws { 8 | 9 | class f9tws_API ExgMdFmt23Handler : public ExgMdHandlerPkCont { 10 | fon9_NON_COPY_NON_MOVE(ExgMdFmt23Handler); 11 | void PkContOnReceived(const void* pk, unsigned pksz, SeqT seq) override; 12 | public: 13 | using ExgMdHandlerPkCont::ExgMdHandlerPkCont; 14 | virtual ~ExgMdFmt23Handler(); 15 | }; 16 | 17 | } // namespaces 18 | #endif//__f9tws_ExgMdFmt23Handler_hpp__ 19 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt9.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt9.hpp 2 | // 3 | // 定價交易個股成交資料. 4 | // 5 | // \author fonwinz@gmail.com 6 | #ifndef __f9tws_ExgMdFmt9_hpp__ 7 | #define __f9tws_ExgMdFmt9_hpp__ 8 | #include "f9tws/ExgMdFmt.hpp" 9 | 10 | namespace f9tws { 11 | fon9_PACK(1); 12 | 13 | struct ExgMdFmt9 : public ExgMdHead { 14 | StkNo StkNo_; 15 | fon9::PackBcd<6> DealHHMMSS_; 16 | ExgMdPriQty DealPQ_; 17 | }; 18 | 19 | fon9_PACK_POP; 20 | } // namespaces 21 | #endif//__f9tws_ExgMdFmt9_hpp__ 22 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmt9Handler.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmt9Handler.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmt9Handler_hpp__ 4 | #define __f9tws_ExgMdFmt9Handler_hpp__ 5 | #include "f9tws/ExgMdSystem.hpp" 6 | 7 | namespace f9tws { 8 | 9 | class f9tws_API ExgMdFmt9Handler : public ExgMdHandlerAnySeq { 10 | fon9_NON_COPY_NON_MOVE(ExgMdFmt9Handler); 11 | void OnPkReceived(const ExgMdHead& pk, unsigned pksz) override; 12 | public: 13 | using ExgMdHandlerAnySeq::ExgMdHandlerAnySeq; 14 | virtual ~ExgMdFmt9Handler(); 15 | }; 16 | 17 | } // namespaces 18 | #endif//__f9tws_ExgMdFmt9Handler_hpp__ 19 | -------------------------------------------------------------------------------- /f9tws/ExgMdFmtIxNoList.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdFmtIxNoList.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdFmtIxNoList_hpp__ 4 | #define __f9tws_ExgMdFmtIxNoList_hpp__ 5 | #include "f9tws/ExgMdFmtIx.hpp" 6 | 7 | namespace f9tws { 8 | 9 | extern f9tws_API const IdxNo TwseIxNoList_[43]; 10 | extern f9tws_API const IdxNo TpexIxNoList_[28]; 11 | 12 | } // namespaces 13 | #endif//__f9tws_ExgMdFmtIxNoList_hpp__ 14 | -------------------------------------------------------------------------------- /f9tws/ExgMdPkReceiver.cpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdPkReceiver.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9tws/ExgMdPkReceiver.hpp" 4 | 5 | namespace f9tws { 6 | 7 | ExgMdPkReceiver::~ExgMdPkReceiver() { 8 | } 9 | unsigned ExgMdPkReceiver::GetPkSize(const void* pkptr) { 10 | return reinterpret_cast(pkptr)->GetLength(); 11 | } 12 | 13 | } // namespaces 14 | -------------------------------------------------------------------------------- /f9tws/ExgMdPkReceiver.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdPkReceiver.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdPkReceiver_hpp__ 4 | #define __f9tws_ExgMdPkReceiver_hpp__ 5 | #include "f9tws/ExgMdFmt.hpp" 6 | #include "fon9/PkReceiver.hpp" 7 | 8 | namespace f9tws { 9 | 10 | /// 解析台灣證券交易所(及櫃買中心)行情格式框架. 11 | class f9tws_API ExgMdPkReceiver : public fon9::PkReceiver { 12 | fon9_NON_COPY_NON_MOVE(ExgMdPkReceiver); 13 | using base = fon9::PkReceiver; 14 | public: 15 | ExgMdPkReceiver(bool isDgram = false) 16 | : base{sizeof(ExgMdHead), isDgram} { 17 | } 18 | virtual ~ExgMdPkReceiver(); 19 | 20 | unsigned GetPkSize(const void* pkptr) override; 21 | }; 22 | 23 | } // namespaces 24 | #endif//__f9tws_ExgMdPkReceiver_hpp__ 25 | -------------------------------------------------------------------------------- /f9tws/ExgMdReceiverFactory.cpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdReceiverFactory.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9tws/ExgMdReceiverFactory.hpp" 4 | #include "f9tws/ExgMdReceiverSession.hpp" 5 | 6 | namespace f9tws { 7 | using namespace fon9; 8 | 9 | io::SessionSP ExgMdReceiverFactory::CreateSession(IoManager& ioMgr, const IoConfigItem& cfg, std::string& errReason) { 10 | (void)ioMgr; 11 | StrView tag, value, args = ToStrView(cfg.SessionArgs_); 12 | StrView pkLogName; 13 | while (fon9::StrFetchTagValue(args, tag, value)) { 14 | if (tag == "PkLog") 15 | pkLogName = value; 16 | else { 17 | errReason = "f9tws.ExgMdReceiverFactory.CreateSession: Unknown Tag:" + tag.ToString(); 18 | return nullptr; 19 | } 20 | } 21 | return new ExgMdReceiverSession(this->MdDispatcher_, pkLogName); 22 | } 23 | io::SessionServerSP ExgMdReceiverFactory::CreateSessionServer(IoManager& ioMgr, const IoConfigItem& cfg, std::string& errReason) { 24 | (void)ioMgr; (void)cfg; 25 | errReason = "f9tws.ExgMdReceiverFactory: Not support server."; 26 | return nullptr; 27 | } 28 | 29 | } // namespaces 30 | -------------------------------------------------------------------------------- /f9tws/ExgMdReceiverFactory.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdReceiverFactory.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_ExgMdReceiverFactory_hpp__ 4 | #define __f9tws_ExgMdReceiverFactory_hpp__ 5 | #include "f9tws/ExgMdSystemBase.hpp" 6 | #include "fon9/framework/IoFactory.hpp" 7 | 8 | namespace f9tws { 9 | 10 | class f9tws_API ExgMdReceiverFactory : public fon9::SessionFactory { 11 | fon9_NON_COPY_NON_MOVE(ExgMdReceiverFactory); 12 | using base = fon9::SessionFactory; 13 | public: 14 | const ExgMdSystemBaseSP MdDispatcher_; 15 | 16 | template 17 | ExgMdReceiverFactory(ExgMdSystemBaseSP mdDispatcher, ArgsT&&... args) 18 | : base(std::forward(args)...) 19 | , MdDispatcher_(std::move(mdDispatcher)) { 20 | } 21 | 22 | fon9::io::SessionSP CreateSession(fon9::IoManager& ioMgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 23 | fon9::io::SessionServerSP CreateSessionServer(fon9::IoManager& ioMgr, const fon9::IoConfigItem& cfg, std::string& errReason) override; 24 | }; 25 | 26 | } // namespaces 27 | #endif//__f9tws_ExgMdReceiverFactory_hpp__ 28 | -------------------------------------------------------------------------------- /f9tws/ExgMdSystemBase.cpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/ExgMdSystemBase.cpp 2 | // \author fonwinz@gmail.com 3 | #include "f9tws/ExgMdSystemBase.hpp" 4 | 5 | namespace f9tws { 6 | 7 | ExgMdHandlerPkCont::~ExgMdHandlerPkCont() { 8 | } 9 | void ExgMdHandlerPkCont::OnLogSeqGap(fon9::PkContFeeder& rthis, fon9::RevBuffer& rbuf, const void* pk) { 10 | (void)rthis; 11 | fon9::RevPrint(rbuf, "TwsExgMd.Gap" 12 | "|mkt=", static_cast(pk)->GetMarket(), 13 | "|fmt=", static_cast(pk)->GetFmtNo()); 14 | } 15 | //--------------------------------------------------------------------------// 16 | ExgMdSystemBase::~ExgMdSystemBase() { 17 | } 18 | void ExgMdSystemBase::OnMdSystemStartup(const unsigned tdayYYYYMMDD, const std::string& logPath) { 19 | base::OnMdSystemStartup(tdayYYYYMMDD, logPath); 20 | for (const ExgMdHandlerSP& pph : this->MdHandlers_) { 21 | if (pph.get()) 22 | pph->DailyClear(); 23 | } 24 | } 25 | 26 | } // namespaces 27 | -------------------------------------------------------------------------------- /f9tws/TwsTools.hpp: -------------------------------------------------------------------------------- 1 | // \file f9tws/TwsTools.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __f9tws_TwsTools_hpp__ 4 | #define __f9tws_TwsTools_hpp__ 5 | #include "f9tws/TwsTypes.h" 6 | #include "f9tws/ExgTypes.hpp" 7 | #include "fon9/fmkt/FmktTools.hpp" 8 | 9 | inline f9tws_SymbKind StrTo(fon9::StrView s, f9tws_SymbKind null, const char** endptr = nullptr) { 10 | return static_cast(fon9::HexStrTo(s, endptr, null)); 11 | } 12 | inline char* ToStrRev(char* pout, f9tws_SymbKind v) { 13 | return fon9::HexToStrRev(pout, fon9::cast_to_underlying(v)); 14 | } 15 | //--------------------------------------------------------------------------// 16 | namespace f9tws { 17 | 18 | struct f9tws_API TwsSymbKindLvPriStep { 19 | f9tws_SymbKind Kind_; 20 | char Padding____[7]; 21 | const fon9::fmkt::LvPriStep* LvPriSteps_; 22 | 23 | TwsSymbKindLvPriStep() = default; 24 | TwsSymbKindLvPriStep(StkNo stkno) { 25 | this->Setup(stkno); 26 | } 27 | void Setup(StkNo stkno); 28 | }; 29 | 30 | } // namespaces 31 | #endif//__f9tws_TwsTools_hpp__ 32 | -------------------------------------------------------------------------------- /fon9/Assert.c: -------------------------------------------------------------------------------- 1 | /// \file fon9/Assert.c 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/Assert.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #if defined(fon9_WINDOWS) && !defined(NDEBUG) 10 | fon9_API void fon9_wassert( 11 | _In_z_ wchar_t const* _Message, 12 | _In_z_ wchar_t const* _File, 13 | _In_ unsigned _Line 14 | ) { 15 | _wassert(_Message, _File, _Line); 16 | } 17 | #endif 18 | 19 | #ifdef __cplusplus 20 | }// extern "C" 21 | #endif 22 | -------------------------------------------------------------------------------- /fon9/Assert.h: -------------------------------------------------------------------------------- 1 | /// \file fon9/Assert.h 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_Assert_h__ 4 | #define __fon9_Assert_h__ 5 | #include "fon9/sys/Config.h" 6 | #include 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #if defined(fon9_WINDOWS) && !defined(NDEBUG) 13 | #undef assert 14 | #define assert(expression) (void)( \ 15 | (!!(expression)) || \ 16 | (fon9_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \ 17 | ) 18 | 19 | // 為了 debug 時, 可以在這裡可以設定中斷, 所以改寫了 assert(). 20 | fon9_API void fon9_wassert( 21 | _In_z_ wchar_t const* _Message, 22 | _In_z_ wchar_t const* _File, 23 | _In_ unsigned _Line 24 | ); 25 | #endif 26 | 27 | #ifdef __cplusplus 28 | }// extern "C" 29 | #endif 30 | #endif//__fon9_Assert_h__ 31 | -------------------------------------------------------------------------------- /fon9/Base64_UT.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/Base64_UT.cpp 2 | // \author fonwinz@gmail.com 3 | #define _CRT_SECURE_NO_WARNINGS 4 | #include "fon9/Base64.hpp" 5 | #include "fon9/TestTools.hpp" 6 | 7 | //--------------------------------------------------------------------------// 8 | 9 | void TestB64(const std::string orig, const std::string b64) { 10 | char dst[1024]; 11 | auto res = fon9::Base64Encode(dst, sizeof(dst), orig.c_str(), orig.size()); 12 | fon9_CheckTestResult(("Base64Encode:" + orig).c_str(), b64 == std::string(dst, res.GetResult())); 13 | res = fon9::Base64Decode(dst, sizeof(dst), b64.c_str(), b64.size()); 14 | fon9_CheckTestResult(("Base64Decode:" + b64).c_str(), orig == std::string(dst, res.GetResult())); 15 | } 16 | 17 | void TestAllB64() { 18 | TestB64("", ""); 19 | TestB64("f", "Zg=="); 20 | TestB64("fo", "Zm8="); 21 | TestB64("foo", "Zm9v"); 22 | TestB64("foob", "Zm9vYg=="); 23 | TestB64("fooba", "Zm9vYmE="); 24 | TestB64("foobar", "Zm9vYmFy"); 25 | } 26 | 27 | //--------------------------------------------------------------------------// 28 | 29 | int main(int argc, char** args) { 30 | (void)argc; (void)args; 31 | #if defined(_MSC_VER) && defined(_DEBUG) 32 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 33 | //_CrtSetBreakAlloc(176); 34 | #endif 35 | fon9::AutoPrintTestInfo utinfo{"Base64"}; 36 | 37 | TestAllB64(); 38 | } 39 | -------------------------------------------------------------------------------- /fon9/CStrView.h: -------------------------------------------------------------------------------- 1 | // \file fon9/CStrView.h 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_CStrView_h__ 4 | #define __fon9_CStrView_h__ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif//__cplusplus 9 | 10 | /// 使用時, 除非有特別的說明, 11 | /// Begin_ 可以視為一般的 c 字串, *(End_) 為 '\0'; 12 | struct fon9_CStrView_t { 13 | const char* Begin_; 14 | const char* End_; 15 | }; 16 | typedef struct fon9_CStrView_t fon9_CStrView; 17 | 18 | #ifdef __cplusplus 19 | }//extern "C" 20 | 21 | template 22 | inline auto fon9_CStrViewFrom(fon9_CStrView& dst, const StrT& str) 23 | -> decltype(str.c_str(), void()) { 24 | dst.Begin_ = str.c_str(); 25 | dst.End_ = dst.Begin_ + str.size(); 26 | } 27 | 28 | template 29 | inline auto fon9_ToCStrView(const StrT& str) -> decltype(fon9_CStrView{str.c_str(),str.c_str()+str.size()}) { 30 | fon9_CStrView retval; 31 | fon9_CStrViewFrom(retval, str); 32 | return retval; 33 | } 34 | template 35 | inline auto fon9_ToCStrView(const StrT& str) -> decltype(fon9_CStrView(ToStrView(str).ToCStrView())) { 36 | return ToStrView(str).ToCStrView(); 37 | } 38 | #endif//__cplusplus 39 | 40 | #endif//__fon9_CStrView_h__ 41 | -------------------------------------------------------------------------------- /fon9/Comparable.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/Comparable.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_Comparable_hpp__ 4 | #define __fon9_Comparable_hpp__ 5 | 6 | namespace fon9 { 7 | 8 | /// \ingroup AlNum 9 | /// - 您的 T 必須有定義: 10 | /// - bool operator==(const T& lhs, const T& rhs); 11 | /// - bool operator< (const T& lhs, const T& rhs); 12 | /// - 然後可透過這裡, 增加: 13 | /// - bool operator!=(const T& lhs, const T& rhs); 14 | /// - bool operator> (const T& lhs, const T& rhs); 15 | /// - bool operator>=(const T& lhs, const T& rhs); 16 | /// - bool operator<=(const T& lhs, const T& rhs); 17 | template 18 | struct Comparable { 19 | inline friend bool operator!=(const T& lhs, const T& rhs) { 20 | return !(lhs == rhs); 21 | } 22 | inline friend bool operator> (const T& lhs, const T& rhs) { 23 | return (rhs < lhs); 24 | } 25 | inline friend bool operator<=(const T& lhs, const T& rhs) { 26 | return !(rhs < lhs); 27 | } 28 | inline friend bool operator>=(const T& lhs, const T& rhs) { 29 | return !(lhs < rhs); 30 | } 31 | }; 32 | 33 | } // namespaces 34 | #endif//__fon9_Comparable_hpp__ 35 | -------------------------------------------------------------------------------- /fon9/ConfigUtils.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/ConfigUtils.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/ConfigUtils.hpp" 4 | 5 | namespace fon9 { 6 | 7 | fon9_API EnabledYN StrTo(StrView str, EnabledYN defaultValue, const char** endptr) { 8 | const char* pbeg = StrTrimHead(&str).begin(); 9 | switch (toupper(str.Get1st())) { 10 | case 'Y': 11 | if (endptr) { 12 | ++pbeg; 13 | if (str.size() >= 3) { // "Yes" 14 | if (toupper(pbeg[0]) == 'E' && toupper(pbeg[1]) == 'S') 15 | pbeg += 2; 16 | } 17 | *endptr = pbeg; 18 | } 19 | return EnabledYN::Yes; 20 | case 'N': 21 | if (endptr) { 22 | ++pbeg; 23 | if (str.size() >= 2) { // "No" 24 | if (toupper(pbeg[0]) == 'O') 25 | ++pbeg; 26 | } 27 | *endptr = pbeg; 28 | } 29 | return EnabledYN{}; 30 | case EOF: 31 | if (endptr) 32 | *endptr = pbeg; 33 | return EnabledYN{}; 34 | default: 35 | if (endptr) 36 | *endptr = pbeg; 37 | return defaultValue; 38 | } 39 | } 40 | 41 | } // namespaces 42 | -------------------------------------------------------------------------------- /fon9/CountDownLatch.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/CountDownLatch.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/CountDownLatch.hpp" 4 | 5 | namespace fon9 { 6 | 7 | void CountDownLatch::Wait() { 8 | Locker locker(this->Mutex_); 9 | while (this->Counter_ > 0) 10 | this->Waiter_.Wait(locker); 11 | } 12 | void CountDownLatch::CountDown() { 13 | Locker locker(this->Mutex_); 14 | if (--this->Counter_ > 0) 15 | return; 16 | this->Counter_ = 0; 17 | this->Waiter_.NotifyAll(locker); 18 | } 19 | int CountDownLatch::ForceWakeUp() { 20 | Locker locker(this->Mutex_); 21 | int bfcount = this->Counter_; 22 | this->Counter_ = 0; 23 | this->Waiter_.NotifyAll(locker); 24 | return bfcount; 25 | } 26 | int CountDownLatch::AddCounter(unsigned count) { 27 | Locker locker(this->Mutex_); 28 | int bfcount = this->Counter_; 29 | this->Counter_ += count; 30 | return bfcount; 31 | } 32 | 33 | } // namespace 34 | -------------------------------------------------------------------------------- /fon9/CountDownLatch.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/CountDownLatch.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_CountDownLatch_hpp__ 4 | #define __fon9_CountDownLatch_hpp__ 5 | #include "fon9/WaitPolicy.hpp" 6 | 7 | namespace fon9 { 8 | 9 | fon9_WARN_DISABLE_PADDING; 10 | /// \ingroup Thrs 11 | /// 等候指定數量的倒數. 12 | /// 一旦倒數到 0, 就會叫醒所有的等候者, 且以後的等候都會立即返回. 13 | class fon9_API CountDownLatch { 14 | fon9_NON_COPY_NON_MOVE(CountDownLatch); 15 | using Waiter = WaitPolicy_CV; 16 | using Mutex = Waiter::Mutex; 17 | using Locker = typename Waiter::Locker; 18 | Mutex Mutex_; 19 | Waiter Waiter_; 20 | signed Counter_; 21 | public: 22 | /// 建構時指定要倒數的次數. 23 | inline explicit CountDownLatch(unsigned count) : Counter_(static_cast(count)) { 24 | } 25 | /// 等候倒數到0, 才會返回. 26 | /// 這裡不會變動計數器. 27 | void Wait(); 28 | 29 | /// 倒數一次, 倒數到0時, 觸發喚醒全部等候者. 30 | void CountDown(); 31 | 32 | /// 強迫倒數結束. 33 | /// 返回強制中斷前剩餘倒數次數. 34 | int ForceWakeUp(); 35 | 36 | /// 強制增加 Counter. 37 | /// 返回強制增加前剩餘倒數次數. 38 | int AddCounter(unsigned count); 39 | }; 40 | fon9_WARN_POP; 41 | 42 | } // namespaces 43 | #endif//__fon9_CountDownLatch_hpp__ 44 | -------------------------------------------------------------------------------- /fon9/CtrlBreakHandler.h: -------------------------------------------------------------------------------- 1 | // \file fon9/CtrlBreakHandler.h 2 | // fon9 console 3 | // \author fonwinz@gmail.com 4 | #ifndef __fon9_CtrlBreakHandler_h__ 5 | #define __fon9_CtrlBreakHandler_h__ 6 | #include "fon9/sys/Config.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | extern fon9_API const char* fon9_AppBreakMsg; 13 | extern fon9_API void fon9_CAPI_CALL fon9_SetupCtrlBreakHandler(void); 14 | 15 | /// 使用者手動結束程式, 主程式必須使用 while(fon9_AppBreakMsg == NULL) 迴圈; 16 | /// 此處會關閉 stdin; 中斷正在等後使用者輸入的地方. 17 | /// 您必須自行確保 appBreakMsg 在程式 main() 結束前都持續有效! 18 | extern fon9_API void fon9_CAPI_CALL fon9_BreakApp(const char* appBreakMsg); 19 | 20 | #ifdef __cplusplus 21 | }//extern "C" 22 | #endif 23 | #endif//__fon9_CtrlBreakHandler_h__ 24 | -------------------------------------------------------------------------------- /fon9/CyclicBarrier.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/CyclicBarrier.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/CyclicBarrier.hpp" 4 | 5 | namespace fon9 { 6 | 7 | void CyclicBarrier::Wait() { 8 | Locker locker(this->Mutex_); 9 | if (++this->WaitingCount_ < this->ExpectedCount_) { 10 | this->Latch_.Wait(locker); 11 | } else { 12 | this->WaitingCount_ = 0; 13 | this->Latch_.NotifyAll(locker); 14 | } 15 | } 16 | 17 | } // namespace 18 | -------------------------------------------------------------------------------- /fon9/CyclicBarrier.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/CyclicBarrier.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_CyclicBarrier_hpp__ 4 | #define __fon9_CyclicBarrier_hpp__ 5 | #include "fon9/WaitPolicy.hpp" 6 | 7 | namespace fon9 { 8 | 9 | /// \ingroup Thrs 10 | /// 當同時等候中的 Threads 到達指定數量時, 則喚醒所有等候者. 11 | /// 喚醒等候者之後, 計數器會歸0, 重複等候邏輯. 12 | class fon9_API CyclicBarrier { 13 | fon9_NON_COPY_NON_MOVE(CyclicBarrier); 14 | using Waiter = WaitPolicy_CV; 15 | using Mutex = Waiter::Mutex; 16 | using Locker = typename Waiter::Locker; 17 | Mutex Mutex_; 18 | Waiter Latch_; 19 | unsigned WaitingCount_; 20 | public: 21 | /// 期待等候的數量. 22 | const unsigned ExpectedCount_; 23 | explicit CyclicBarrier(unsigned expectedCount) : WaitingCount_(0), ExpectedCount_(expectedCount) { 24 | } 25 | /// 當同時等候的Threads到達指定數量時返回. 26 | void Wait(); 27 | }; 28 | 29 | } // namespaces 30 | #endif//__fon9_CyclicBarrier_hpp__ 31 | -------------------------------------------------------------------------------- /fon9/DecBase.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/DecBase.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/DecBase.hpp" 4 | 5 | namespace fon9 { 6 | 7 | fon9_API uintmax_t GetDecDivisor(DecScaleT scale) { 8 | // 使用 uintmax_t 可以到19位, 但卻無法處理 intmax_t 的負數, 所以這裡必須使用 DecDivisor::Divisor 9 | static constexpr intmax_t dmap[DecScaleMax + 1]{ 10 | DecDivisor::Divisor, 11 | DecDivisor::Divisor, 12 | DecDivisor::Divisor, 13 | DecDivisor::Divisor, 14 | DecDivisor::Divisor, 15 | DecDivisor::Divisor, 16 | DecDivisor::Divisor, 17 | DecDivisor::Divisor, 18 | DecDivisor::Divisor, 19 | DecDivisor::Divisor, 20 | DecDivisor::Divisor, 21 | DecDivisor::Divisor, 22 | DecDivisor::Divisor, 23 | DecDivisor::Divisor, 24 | DecDivisor::Divisor, 25 | DecDivisor::Divisor, 26 | DecDivisor::Divisor, 27 | DecDivisor::Divisor, 28 | DecDivisor::Divisor, 29 | }; 30 | if (fon9_LIKELY(scale < numofele(dmap))) 31 | return static_cast(dmap[scale]); 32 | Raise("GetDecDivisor(scale > DecScaleMax)"); 33 | } 34 | 35 | } // namespaces 36 | -------------------------------------------------------------------------------- /fon9/DummyMutex.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/DummyMutex.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_DummyMutex_hpp__ 4 | #define __fon9_DummyMutex_hpp__ 5 | #include "fon9/sys/Config.hpp" 6 | 7 | namespace fon9 { 8 | 9 | class DummyMutex { 10 | fon9_NON_COPY_NON_MOVE(DummyMutex); 11 | public: 12 | DummyMutex() = default; 13 | void lock() {} 14 | void unlock() {} 15 | }; 16 | 17 | } // namespaces 18 | #endif//__fon9_DummyMutex_hpp__ 19 | -------------------------------------------------------------------------------- /fon9/ErrC.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/ErrC.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_ErrC_hpp__ 4 | #define __fon9_ErrC_hpp__ 5 | #include "fon9/sys/Config.hpp" 6 | 7 | fon9_BEFORE_INCLUDE_STD; 8 | #include 9 | fon9_AFTER_INCLUDE_STD; 10 | 11 | namespace fon9 { 12 | 13 | using ErrC = std::error_condition; 14 | 15 | #ifdef fon9_WINDOWS 16 | fon9_API ErrC GetSysErrC(DWORD eno = ::GetLastError()); 17 | #else 18 | fon9_API ErrC GetSysErrC(int eno = errno); 19 | #endif 20 | 21 | template 22 | void RevPrint(RevBuffer& rbuf, ErrC errc) { 23 | RevPrint(rbuf, ':', errc.value(), ':', errc.message()); 24 | if (errc.category() != std::generic_category()) 25 | RevPrint(rbuf, errc.category().name()); 26 | } 27 | 28 | } // namespace 29 | #endif//__fon9_ErrC_hpp__ 30 | -------------------------------------------------------------------------------- /fon9/F9cardDevel.h: -------------------------------------------------------------------------------- 1 | // \file fon9/F9cardDevel.h 2 | // 3 | // 用於開發階段, 包含 [量測延遲] 所需的相關檔案. 4 | // 5 | // \author fonwinz@gmail.com 6 | #ifndef __fon9_F9cardDevel_h__ 7 | #define __fon9_F9cardDevel_h__ 8 | 9 | #ifdef F9CARD 10 | #include "f9/LatencyMeasure.h" 11 | #include "f9/CpuCache.h" 12 | #else 13 | # define f9_LatencyMeasure_Push(locName) 14 | # define f9_DCachePrefetchRd(addr,locality) 15 | # define f9_DCachePrefetchWr(addr,locality) 16 | #endif 17 | 18 | #endif//__fon9_F9cardDevel_h__ 19 | -------------------------------------------------------------------------------- /fon9/FdrNotify.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/FdrNotify.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_FdrNotify_hpp__ 4 | #define __fon9_FdrNotify_hpp__ 5 | #include "fon9/Fdr.hpp" 6 | #include "fon9/Outcome.hpp" 7 | 8 | #ifdef __linux__ 9 | #define fon9_HAVE_EVENTFD 10 | #include 11 | #endif 12 | 13 | namespace fon9 { 14 | 15 | /// \ingroup Misc 16 | /// - Linux: 使用 eventfd() 實現. 17 | /// - 非linux: 使用 pipe() 實現. 18 | class fon9_API FdrNotify { 19 | fon9_NON_COPY_NON_MOVE(FdrNotify); 20 | #ifdef fon9_HAVE_EVENTFD 21 | FdrAuto EventFdr_; 22 | #else 23 | FdrAuto FdrRead_; 24 | FdrAuto FdrWrite_; 25 | #endif 26 | public: 27 | using Result = Result3; 28 | 29 | FdrNotify() { 30 | this->Open(); 31 | } 32 | /// 開啟 fd, 若建構時已開啟成功, 不會重新開啟. 33 | Result Open(); 34 | /// 喚醒讀取端. 35 | Result Wakeup(); 36 | /// 取得讀取端的 fd. 37 | Fdr::fdr_t GetReadFD() const { 38 | #ifdef fon9_HAVE_EVENTFD 39 | return EventFdr_.GetFD(); 40 | #else 41 | return FdrRead_.GetFD(); 42 | #endif 43 | } 44 | /// 傳回 Wakeup() 呼叫的次數, 並清除計數器. 45 | uint64_t ClearWakeup(); 46 | }; 47 | 48 | } // namespaces 49 | #endif//__fon9_FdrNotify_hpp__ 50 | -------------------------------------------------------------------------------- /fon9/FileReadAll.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/FileReadAll.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/FileReadAll.hpp" 4 | 5 | namespace fon9 { 6 | 7 | fon9_API ReadAllResult OpenReadAll(File& fd, CharVector& fbuf, std::string fname, FileMode fmode) { 8 | File::Result fres; 9 | if (!fname.empty()) { 10 | fres = fd.Open(std::move(fname), fmode); 11 | if (fres.IsError()) 12 | return ReadAllResult{"Open", fres.GetError()}; 13 | } 14 | fres = fd.GetFileSize(); 15 | if (fres.IsError()) 16 | return ReadAllResult{"GetFileSize", fres.GetError()}; 17 | if (fbuf.alloc(fres.GetResult()) == nullptr) 18 | return ReadAllResult{"Alloc", std::errc::not_enough_memory}; 19 | fres = fd.Read(0, fbuf.begin(), fres.GetResult()); 20 | if (fres.IsError()) 21 | return ReadAllResult{"Read", fres.GetError()}; 22 | return ReadAllResult{}; 23 | } 24 | 25 | } // namespace 26 | -------------------------------------------------------------------------------- /fon9/FileReadAll.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/FileReadAll.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_FileReadAll_hpp__ 4 | #define __fon9_FileReadAll_hpp__ 5 | #include "fon9/buffer/DcQueueList.hpp" 6 | #include "fon9/buffer/FwdBufferList.hpp" 7 | #include "fon9/File.hpp" 8 | 9 | namespace fon9 { 10 | 11 | using ReadAllResult = Result2T; 12 | 13 | /// fname.empty() 則直接使用 fd, 不需要開啟檔案; 14 | fon9_API ReadAllResult OpenReadAll(File& fd, CharVector& fbuf, std::string fname, FileMode fmode); 15 | 16 | template 17 | typename FileT::Result FileReadAll(FileT& fd, PosT& fpos, ConsumerT&& consumer) { 18 | DcQueueList rdbuf; 19 | for (;;) { 20 | FwdBufferNode* node = FwdBufferNode::Alloc(32 * 1024); 21 | auto res = fd.Read(fpos, node->GetDataEnd(), node->GetRemainSize()); 22 | if (res.IsError()) { 23 | FreeNode(node); 24 | return res; 25 | } 26 | if (res.GetResult() <= 0) { 27 | FreeNode(node); 28 | return res; 29 | } 30 | fpos += res.GetResult(); 31 | node->SetDataEnd(node->GetDataEnd() + res.GetResult()); 32 | rdbuf.push_back(node); 33 | if (!consumer(rdbuf, res)) 34 | return res; 35 | } 36 | } 37 | 38 | } // namespaces 39 | #endif//__fon9_FileReadAll_hpp__ 40 | -------------------------------------------------------------------------------- /fon9/FlowCounter.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/FlowCounter.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/FlowCounter.hpp" 4 | 5 | namespace fon9 { 6 | 7 | ConfigParser::Result FlowCounterArgs::OnTagValue(StrView tag, StrView& value) { 8 | if (iequals(tag, "Fc")) 9 | return this->OnValue(value); 10 | return ConfigParser::Result::EUnknownTag; 11 | } 12 | ConfigParser::Result FlowCounterArgs::OnValue(StrView& value) { 13 | this->FcCount_ = StrTo(&value, this->FcCount_); 14 | if (StrTrimHead(&value).Get1st() == '/') { 15 | value.SetBegin(value.begin() + 1); 16 | this->FcTimeMS_ = StrTo(&value, this->FcTimeMS_); 17 | } 18 | return value.empty() ? ConfigParser::Result::Success : ConfigParser::Result::EInvalidValue; 19 | } 20 | 21 | } // namespace 22 | -------------------------------------------------------------------------------- /fon9/HostId.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/HostId.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/HostId.hpp" 4 | 5 | namespace fon9 { 6 | 7 | fon9_API HostId LocalHostId_; 8 | 9 | } // namespaces 10 | -------------------------------------------------------------------------------- /fon9/HostId.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/HostId.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_HostId_hpp__ 4 | #define __fon9_HostId_hpp__ 5 | #include "fon9/sys/Config.hpp" 6 | #include 7 | 8 | namespace fon9 { 9 | 10 | using HostId = uint32_t; 11 | 12 | /// \ingroup Misc 13 | /// 需在啟動時由使用者設定內容, 在沒設定之前為 LocalHostId_==0. 14 | extern fon9_API HostId LocalHostId_; 15 | 16 | } // namespaces 17 | #endif//__fon9_HostId_hpp__ 18 | -------------------------------------------------------------------------------- /fon9/Outcome.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/Outcome.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/Outcome.hpp" 4 | 5 | namespace fon9 { 6 | 7 | [[noreturn]] fon9_API void RaiseOutcomeException(OutcomeSt st) { 8 | switch (st) { 9 | default: 10 | case OutcomeSt::NoValue: Raise("Outcome NoValue"); 11 | case OutcomeSt::Result: Raise("Outcome HasResult"); 12 | case OutcomeSt::Error: Raise("Outcome IsError"); 13 | } 14 | } 15 | 16 | } // namespace 17 | -------------------------------------------------------------------------------- /fon9/PassKey.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/PassKey.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/PassKey.hpp" 4 | #include "fon9/StrTo.hpp" 5 | 6 | namespace fon9 { 7 | 8 | static bool defaultPassKeyToPassword(const StrView& passKey, CharVector& password) { 9 | password.assign(passKey); 10 | return false; 11 | } 12 | static FnPassKeyToPassword stFnPassKeyToPassword = defaultPassKeyToPassword; 13 | //--------------------------------------------------------------------------// 14 | fon9_API void SetFnPassKeyToPassword(FnPassKeyToPassword fnPassKeyToPassword) { 15 | stFnPassKeyToPassword = (fnPassKeyToPassword ? fnPassKeyToPassword : defaultPassKeyToPassword); 16 | } 17 | 18 | fon9_API bool PassKeyToPassword(const StrView& passKey, CharVector& password) { 19 | return stFnPassKeyToPassword(passKey, password); 20 | } 21 | 22 | fon9_API unsigned PassKeyToPassNum(const StrView& passKey, unsigned defaultPassNum) { 23 | CharVector password; 24 | if (PassKeyToPassword(passKey, password)) 25 | return StrTo(ToStrView(password), defaultPassNum); 26 | return defaultPassNum; 27 | } 28 | 29 | } // namesapce fon9; 30 | -------------------------------------------------------------------------------- /fon9/PassKey.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/PassKey.hpp 2 | // 3 | // PassIdMgr: 協助管理密碼設定 4 | // 在系統的設定裡面使用 PassKey="PassId/Salt"; 可以避免在設定中出現[明碼]. 5 | // 6 | // \author fonwinz@gmail.com 7 | #ifndef __fon9_PassKey_hpp__ 8 | #define __fon9_PassKey_hpp__ 9 | #include "fon9/CharVector.hpp" 10 | 11 | namespace fon9 { 12 | 13 | typedef bool (*FnPassKeyToPassword)(const StrView& passKey, CharVector& password); 14 | 15 | /// \ingroup Misc 16 | /// 設定透過 passKey 取得 password 的功能. 17 | extern fon9_API void SetFnPassKeyToPassword(FnPassKeyToPassword fnPassKeyToPassword); 18 | 19 | /// \ingroup Misc 20 | /// 透過 passKey 取得 password. 21 | /// 預設: password = passKey, 返回 false; 22 | extern fon9_API bool PassKeyToPassword(const StrView& passKey, CharVector& password); 23 | 24 | /// \ingroup Misc 25 | /// 透過 passKey 取得數字密碼. 26 | /// \code 27 | /// if (PassKeyToPassword()) return StrTo(password, defaultPassNum); 28 | /// else return defaultPassNum; 29 | /// \endcode 30 | extern fon9_API unsigned PassKeyToPassNum(const StrView& passKey, unsigned defaultPassNum); 31 | 32 | } // namespace 33 | #endif//__fon9_PassKey_hpp__ 34 | -------------------------------------------------------------------------------- /fon9/Random.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/Random.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_Random_hpp__ 4 | #define __fon9_Random_hpp__ 5 | #include "fon9/sys/Config.hpp" 6 | 7 | fon9_BEFORE_INCLUDE_STD; 8 | #include 9 | fon9_AFTER_INCLUDE_STD; 10 | 11 | namespace fon9 { 12 | 13 | /// \ingroup Misc 14 | /// 在 dst[0..dstSize-1] 填入亂數. 15 | fon9_API void RandomBytes(void* dst, size_t dstSize); 16 | 17 | /// \ingroup Misc 18 | /// 在 dst[0..dstSize) 任意填入以下 ASCII 字元, 不包含 EOS. 19 | /// - '0'..'9', 'A'..'Z', 'a'..'z' 20 | /// - '+', '-', '*', '/', '%', '@' 21 | /// - '!', '$', '&', '_', '?', '^' 22 | fon9_API void RandomChars(char* dst, size_t dstSize); 23 | 24 | /// \ingroup Misc 25 | /// = RandomChars(dst, dstSize-1); dst[dstSize-1] = 0; 26 | inline void RandomString(char* dst, size_t dstSize) { 27 | if (fon9_LIKELY(dstSize > 0)) { 28 | dst[dstSize - 1] = 0; 29 | if (fon9_LIKELY(dstSize > 1)) 30 | RandomChars(dst, dstSize - 1); 31 | } 32 | } 33 | 34 | /// \ingroup Misc 35 | /// 取得一個 thrdad_local 的 std::default_random_engine 36 | fon9_API std::default_random_engine& GetRandomEngine(); 37 | 38 | } // namespaces 39 | #endif//__fon9_Random_hpp__ 40 | -------------------------------------------------------------------------------- /fon9/SimpleFactory.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/SimpleFactory.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/SimpleFactory.hpp" 4 | 5 | namespace fon9 { 6 | 7 | fon9_API void SimpleFactoryPrintDupName(StrView name, unsigned priority) { 8 | fprintf(stderr, "SimpleFactoryRegister: priority=%u, dup name: %s\n", priority, name.ToString().c_str()); 9 | } 10 | 11 | } // namespaces 12 | -------------------------------------------------------------------------------- /fon9/SleepPolicy.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/SleepPolicy.hpp 2 | /// \brief 提供各種 [睡一會兒] 的策略 3 | /// \author fonwinz@gmail.com 4 | #ifndef __fon9_SleepPolicy_hpp__ 5 | #define __fon9_SleepPolicy_hpp__ 6 | #include "fon9/sys/Config.hpp" 7 | 8 | fon9_BEFORE_INCLUDE_STD; 9 | #include 10 | fon9_AFTER_INCLUDE_STD; 11 | 12 | namespace fon9 { 13 | 14 | /// \ingroup Thrs 15 | /// 不睡覺,立即返回. 16 | class BusySleepPolicy { 17 | public: 18 | /// 不睡, 立即返回. 19 | static void Sleep() { 20 | } 21 | /// 因為不睡, 所以不用喚醒: do nothing. 22 | static void WakeUp() { 23 | } 24 | }; 25 | 26 | /// \ingroup Thrs 27 | /// 用 std::this_thread::yield() 睡覺. 28 | class YieldSleepPolicy { 29 | public: 30 | /// 利用 std::this_thread::yield() 睡覺, 然後立即返回. 31 | static void Sleep() { 32 | std::this_thread::yield(); 33 | } 34 | /// 等候 std::this_thread::yield() 返回自然會醒, 所以這裡: do nothing. 35 | static void WakeUp() { 36 | } 37 | }; 38 | 39 | /// \ingroup Thrs 40 | /// 用 std::this_thread::sleep_for() 睡覺. 41 | /// \tparam ns 沉睡時間(10^-9 秒) 42 | template 43 | class NanoSleepPolicy { 44 | public: 45 | /// 沉睡 ns (10^-9 秒), 然後返回, 睡醒前無法中斷. 46 | static void Sleep() { 47 | std::this_thread::sleep_for(std::chrono::nanoseconds(ns)); 48 | } 49 | /// 等時間到自然會醒, 沒有喚醒功能: do nothing. 50 | static void WakeUp() { 51 | } 52 | }; 53 | 54 | } // namespaces 55 | #endif//__fon9_SleepPolicy_hpp__ 56 | -------------------------------------------------------------------------------- /fon9/SpinMutex.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/SpinMutex.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_SpinMutex_hpp__ 4 | #define __fon9_SpinMutex_hpp__ 5 | #include "fon9/sys/Config.hpp" 6 | #include "fon9/SleepPolicy.hpp" 7 | #include 8 | 9 | namespace fon9 { 10 | 11 | /// \ingroup Thrs 12 | /// 使用 spin 機制模擬 mutex. 13 | /// 您必須提供 SleepPolicy::Sleep() 在鎖不住時, 睡一會兒. 14 | /// \tparam SleepPolicy 參考 fon9/SleepPolicy.hpp: BusySleepPolicy, YieldSleepPolicy, NanoSleepPolicy... 15 | template 16 | class SpinMutex : private SleepPolicy { 17 | fon9_NON_COPYABLE(SpinMutex); 18 | std::atomic_flag Mx_ = ATOMIC_FLAG_INIT; 19 | public: 20 | using SleepPolicy::SleepPolicy; 21 | SpinMutex() : SleepPolicy{} { 22 | } 23 | 24 | /// 當鎖不住時, 利用 SleepPolicy::Sleep() 睡一會兒, 然後重新嘗試再鎖一次, 直到鎖成功才返回. 25 | void lock() { 26 | while (!try_lock()) 27 | this->Sleep(); 28 | } 29 | 30 | /// 嘗試鎖住, 立即即返回: 鎖成功傳回 true, 無法鎖住傳回 false. 31 | bool try_lock() { 32 | return !this->Mx_.test_and_set(std::memory_order_acquire); 33 | } 34 | 35 | /// 解鎖, 不檢查現在鎖的狀態, 所以您必須自行確定: 之前有鎖成功. 36 | void unlock() { 37 | this->Mx_.clear(std::memory_order_release); 38 | this->WakeUp(); 39 | } 40 | 41 | void Wait() { 42 | this->Sleep(); 43 | } 44 | }; 45 | 46 | using SpinBusy = SpinMutex; 47 | 48 | } // namespaces 49 | #endif//__fon9_SpinMutex_hpp__ 50 | -------------------------------------------------------------------------------- /fon9/ThreadId.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/ThreadId.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/ThreadId.hpp" 4 | #include "fon9/ToStr.hpp" 5 | 6 | #ifndef fon9_WINDOWS 7 | #include //For SYS_xxx definitions 8 | inline static fon9::ThreadId::IdType GetCurrentThreadId() { 9 | // return static_cast(pthread_self());//pthread_self()用的是一個內部指標, 與 OS 的 thread-id 無關, 所以並不適合. 10 | return static_cast(::syscall(SYS_gettid)); 11 | // return static_cast(syscall(__NR_gettid)); 12 | } 13 | #endif 14 | 15 | namespace fon9 { 16 | 17 | const thread_local ThreadId ThisThread_; 18 | 19 | ThreadId::ThreadId() : ThreadId_{::GetCurrentThreadId()} { 20 | char* const pend = this->ThreadIdStr_ + sizeof(this->ThreadIdStr_); 21 | char* pout = UIntToStrRev(pend, this->ThreadId_); 22 | size_t wlen = static_cast(pend - pout); 23 | while (++wlen <= 5) 24 | *--pout = ' '; 25 | *--pout = ' '; 26 | this->ThreadIdStrWidth_ = static_cast(wlen); 27 | memmove(this->ThreadIdStr_, pout, wlen); 28 | *(this->ThreadIdStr_ + wlen) = '\0'; 29 | } 30 | 31 | fon9_API const ThreadId& GetThisThreadId() { 32 | return ThisThread_; 33 | } 34 | 35 | } // namespaces 36 | -------------------------------------------------------------------------------- /fon9/ThreadId.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/ThreadId.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_ThreadId_hpp__ 4 | #define __fon9_ThreadId_hpp__ 5 | #include "fon9/StrView.hpp" 6 | 7 | namespace fon9 { 8 | 9 | /// \ingroup Thrs 10 | /// this thread 的基本資料. 11 | struct ThreadId { 12 | using IdType = uintptr_t; 13 | /// Windows=GetCurrentThreadId(), Linux=pthread_self() 14 | IdType ThreadId_; 15 | /// ThreadIdStr_ 不含 EOS 的長度. 16 | uint8_t ThreadIdStrWidth_; 17 | /// ThreadId_ 轉成字串: 預設 = 從前方算起 " nnnnn"(10進位字串, 長度最少為6包含開頭1空白), 若超過5碼, 則自動擴展. 18 | /// 必定會有 EOS, 但不包含在 ThreadIdStrWidth_. 19 | char ThreadIdStr_[15]; 20 | 21 | ThreadId(); 22 | 23 | StrView GetThreadIdStr() const { 24 | return StrView{this->ThreadIdStr_, this->ThreadIdStrWidth_}; 25 | } 26 | }; 27 | 28 | /// \ingroup Thrs 29 | /// Windows 不能使用 fon9_API + thread_local, 所以必須使用 GetThisThreadId() 取得. 30 | extern const thread_local ThreadId ThisThread_; 31 | 32 | /// \ingroup Thrs 33 | /// 取得 this_thread 的 ThreadId: 可藉此取得 ThreadId_, ThreadIdStr_. 34 | fon9_API const ThreadId& GetThisThreadId(); 35 | 36 | } // namespaces 37 | #endif//__fon9_ThreadId_hpp__ 38 | -------------------------------------------------------------------------------- /fon9/ThreadTools.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/ThreadTools.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/ThreadTools.hpp" 4 | 5 | namespace fon9 { 6 | 7 | #ifdef fon9_WINDOWS 8 | 9 | const DWORD MS_VC_EXCEPTION = 0x406D1388; 10 | 11 | fon9_WARN_DISABLE_PADDING 12 | #pragma pack(push,8) 13 | typedef struct tagTHREADNAME_INFO 14 | { 15 | DWORD dwType; // Must be 0x1000. 16 | LPCSTR szName; // Pointer to name (in user addr space). 17 | DWORD dwThreadID; // Thread ID (-1=caller thread). 18 | DWORD dwFlags; // Reserved for future use, must be zero. 19 | } THREADNAME_INFO; 20 | #pragma pack(pop) 21 | fon9_WARN_POP 22 | 23 | void SetCurrentThreadName(const char* threadName) { 24 | THREADNAME_INFO info; 25 | info.dwType = 0x1000; 26 | info.szName = threadName; 27 | info.dwThreadID = (DWORD)-1; 28 | info.dwFlags = 0; 29 | #pragma warning(push) 30 | #pragma warning(disable: 6320 6322) 31 | __try { 32 | RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); 33 | } 34 | __except (EXCEPTION_EXECUTE_HANDLER) { 35 | } 36 | #pragma warning(pop) 37 | } 38 | #endif 39 | 40 | } // namespaces 41 | -------------------------------------------------------------------------------- /fon9/ThreadTools.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/ThreadTools.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_ThreadTools_hpp__ 4 | #define __fon9_ThreadTools_hpp__ 5 | #include "fon9/sys/Config.hpp" 6 | 7 | fon9_BEFORE_INCLUDE_STD 8 | #include 9 | fon9_AFTER_INCLUDE_STD 10 | 11 | namespace fon9 { 12 | 13 | inline void JoinThread(std::thread& thr) { 14 | if (thr.joinable()) 15 | thr.join(); 16 | } 17 | 18 | template 19 | inline void JoinThreads(ThreadContainer& thrs) { 20 | for (std::thread& thr : thrs) 21 | JoinThread(thr); 22 | } 23 | 24 | inline void JoinOrDetach(std::thread& thr) { 25 | if (thr.get_id() == std::this_thread::get_id()) 26 | thr.detach(); 27 | else 28 | if (thr.joinable()) 29 | thr.join(); 30 | } 31 | 32 | template 33 | inline void JoinOrDetach(ThreadContainer& thrs) { 34 | for (std::thread& thr : thrs) 35 | JoinOrDetach(thr); 36 | } 37 | 38 | /// 設定 ThreadName. 39 | /// 可讓 M$ VS 開發環境, 在 debug 時的 Threads 視窗, 清楚看出各個 threads 的用途. 40 | #ifdef fon9_WINDOWS 41 | fon9_API void SetCurrentThreadName(const char* threadName); 42 | #else 43 | inline void SetCurrentThreadName(const char* threadName) { 44 | (void)threadName; 45 | } 46 | #endif 47 | 48 | } // namespace fon9 49 | #endif//__fon9_ThreadTools_hpp__ 50 | -------------------------------------------------------------------------------- /fon9/Tools.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/Tools.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_Tools_hpp__ 4 | #define __fon9_Tools_hpp__ 5 | #include "fon9/Outcome.hpp" 6 | #include "fon9/StrView.hpp" 7 | 8 | namespace fon9 { 9 | 10 | enum class HowWait { 11 | Unknown, 12 | Block, 13 | Yield, 14 | Busy, 15 | }; 16 | inline bool IsBlockWait(HowWait value) { 17 | return value <= HowWait::Block; 18 | } 19 | fon9_API HowWait StrToHowWait(StrView value); 20 | fon9_API StrView HowWaitToStr(HowWait value); 21 | 22 | /// \ingroup Misc 23 | /// 設定「現在 thread」的 CPU 綁定. 24 | /// \retval Result3::kNoResult() cpuAffinity < 0: 不綁定. 25 | /// \retval Result3::kSuccess() cpuAffinity >=0: 綁定成功. 26 | /// \retval retval.IsError() 綁定失敗原因. 27 | fon9_API Result3 SetCpuAffinity(int cpuAffinity); 28 | 29 | /// \ingroup Misc 30 | /// 將 big5 字串轉成 utf8. 31 | /// 轉換後 outbuf 尾端不包含 EOS. 32 | fon9_API size_t Big5ToUtf8NoEOS(StrView strBig5, char* outbuf, size_t outbufsz); 33 | /// \ingroup Misc 34 | /// 將 big5 字串轉成 utf8. 35 | /// 轉換後 outbuf 尾端如果還有空間, 則會填入一個 EOS. 36 | inline size_t Big5ToUtf8EOS(const StrView& strBig5, char* outbuf, size_t outbufsz) { 37 | size_t retval = Big5ToUtf8NoEOS(strBig5, outbuf, outbufsz); 38 | if (retval < outbufsz) 39 | outbuf[retval] = '\0'; 40 | return retval; 41 | } 42 | 43 | } // namespace 44 | #endif//__fon9_Tools_hpp__ 45 | -------------------------------------------------------------------------------- /fon9/TsAppend.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/TsAppend.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/TsAppend.hpp" 4 | #include "fon9/BitvFixedInt.hpp" 5 | 6 | namespace fon9 { 7 | 8 | fon9_API void TsAppend(AsyncFileAppender& pklog, TimeStamp now, 9 | const void* pkptr, uint16_t pksz) { 10 | size_t kSaveSize = pksz + sizeof(now) + sizeof(pksz); 11 | RevBufferNode* rbuf{RevBufferNode::Alloc(kSaveSize)}; 12 | fon9::byte* pbuf = rbuf->GetDataBegin() - kSaveSize; 13 | rbuf->SetPrefixUsed(pbuf); 14 | *pbuf = fon9_BitvT_TimeStamp_Orig7; // 0xe0 15 | ToBitvFixedRev(reinterpret_cast(pbuf) + sizeof(now), now.GetOrigValue()); 16 | PutBigEndian(pbuf + sizeof(now), pksz); 17 | memcpy(pbuf + sizeof(now) + sizeof(pksz), pkptr, pksz); 18 | pklog.Append(rbuf); 19 | } 20 | 21 | } // namespaces 22 | -------------------------------------------------------------------------------- /fon9/TsAppend.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/TsAppend.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_TsAppend_hpp__ 4 | #define __fon9_TsAppend_hpp__ 5 | #include "fon9/FileAppender.hpp" 6 | #include "fon9/TimeStamp.hpp" 7 | 8 | namespace fon9 { 9 | 10 | /// 將 pkptr 加入 pklog 尾端, 格式如下: 11 | /// - 0xe0 (fon9_BitvT_TimeStamp_Orig7) 12 | /// - 收到封包的時間: EpochTime(UTC).us: 7 bytes, BigEndian 13 | /// - 封包大小 pksz: 2 bytes, BigEndian 14 | /// - 封包內容 pkptr; 15 | fon9_API void TsAppend(AsyncFileAppender& pklog, TimeStamp now, 16 | const void* pkptr, uint16_t pksz); 17 | 18 | } // namespaces 19 | #endif//__fon9_TsAppend_hpp__ 20 | -------------------------------------------------------------------------------- /fon9/TsReceiver.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/TsReceiver.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/TsReceiver.hpp" 4 | #include "fon9/BitvDecode.hpp" 5 | 6 | namespace fon9 { 7 | 8 | TsReceiver::~TsReceiver() { 9 | } 10 | bool TsReceiver::FeedBuffer(DcQueue& rxbuf) { 11 | char peekbuf[0x10000]; 12 | PkszT pksz; 13 | TimeStamp pktm; 14 | while (auto pkptr = static_cast(rxbuf.Peek(peekbuf, kHeadSize))) { 15 | if (fon9_UNLIKELY(*pkptr != fon9_BitvT_TimeStamp_Orig7)) 16 | rxbuf.PopUnknownChar(fon9_BitvT_TimeStamp_Orig7); 17 | else { 18 | pktm.SetOrigValue(GetPackedBigEndian(pkptr + 1, sizeof(pktm) - 1)); 19 | pksz = GetBigEndian(pkptr + sizeof(pktm)); 20 | pkptr = static_cast(rxbuf.Peek(peekbuf, pksz + kHeadSize)); 21 | if (fon9_UNLIKELY(pkptr == nullptr)) // rxbuf 資料不足. 22 | break; 23 | bool isCont = this->OnPkReceived(pktm, pkptr + kHeadSize, pksz); 24 | rxbuf.PopConsumed(pksz + kHeadSize); 25 | if (!isCont) 26 | return false; 27 | } 28 | } 29 | return true; 30 | } 31 | 32 | } // namespaces 33 | -------------------------------------------------------------------------------- /fon9/TsReceiver.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/TsReceiver.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_TsReceiver_hpp__ 4 | #define __fon9_TsReceiver_hpp__ 5 | #include "fon9/buffer/DcQueue.hpp" 6 | #include "fon9/TimeStamp.hpp" 7 | 8 | namespace fon9 { 9 | 10 | /// \ingroup Misc. 11 | /// 用來解析使用 TsAppend 寫入的封包. 12 | class fon9_API TsReceiver { 13 | fon9_NON_COPY_NON_MOVE(TsReceiver); 14 | 15 | public: 16 | using PkszT = uint16_t; 17 | enum : size_t { 18 | kHeadSize = sizeof(TimeStamp) + sizeof(PkszT) 19 | }; 20 | 21 | TsReceiver() = default; 22 | virtual ~TsReceiver(); 23 | 24 | /// 收到的訊息透過這裡處理. 25 | /// - 返回時機: rxbuf 用完, 或 rxbuf 剩餘資料不足一個封包. 26 | /// 27 | /// \retval false 呼叫 OnPkReceived() 時返回 false, 中斷 FeedBuffer(); 28 | /// \retval true rxbuf 資料不足, 或已解析完畢. 29 | bool FeedBuffer(DcQueue& rxbuf); 30 | 31 | protected: 32 | /// 當收到封包時透過這裡通知衍生者. 33 | /// static_cast(pk) - kHeadSize 必定為 head + pk 的內容. 34 | /// 35 | /// \retval false 結束 FeedBuffer(); 36 | /// \retval true 繼續 FeedBuffer(); 37 | virtual bool OnPkReceived(TimeStamp pktm, const void* pk, PkszT pksz) = 0; 38 | }; 39 | 40 | } // namespaces 41 | #endif//__fon9_TsReceiver_hpp__ 42 | -------------------------------------------------------------------------------- /fon9/Unaligned.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/Unaligned.hpp 2 | /// 3 | /// 存取沒有[記憶體對齊]的資料. 4 | /// 5 | /// - 直接存取沒有[記憶體對齊]的資料, 某些CPU可能會 Bus error, 6 | /// 所以使用 fon9::GetUnaligned(); fon9::PutUnaligned(); 支援這類情形. 7 | /// - 直接使用 memcpy()? 因為較新的 compiler 都能最佳化 memcpy(dst,src,固定大小); 8 | /// 但是如果是 non-POD? 用 memcpy() 是否會有副作用? 9 | /// 10 | /// \author fonwinz@gmail.com 11 | #ifndef __fon9_Unaligned_hpp__ 12 | #define __fon9_Unaligned_hpp__ 13 | #include 14 | 15 | namespace fon9 { 16 | 17 | #if defined(_MSC_VER) && defined(_WIN64) 18 | template 19 | static inline T GetUnaligned(const T __unaligned* address) { 20 | return *address; 21 | } 22 | template 23 | static inline void PutUnaligned(T __unaligned* address, T value) { 24 | *address = value; 25 | } 26 | #else 27 | template 28 | static inline T GetUnaligned(const T* address) { 29 | T v; 30 | memcpy(&v, address, sizeof(T)); 31 | return v; 32 | } 33 | template 34 | static inline void PutUnaligned(T* address, T value) { 35 | memcpy(address, &value, sizeof(value)); 36 | } 37 | #endif 38 | 39 | } // namespace 40 | #endif//__fon9_Unaligned_hpp__ 41 | -------------------------------------------------------------------------------- /fon9/auth/PolicyAgent.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/auth/PolicyAgent.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_auth_PolicyAgent_hpp__ 4 | #define __fon9_auth_PolicyAgent_hpp__ 5 | #include "fon9/auth/PolicyTree.hpp" 6 | #include "fon9/seed/MaTree.hpp" 7 | 8 | namespace fon9 { namespace auth { 9 | 10 | class fon9_API PolicyAgent : public seed::NamedSapling { 11 | fon9_NON_COPY_NON_MOVE(PolicyAgent); 12 | using base = seed::NamedSapling; 13 | 14 | public: 15 | template 16 | PolicyAgent(PolicyTreeSP sapling, NamedSeedArgsT&&... namedSeedArgs) 17 | : base(std::move(sapling), std::forward(namedSeedArgs)...) { 18 | } 19 | 20 | bool LinkStorage(const InnDbfSP& storage, InnRoomSize minRoomSize) { 21 | if (storage) 22 | return storage->LinkTable(&this->Name_, *static_cast(this->Sapling_.get()), minRoomSize); 23 | return false; 24 | } 25 | }; 26 | 27 | } } // namespaces 28 | #endif//__fon9_auth_PolicyAgent_hpp__ 29 | -------------------------------------------------------------------------------- /fon9/auth/PolicyMaster.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/auth/PolicyMaster.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/auth/PolicyMaster.hpp" 4 | 5 | namespace fon9 { namespace auth { 6 | 7 | MasterPolicyItem::MasterPolicyItem(const StrView& policyId, MasterPolicyTreeSP owner) 8 | : base{policyId} 9 | , OwnerMasterTree_{std::move(owner)} { 10 | } 11 | seed::TreeSP MasterPolicyItem::GetSapling() { 12 | return this->DetailSapling_; 13 | } 14 | void MasterPolicyItem::SetRemoved(PolicyTable&) { 15 | this->DetailSapling_.reset(); 16 | } 17 | 18 | } } // namespaces 19 | -------------------------------------------------------------------------------- /fon9/auth/PolicyTree.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/PolicyTree.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_auth_PolicyTree_hpp__ 4 | #define __fon9_auth_PolicyTree_hpp__ 5 | #include "fon9/auth/PolicyTable.hpp" 6 | #include "fon9/seed/Tree.hpp" 7 | 8 | namespace fon9 { namespace auth { 9 | 10 | class fon9_API PolicyTree : public seed::Tree, public PolicyTable { 11 | fon9_NON_COPY_NON_MOVE(PolicyTree); 12 | using base = seed::Tree; 13 | struct PodOp; 14 | struct TreeOp; 15 | 16 | public: 17 | using base::base; 18 | 19 | /// 預設使用底下 Layout1 建構: 20 | /// - KeyField = seed::FieldCharVector(keyName) 21 | /// - Tab = {tabName, fields} 22 | /// - 若上述 Layout 不符, 您也可以直接使用 seed::Tree 的建構參數. 23 | PolicyTree(std::string tabName, std::string keyName, seed::Fields&& fields, 24 | seed::TabFlag tabFlags = seed::TabFlag::Writable | seed::TabFlag::NoSapling); 25 | 26 | virtual void OnTreeOp(seed::FnTreeOp fnCallback) override; 27 | virtual void OnParentSeedClear() override; 28 | }; 29 | using PolicyTreeSP = seed::TreeSPT; 30 | 31 | } } // namespaces 32 | #endif//__fon9_auth_PolicyTree_hpp__ 33 | -------------------------------------------------------------------------------- /fon9/auth/RoleMgr.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/auth/RoleMgr.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_auth_RoleMgr_hpp__ 4 | #define __fon9_auth_RoleMgr_hpp__ 5 | #include "fon9/auth/PolicyAgent.hpp" 6 | 7 | namespace fon9 { namespace auth { 8 | 9 | /// \ingroup auth 10 | /// 使用者 **角色** 管理員. 11 | /// - 透過 RoleId 取得各個 Policy 的設定. 12 | /// - RoleMgr 是一種特殊的 Policy Agent, 由 AuthMgr 在建構時主動加入. 13 | /// - 每個 RoleItem 包含一個 PolicyKeys; 14 | class fon9_API RoleMgr : public PolicyAgent { 15 | fon9_NON_COPY_NON_MOVE(RoleMgr); 16 | using base = PolicyAgent; 17 | 18 | public: 19 | RoleMgr(std::string name); 20 | 21 | enum GetRoleMode { 22 | /// 清除 res.PolicyKeys_, 取得新的設定; 23 | GetRoleMode_Renew, 24 | /// 保留 res.PolicyKeys_, 增加 res.PolicyKeys_ 不存在的設定; 25 | GetRoleMode_Append, 26 | /// 保留 res.PolicyKeys_, 新的 Policy 若已存在則取代, 若不存在則新增; 27 | GetRoleMode_Replace, 28 | }; 29 | bool GetRole(StrView roleId, RoleConfig& res, GetRoleMode mode); 30 | 31 | bool LinkStorage(const InnDbfSP& storage) { 32 | return base::LinkStorage(storage, 128); 33 | } 34 | }; 35 | 36 | } } // namespaces 37 | #endif//__fon9_auth_RoleMgr_hpp__ 38 | -------------------------------------------------------------------------------- /fon9/auth/SaslScramSha256.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/auth/SaslScramSha256.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/auth/SaslScramSha256.hpp" 4 | 5 | namespace fon9 { namespace auth { 6 | 7 | } } // namespaces 8 | -------------------------------------------------------------------------------- /fon9/auth/SaslScramSha256.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/auth/SaslScramSha256.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_auth_SaslScramSha256_hpp__ 4 | #define __fon9_auth_SaslScramSha256_hpp__ 5 | #include "fon9/crypto/Sha256.hpp" 6 | #include "fon9/auth/SaslScram.hpp" 7 | 8 | namespace fon9 { namespace auth { 9 | 10 | fon9_API_TEMPLATE_CLASS(SaslScramSha256, SaslScram, crypto::Sha256); 11 | 12 | } } // namespaces 13 | #endif//__fon9_auth_SaslScramSha256_hpp__ 14 | -------------------------------------------------------------------------------- /fon9/auth/SaslScramSha256Client.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/auth/SaslScramSha256Client.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_auth_SaslScramSha256Client_hpp__ 4 | #define __fon9_auth_SaslScramSha256Client_hpp__ 5 | #include "fon9/auth/SaslClient.hpp" 6 | 7 | namespace fon9 { namespace auth { 8 | 9 | fon9_API SaslClientSP SaslScramSha256ClientCreator(const StrView& authz, const StrView& authc, const StrView& pass); 10 | fon9_API SaslClientSP SaslScramSha256ClientCreator_ChgPass(const StrView& authz, const StrView& authc, const StrView& oldPass, const StrView& newPass); 11 | 12 | } } // namespaces 13 | #endif//__fon9_auth_SaslScramSha256Client_hpp__ 14 | -------------------------------------------------------------------------------- /fon9/auth/SaslScramSha256Server.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/auth/SaslScramSha256Server.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/auth/SaslScramSha256Server.hpp" 4 | 5 | namespace fon9 { namespace auth { 6 | 7 | class AA_SCRAM_SHA_256 : public AuthAgent { 8 | fon9_NON_COPY_NON_MOVE(AA_SCRAM_SHA_256); 9 | using base = AuthAgent; 10 | public: 11 | UserMgrSP UserMgr_; 12 | AA_SCRAM_SHA_256(const seed::MaTreeSP& /*maTree*/, std::string name, UserMgrSP userMgr) 13 | : base{std::move(name)} 14 | , UserMgr_{std::move(userMgr)} { 15 | } 16 | AuthSessionSP CreateAuthSession(AuthMgrSP authMgr, FnOnAuthVerifyCB cb) override { 17 | return new AuthSession_SaslScramSha256(authMgr, std::move(cb), this->UserMgr_); 18 | } 19 | }; 20 | 21 | fon9_API UserMgrSP PlantScramSha256(AuthMgr& authMgr) { 22 | if (UserMgrSP userMgr = UserMgr::Plant(authMgr, "UserSha256", &PassRec::HashPass)) { 23 | if (authMgr.Agents_->Plant("AA_SCRAM_SHA_256.Plant", "AA_SCRAM_SHA_256", userMgr)) 24 | return userMgr; 25 | authMgr.Agents_->Remove(&userMgr->Name_); 26 | } 27 | return nullptr; 28 | } 29 | 30 | } } // namespaces 31 | -------------------------------------------------------------------------------- /fon9/buffer/BufferNode.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/buffer/BufferNode.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/buffer/BufferNode.hpp" 4 | 5 | namespace fon9 { 6 | 7 | BufferNodeVirtual::~BufferNodeVirtual() { 8 | } 9 | 10 | fon9_API void FreeNode(BufferNode* node) { 11 | switch (node->GetNodeType()) { 12 | case BufferNodeType::Data: 13 | break; 14 | case BufferNodeType::Virtual: 15 | BufferNodeVirtual* vnode = static_cast(node); 16 | auto blksz = vnode->BlockSize_; 17 | vnode->~BufferNodeVirtual(); 18 | // 有 vtbl, 所以 free 的對象必須是: vnode (而不是 node); (void*)node 不一定與 (void*)vnode 相等. 19 | MemBlock::FreeBlock(vnode, blksz); 20 | return; 21 | } 22 | MemBlock::FreeBlock(node, node->BlockSize_); 23 | } 24 | 25 | } // namespaces 26 | -------------------------------------------------------------------------------- /fon9/buffer/BufferNodeWaiter.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/BufferNodeWaiter.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/buffer/BufferNodeWaiter.hpp" 4 | 5 | namespace fon9 { 6 | 7 | BufferNodeWaiter::~BufferNodeWaiter() { 8 | } 9 | BufferNodeWaiter* BufferNodeWaiter::Alloc(CountDownLatch& waiter) { 10 | BufferNodeWaiter* res = base::Alloc(0, StyleFlag::AllowCrossing); 11 | res->Waiter_ = &waiter; 12 | return res; 13 | } 14 | void BufferNodeWaiter::OnBufferConsumed() { 15 | this->Waiter_->CountDown(); 16 | } 17 | void BufferNodeWaiter::OnBufferConsumedErr(const ErrC&) { 18 | this->Waiter_->CountDown(); 19 | } 20 | 21 | } // namespaces 22 | -------------------------------------------------------------------------------- /fon9/buffer/RevBuffer.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/buffer/RevBuffer.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/buffer/RevBuffer.hpp" 4 | 5 | namespace fon9 { 6 | 7 | void RevBuffer::ForVtblInLib() { 8 | } 9 | char* RevBufferFixedMem::OnRevBufferAlloc(size_t) { 10 | Raise("RevBufferFixedMem overflow"); 11 | } 12 | 13 | } // namespace 14 | -------------------------------------------------------------------------------- /fon9/buffer/RevBufferList.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/buffer/RevBufferList.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/buffer/RevBufferList.hpp" 4 | 5 | namespace fon9 { 6 | 7 | char* RevBufferList::OnRevBufferAlloc(size_t sz) { 8 | this->SetFrontNodeUsed(); 9 | this->ResetMemPtr(this->Builder_.NewFront(sz)); 10 | return this->MemCurrent_; 11 | } 12 | 13 | } // namespace 14 | -------------------------------------------------------------------------------- /fon9/fix/FixBase.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fix/FixBase.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fix/FixBase.hpp" 4 | 5 | namespace fon9 { namespace fix { 6 | 7 | } } // namespaces 8 | -------------------------------------------------------------------------------- /fon9/fix/FixConfig.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fix/FixConfig.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fix/FixConfig.hpp" 4 | 5 | namespace fon9 { namespace fix { 6 | 7 | const FixMsgTypeConfig* FixConfig::Get(StrView msgType) const { 8 | if (fon9_LIKELY(msgType.size() == 1)) { 9 | int idx = Alpha2Seq(*msgType.begin()); 10 | if (0 <= idx && idx < static_cast(numofele(this->Configs_))) 11 | return &this->Configs_[idx]; 12 | } 13 | ConfigMap::const_iterator ifind = this->ConfigMap_.find(CharVector::MakeRef(msgType)); 14 | return(ifind == this->ConfigMap_.end() ? nullptr : &ifind->second); 15 | } 16 | FixMsgTypeConfig& FixConfig::Fetch(StrView msgType) { 17 | if (fon9_LIKELY(msgType.size() == 1)) { 18 | int idx = Alpha2Seq(*msgType.begin()); 19 | if (0 <= idx && idx < static_cast(numofele(this->Configs_))) 20 | return this->Configs_[idx]; 21 | } 22 | return this->ConfigMap_.kfetch(CharVector{msgType}).second; 23 | } 24 | 25 | } } // namespaces 26 | -------------------------------------------------------------------------------- /fon9/fix/IoFixSender.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fix/IoFixSender.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fix/IoFixSender.hpp" 4 | 5 | namespace fon9 { namespace fix { 6 | 7 | IoFixSender::~IoFixSender() { 8 | } 9 | void IoFixSender::OnSendFixMessage(const Locker& lk, BufferList buf) { 10 | assert(lk.owns_lock()); (void)lk;// FixRecorder 仍在鎖定狀態! 11 | if (io::Device* dev = this->Device_.get()) { 12 | // 使用 SendASAP() 一定會 low latency 嗎? 13 | // 因為會立即呼叫 send() or WSASend(), 可能會花不少時間. 14 | // - 這段時間如果可以處理 n 筆 Request 15 | // - 且瞬間有多筆要求在等著處理 16 | // - 那這些等待中的 Request, latency 就會變很高了! 17 | 18 | //dev->SendASAP(std::move(buf)); // for low latency? 19 | //dev->SendBuffered(std::move(buf)); // for high throughput? 20 | // 由 dev 的 property 決定是否 ASAP. 21 | dev->Send(std::move(buf)); 22 | } 23 | } 24 | 25 | } } // namespaces 26 | -------------------------------------------------------------------------------- /fon9/fix/IoFixSender.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/fix/IoFixSender.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_fix_IoFixSender_hpp__ 4 | #define __fon9_fix_IoFixSender_hpp__ 5 | #include "fon9/fix/FixSender.hpp" 6 | #include "fon9/io/Device.hpp" 7 | 8 | namespace fon9 { namespace fix { 9 | 10 | /// \ingroup fix 11 | /// 使用 fon9::io::Device 輸出 FIX 訊息. 12 | class fon9_API IoFixSender : public FixSender { 13 | fon9_NON_COPY_NON_MOVE(IoFixSender); 14 | using base = FixSender; 15 | 16 | io::DeviceSP Device_; 17 | 18 | void OnSendFixMessage(const Locker&, BufferList buf) override; 19 | 20 | void SwapDevice(io::DeviceSP& dev) { 21 | Locker lk{this->Lock()}; 22 | this->Device_.swap(dev); 23 | } 24 | 25 | public: 26 | using base::base; 27 | ~IoFixSender(); 28 | 29 | void OnFixSessionDisconnected() { 30 | io::DeviceSP dev; 31 | this->SwapDevice(dev); 32 | } 33 | void OnFixSessionConnected(io::DeviceSP dev) { 34 | this->SwapDevice(dev); 35 | } 36 | io::DeviceSP GetDevice() const { 37 | return this->Device_; 38 | } 39 | }; 40 | using IoFixSenderSP = intrusive_ptr; 41 | 42 | } } // namespaces 43 | #endif//__fon9_fix_IoFixSender_hpp__ 44 | -------------------------------------------------------------------------------- /fon9/fix/README.md: -------------------------------------------------------------------------------- 1 | fon9 FIX engine 2 | =============== 3 | 4 | ## 基本說明 5 | * 僅支援 FIX 4.2 及 4.4 6 | 7 | ## 基礎元件 8 | * 提供 FIX Message 的解析: `fon9::fix::FixParser` 9 | * FIX Message 打包: `fon9::fix::FixBuilder` 10 | * 將欄位直接填入輸出緩衝區, 不提供將「欄位列表」打包成 FIX Message 的功能。 11 | * `fon9::fix::FixBuilder` 填妥大部分「交易內容」相關的欄位, 12 | 其他與 FIX 協定相關的欄位(例如: CompID、BeginString), 則留給 `fon9::fix::FixSender` 處理。 13 | * 提供 Session 收送訊息記錄、狀態記錄: `fon9::fix::FixRecorder` 14 | * 取回之前送過的資料: `fon9::fix::FixRecorder::ReloadSent` 15 | * `fon9::fix::FixSender` 16 | * 完成完整的 FIX 訊息: 17 | * 填入 CompIDs 18 | * 填入 SendingTime 19 | * 填入 MsgSeqNum 20 | * 填入 MsgType 21 | * 填入 BodyLength、BeginString 22 | * 填入 CheckSum 23 | * 提供 SequenceReset 24 | * 提供 Replay 25 | * 訊息接收流程, Logon 必須是第一個訊息: 26 | * Acceptor 27 | * Device.LinkReady 28 | * Recv Logon 29 | * 檢查認證訊息 30 | * 用 Logon 提供的資訊取得 FixRecorder 31 | * 開始 FIX 訊息交換 32 | * Initiator 33 | * Device.LinkReady 34 | * 取得 FixRecorder 35 | * Send Logon 36 | * Recv Logon 37 | * 開始 FIX 訊息交換 38 | * 由於 Acceptor 必須在確認 Logon 之後才能取得正確的 FixRecorder, 39 | 所以 Logon 訊息必須由 FixSession 自行處理. 40 | * 在進入 FIX 訊息交換階段, 才將收到的訊息(包含 Logon) 41 | * 交給 `fon9::fix::FixReceiver` 去確保序號的連續. 42 | * 確定連續的訊息, 再透過 FixMsgTypeConfig.FixMsgHandler_ 接力處理. 43 | 44 | -------------------------------------------------------------------------------- /fon9/fmkt/FmdRtsPackType.txt: -------------------------------------------------------------------------------- 1 | 2020/08/10 2 | - 在 [買賣報價、成交明細] 增加 MktSeq 欄位,在多資訊源的環境,用來過濾重複(過時)資訊: 3 | - 成交封包, 仍要提供 MktSeq, 因為試算成交的 TotalQty 為 0, 所以不能只用 TotalQty 判斷是否為舊封包. 4 | 5 | - 目前情況: 6 | 只有 Deal, BS 需要 MktSeq, 其餘現有資料都不需要 MktSeq, 在可見的未來不會有改變. 7 | f9sv_RtsPackType_DealPack, 8 | f9sv_RtsPackType_DealBS, 9 | f9sv_RtsPackType_SnapshotBS, 10 | f9sv_RtsPackType_CalculatedBS, 11 | f9sv_RtsPackType_UpdateBS, 12 | 13 | - 方法1. 在 enum f9sv_RtsPackType 增加一個 f9sv_RtsPackType_MktSeq; 14 | /// - MktSeq(Bitv) (應更新 BS.MktSeq 欄位) 15 | /// - MktSeq 之後, 接著後續的 RtsPackType 及其內容. 16 | /// - 僅在 Server 有提供 BS.MktSeq 欄位時才會有此封包. 17 | /// - 用在多資訊來源時, 判斷是否為重複資料. 18 | 19 | - 方法2. 在原本的封包增加 MktSeq(Bitv) 內容(如果有 BS.MktSeq 欄位) 20 | 21 | - 考量: 22 | - [方法1]在回補時, 會難以判斷 InfoTime? 23 | - f9sv_RtsPackType_MktSeq + InfoTime + MktSeq + [後續封包(不含InfoTime)]. 24 | - [後續封包]解析要排除 InfoTime. 25 | - 依然要改動到[後續封包]解析程序? 26 | - 可將[後續封包]的InfoTime設為Null,就不會動到[後續封包]解析程序了. 27 | - [方法1]資料量會比[方法2]多 2 bytes: (PkType=f9sv_RtsPackType_MktSeq) + (MktSeq) + (後續封包:InfoTime=Null) 28 | - 會用到 MktSeq 的環境,通常API端會接收[交易所行情],用來過濾重複資訊,此時 2 bytes 是否有那麼嚴重? 29 | - 使用[方法1]的未來擴充性較佳. 30 | - 未來還有需要 MktSeq 的訊息需要擴充嗎? 31 | - 不論選擇哪種方式,打包端都必須修改。 32 | - 方法1: 解包端較單純。 33 | - 方法2: 每個提供 MktSeq 的封包都解要調整。 34 | 35 | - 最後決定: 使用[方法2.] 36 | - 依目前情況來看, 現有 enum f9sv_RtsPackType; 已確定了要修改的內容, 以後的變動不大. 37 | - 所以直接修改[打包及解包]比較單純. 38 | -------------------------------------------------------------------------------- /fon9/fmkt/README.md: -------------------------------------------------------------------------------- 1 | fon9 financial market 2 | ===================== 3 | 4 | ## 基本說明 5 | * 金融市場擴充模組 6 | * 基本行情 7 | * 下單基底: Server/Client 共用的部分 8 | 9 | ## 基礎元件 10 | * Symb、SymbTree 11 | 12 | ## 基本行情 13 | * SymbRef、SymbBS、SymbDeal 14 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbBS.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbBS.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_SymbBS_hpp__ 4 | #define __fon9_fmkt_SymbBS_hpp__ 5 | #include "fon9/fmkt/SymbDy.hpp" 6 | #include "fon9/fmkt/SymbBSData.hpp" 7 | 8 | namespace fon9 { namespace fmkt { 9 | 10 | /// \ingroup fmkt 11 | /// 商品資料的擴充: 行情的買賣報價. 12 | fon9_API_TEMPLATE_CLASS(SymbTwsBS, SimpleSymbData, SymbTwsBSData); 13 | fon9_API_TEMPLATE_CLASS(SymbTwfBS, SimpleSymbData, SymbTwfBSData); 14 | 15 | /// 不包含「衍生買賣」, 包含 LmtFlags. 16 | fon9_API seed::Fields SymbTwsBS_MakeFields(bool isAddMarketSeq); 17 | /// 包含「衍生買賣」, 不包含 LmtFlags. 18 | fon9_API seed::Fields SymbTwfBS_MakeFields(bool isAddMarketSeq, bool isAddChannelSeq); 19 | 20 | using SymbTwaBS = SymbTwfBS; 21 | fon9_API seed::Fields SymbTwaBS_MakeFields(bool isAddMarketSeq); 22 | 23 | class fon9_API SymbBSTabDy : public SymbDataTab { 24 | fon9_NON_COPY_NON_MOVE(SymbBSTabDy); 25 | using base = SymbDataTab; 26 | public: 27 | SymbBSTabDy(Named&& named, bool isAddMarketSeq = true) 28 | : base{std::move(named), SymbTwaBS_MakeFields(isAddMarketSeq), seed::TabFlag::NoSapling_NoSeedCommand_Writable} { 29 | } 30 | 31 | SymbDataSP FetchSymbData(Symb&) override; 32 | }; 33 | 34 | } } // namespaces 35 | #endif//__fon9_fmkt_SymbBS_hpp__ 36 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbBreakSt.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbBreakSt.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbBreakSt.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | seed::Fields SymbBreakSt_MakeFieldsTws() { 9 | seed::Fields flds; 10 | flds.Add(fon9_MakeField(SymbBreakSt, Data_.BreakHHMMSS_, "BreakTime")); 11 | flds.Add(fon9_MakeField(SymbBreakSt, Data_.RestartHHMMSS_, "RestartTime")); 12 | return flds; 13 | } 14 | 15 | seed::Fields SymbBreakSt_MakeFieldsTwf() { 16 | seed::Fields flds = SymbBreakSt_MakeFieldsTws(); 17 | flds.Add(fon9_MakeField(SymbBreakSt, Data_.ReopenHHMMSS_, "ReopenTime")); 18 | flds.Add(fon9_MakeField(SymbBreakSt, Data_.Reason_, "Reason")); 19 | return flds; 20 | } 21 | 22 | } } // namespaces 23 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbDy.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbDy.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbDy.hpp" 4 | 5 | namespace fon9 { namespace fmkt { 6 | 7 | SymbDy::SymbDy(SymbDyTreeSP symbTreeSP, const StrView& symbid) : base{symbid}, SymbTreeSP_{std::move(symbTreeSP)} { 8 | } 9 | SymbData* SymbDy::GetSymbData(int tabid) { 10 | if (tabid <= 0) 11 | return this; 12 | ExDatas::Locker lk{this->ExDatas_}; 13 | return (static_cast(tabid) <= lk->size() ? (*lk)[static_cast(tabid - 1)].get() : nullptr); 14 | } 15 | SymbData* SymbDy::FetchSymbData(int tabid) { 16 | if (tabid <= 0) 17 | return this; 18 | SymbDataTab* tab = dynamic_cast(this->SymbTreeSP_->LayoutSP_->GetTab(static_cast(tabid))); 19 | if (tab == nullptr) 20 | return nullptr; 21 | ExDatas::Locker lk{this->ExDatas_}; 22 | if (lk->size() < static_cast(tabid)) 23 | lk->resize(static_cast(tabid)); 24 | if (SymbData* dat = (*lk)[static_cast(tabid - 1)].get()) 25 | return dat; 26 | return ((*lk)[static_cast(tabid - 1)] = tab->FetchSymbData(*this)).get(); 27 | } 28 | 29 | //--------------------------------------------------------------------------// 30 | 31 | SymbSP SymbDyTree::MakeSymb(const StrView& symbid) { 32 | return SymbSP{new SymbDy(this, symbid)}; 33 | } 34 | 35 | } } // namespaces 36 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbDynBand.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbDynBand.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbDynBand.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | seed::Fields SymbDynBand_MakeFields() { 9 | seed::Fields flds; 10 | flds.Add(fon9_MakeField(SymbDynBand, Data_.DynBandSt_, "St")); 11 | flds.Add(fon9_MakeField(SymbDynBand, Data_.StHHMMSS_, "Time")); 12 | flds.Add(fon9_MakeField(SymbDynBand, Data_.Reason_, "Reason")); 13 | flds.Add(fon9_MakeField(SymbDynBand, Data_.SideType_, "SideType")); 14 | flds.Add(fon9_MakeField(SymbDynBand, Data_.RangeL_, "RangeL")); 15 | flds.Add(fon9_MakeField(SymbDynBand, Data_.RangeS_, "RangeS")); 16 | return flds; 17 | } 18 | 19 | } } // namespaces 20 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbFuoClosing.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbFuoClosing.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbFuoClosing.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | fon9_API seed::Fields SymbFuoClosing_MakeFields() { 9 | seed::Fields flds; 10 | flds.Add(fon9_MakeField(SymbFuoClosing, Data_.PriSettlement_, "PriSettlement")); 11 | return flds; 12 | } 13 | 14 | } } // namespaces 15 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbFuoClosing.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbFuoClosing.hpp 2 | // 3 | // 期權商品收盤後相關資訊, 例如: 結算價; 4 | // 5 | // \author fonwinz@gmail.com 6 | #ifndef __fon9_fmkt_SymbFuoClosing_hpp__ 7 | #define __fon9_fmkt_SymbFuoClosing_hpp__ 8 | #include "fon9/fmkt/Symb.hpp" 9 | #include "fon9/fmkt/FmktTypes.hpp" 10 | 11 | namespace fon9 { namespace fmkt { 12 | 13 | struct SymbFuoClosing_Data { 14 | /// 結算價 15 | Pri PriSettlement_{Pri::Null()}; 16 | 17 | void Clear() { 18 | this->PriSettlement_.AssignNull(); 19 | } 20 | bool operator==(const SymbFuoClosing_Data& rhs) const { 21 | return this->PriSettlement_ == rhs.PriSettlement_; 22 | } 23 | bool operator!=(const SymbFuoClosing_Data& rhs) const { 24 | return !this->operator==(rhs); 25 | } 26 | }; 27 | 28 | /// \ingroup fmkt 29 | /// 商品資料的擴充: 期權商品收盤後相關資訊. 30 | fon9_API_TEMPLATE_CLASS(SymbFuoClosing, SimpleSymbData, SymbFuoClosing_Data); 31 | 32 | fon9_API seed::Fields SymbFuoClosing_MakeFields(); 33 | 34 | } } // namespaces 35 | #endif//__fon9_fmkt_SymbFuoClosing_hpp__ 36 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbQuoteReq.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbQuoteReq.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbQuoteReq.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | seed::Fields SymbQuoteReq_MakeFields() { 9 | seed::Fields flds; 10 | flds.Add(fon9_MakeField(SymbQuoteReq, Data_.DisclosureTime_, "Time")); 11 | flds.Add(fon9_MakeField(SymbQuoteReq, Data_.DurationSeconds_, "DurSecs")); 12 | return flds; 13 | } 14 | 15 | } } // namespaces 16 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbQuoteReq.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbQuoteReq.hpp 2 | // 3 | // 商品詢價要求 相關欄位. 4 | // 5 | // \author fonwinz@gmail.com 6 | #ifndef __fon9_fmkt_SymbQuoteReq_hpp__ 7 | #define __fon9_fmkt_SymbQuoteReq_hpp__ 8 | #include "fon9/fmkt/Symb.hpp" 9 | #include "fon9/TimeInterval.hpp" 10 | 11 | namespace fon9 { namespace fmkt { 12 | 13 | struct SymbQuoteReq_Data { 14 | /// 詢價揭示時間. 15 | DayTime DisclosureTime_{DayTime::Null()}; 16 | /// 詢價持續時間. 17 | uint16_t DurationSeconds_{}; 18 | char Padding___[6]; 19 | 20 | void Clear() { 21 | this->DisclosureTime_.AssignNull(); 22 | this->DurationSeconds_ = 0; 23 | } 24 | bool operator==(const SymbQuoteReq_Data& rhs) const { 25 | return this->DisclosureTime_ == rhs.DisclosureTime_ 26 | && this->DurationSeconds_ == rhs.DurationSeconds_; 27 | } 28 | bool operator!=(const SymbQuoteReq_Data& rhs) const { 29 | return !this->operator==(rhs); 30 | } 31 | }; 32 | 33 | /// \ingroup fmkt 34 | /// 商品資料的擴充: 詢價要求. 35 | fon9_API_TEMPLATE_CLASS(SymbQuoteReq, SimpleSymbData, SymbQuoteReq_Data); 36 | 37 | fon9_API seed::Fields SymbQuoteReq_MakeFields(); 38 | 39 | } } // namespaces 40 | #endif//__fon9_fmkt_SymbQuoteReq_hpp__ 41 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbRef.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbRef.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbRef.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | seed::Fields SymbRef_MakeFields() { 9 | seed::Fields flds; 10 | flds.Add(fon9_MakeField(SymbRef, Data_.PriRef_, "PriRef")); 11 | flds.Add(fon9_MakeField(SymbRef, Data_.PriUpLmt_, "PriUpLmt")); 12 | flds.Add(fon9_MakeField(SymbRef, Data_.PriDnLmt_, "PriDnLmt")); 13 | return flds; 14 | } 15 | 16 | SymbRefTabDy::SymbDataSP SymbRefTabDy::FetchSymbData(Symb&) { 17 | return SymbDataSP{new SymbRef{}}; 18 | } 19 | 20 | } } // namespaces 21 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbRef.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbRef.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_SymbRef_hpp__ 4 | #define __fon9_fmkt_SymbRef_hpp__ 5 | #include "fon9/fmkt/SymbDy.hpp" 6 | #include "fon9/fmkt/FmktTypes.hpp" 7 | 8 | namespace fon9 { namespace fmkt { 9 | 10 | struct SymbRef_Data { 11 | Pri PriRef_{}; 12 | Pri PriUpLmt_{}; 13 | Pri PriDnLmt_{}; 14 | 15 | void Clear() { 16 | ForceZeroNonTrivial(this); 17 | } 18 | bool operator==(const SymbRef_Data& rhs) const { 19 | return memcmp(this, &rhs, sizeof(*this)) == 0; 20 | } 21 | bool operator!=(const SymbRef_Data& rhs) const { 22 | return !this->operator==(rhs); 23 | } 24 | }; 25 | 26 | /// \ingroup fmkt 27 | /// 商品資料的擴充: 參考價. 28 | fon9_API_TEMPLATE_CLASS(SymbRef, SimpleSymbData, SymbRef_Data); 29 | 30 | fon9_API seed::Fields SymbRef_MakeFields(); 31 | 32 | class fon9_API SymbRefTabDy : public SymbDataTab { 33 | fon9_NON_COPY_NON_MOVE(SymbRefTabDy); 34 | using base = SymbDataTab; 35 | public: 36 | SymbRefTabDy(Named&& named) 37 | : base{std::move(named), SymbRef_MakeFields(), seed::TabFlag::NoSapling_NoSeedCommand_Writable} { 38 | } 39 | 40 | SymbDataSP FetchSymbData(Symb&) override; 41 | }; 42 | 43 | } } // namespaces 44 | #endif//__fon9_fmkt_SymbRef_hpp__ 45 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTabNames.h: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTabNames.h 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_SymbTabNames_h__ 4 | #define __fon9_fmkt_SymbTabNames_h__ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #define fon9_kCSTR_TabName_Base "Base" 11 | #define fon9_kCSTR_TabName_Ref "Ref" 12 | #define fon9_kCSTR_TabName_BS "BS" 13 | #define fon9_kCSTR_TabName_Deal "Deal" 14 | #define fon9_kCSTR_TabName_Open "Open" 15 | #define fon9_kCSTR_TabName_High "High" 16 | #define fon9_kCSTR_TabName_Low "Low" 17 | #define fon9_kCSTR_TabName_BreakSt "BreakSt" 18 | #define fon9_kCSTR_TabName_Closing "Closing" 19 | #define fon9_kCSTR_TabName_DynBand "DynBand" 20 | #define fon9_kCSTR_TabName_QuoteReq "QuoteReq" 21 | #define fon9_kCSTR_TabName_Rt "Rt" 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | #endif//__fon9_fmkt_SymbTabNames_h__ 27 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTimePri.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbHL.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbTimePri.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | seed::Fields SymbTimePri_MakeFields(std::string priName) { 9 | seed::Fields flds; 10 | flds.Add(fon9_MakeField(SymbTimePri, Data_.Time_, "Time")); 11 | flds.Add(fon9_MakeField(SymbTimePri, Data_.Pri_, std::move(priName))); 12 | return flds; 13 | } 14 | 15 | } } // namespaces 16 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwa.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwa.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbTwa.hpp" 4 | 5 | namespace fon9 { namespace fmkt { 6 | 7 | SymbTwa::~SymbTwa() { 8 | } 9 | bool SymbTwa::IsExpired(unsigned tdayYYYYMMDD) const { 10 | return IsSymbExpired(this->EndYYYYMMDD_, tdayYYYYMMDD); 11 | } 12 | void SymbTwa::SessionClear(SymbTree& owner, f9fmkt_TradingSessionId tsesId) { 13 | if (this->TradingMarket_ == f9fmkt_TradingMarket_TwFUT 14 | || this->TradingMarket_ == f9fmkt_TradingMarket_TwOPT) 15 | base::SessionClear(owner, tsesId); 16 | else { 17 | this->TradingSessionId_ = tsesId; 18 | this->TradingSessionSt_ = f9fmkt_TradingSessionSt_Clear; 19 | this->SymbTwaBaseSessionClear(); 20 | } 21 | } 22 | void SymbTwa::OnSymbDailyClear(SymbTree& tree, const Symb& symb) { 23 | base::OnSymbDailyClear(tree, symb); 24 | this->SymbTwaBaseDailyClear(); 25 | } 26 | void SymbTwa::OnSymbSessionClear(SymbTree& tree, const Symb& symb) { 27 | base::OnSymbSessionClear(tree, symb); 28 | this->SymbTwaBaseSessionClear(); 29 | } 30 | seed::Fields SymbTwa::MakeFields() { 31 | seed::Fields flds = base::MakeFields(); 32 | SymbTwaBase::AddFields(flds); 33 | return flds; 34 | } 35 | 36 | } } // namespaces 37 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwa.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwa.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_SymbTwa_hpp__ 4 | #define __fon9_fmkt_SymbTwa_hpp__ 5 | #include "fon9/fmkt/SymbTwaBase.hpp" 6 | #include "fon9/fmkt/Symb.hpp" 7 | 8 | namespace fon9 { namespace fmkt { 9 | 10 | /// \ingroup fmkt 11 | /// 台灣 「證券」+「期交所」預設的商品基本類別. 12 | /// - Symb + SymbTwaBase 13 | class fon9_API SymbTwa : public Symb, public SymbTwaBase { 14 | fon9_NON_COPY_NON_MOVE(SymbTwa); 15 | using base = Symb; 16 | 17 | public: 18 | using base::base; 19 | ~SymbTwa(); 20 | 21 | /// 使用 this->EndYYYYMMDD_ 及 this->TDayYYYYMMDD_ 判斷是否過期. 22 | bool IsExpired() const { 23 | return this->IsSymbExpired(this->EndYYYYMMDD_, this->TDayYYYYMMDD_); 24 | } 25 | bool IsExpired(unsigned tdayYYYYMMDD) const override; 26 | void OnSymbDailyClear(SymbTree& tree, const Symb& symb) override; 27 | void OnSymbSessionClear(SymbTree& tree, const Symb& symb) override; 28 | /// 台灣證券的換盤, 不應清除 SymbData(Open/High/Low...); 29 | /// 台灣期權的換盤, 需要清除 SymbData(Open/High/Low...); 30 | void SessionClear(SymbTree& owner, f9fmkt_TradingSessionId tsesId) override; 31 | 32 | static seed::Fields MakeFields(); 33 | }; 34 | using SymbTwaSP = intrusive_ptr; 35 | 36 | } } // namespaces 37 | #endif//__fon9_fmkt_SymbTwa_hpp__ 38 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwaBase.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwaBase.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbTwaBase.hpp" 4 | 5 | namespace fon9 { namespace fmkt { 6 | 7 | } } // namespaces 8 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwaBase.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwaBase.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_SymbTwaBase_hpp__ 4 | #define __fon9_fmkt_SymbTwaBase_hpp__ 5 | #include "fon9/fmkt/SymbTwsBase.hpp" 6 | #include "fon9/fmkt/SymbTwfBase.hpp" 7 | 8 | namespace fon9 { namespace fmkt { 9 | 10 | /// \ingroup fmkt 11 | /// 台灣 「證券」+「期交所」預設的商品基本資料. 12 | struct SymbTwaBase : public SymbTwsBase, public SymbTwfBase { 13 | template 14 | static void AddFields(seed::Fields& flds) { 15 | SymbTwsBase::AddFields(flds); 16 | SymbTwfBase::AddFields(flds); 17 | } 18 | 19 | void SymbTwaBaseDailyClear() { 20 | this->SymbTwsBaseDailyClear(); 21 | this->SymbTwfBaseDailyClear(); 22 | } 23 | void SymbTwaBaseSessionClear() { 24 | this->SymbTwsBaseSessionClear(); 25 | this->SymbTwfBaseSessionClear(); 26 | } 27 | }; 28 | 29 | } } // namespaces 30 | #endif//__fon9_fmkt_SymbTwaBase_hpp__ 31 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwf.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwf.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbTwf.hpp" 4 | 5 | namespace fon9 { namespace fmkt { 6 | 7 | SymbTwf::~SymbTwf() { 8 | } 9 | bool SymbTwf::IsExpired(unsigned tdayYYYYMMDD) const { 10 | return IsSymbExpired(this->EndYYYYMMDD_, tdayYYYYMMDD); 11 | } 12 | void SymbTwf::OnSymbDailyClear(SymbTree& tree, const Symb& symb) { 13 | base::OnSymbDailyClear(tree, symb); 14 | this->SymbTwfBaseDailyClear(); 15 | } 16 | void SymbTwf::OnSymbSessionClear(SymbTree& tree, const Symb& symb) { 17 | base::OnSymbSessionClear(tree, symb); 18 | this->SymbTwfBaseSessionClear(); 19 | } 20 | seed::Fields SymbTwf::MakeFields() { 21 | seed::Fields flds = base::MakeFields(); 22 | SymbTwfBase::AddFields(flds); 23 | return flds; 24 | } 25 | 26 | } } // namespaces 27 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwf.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwf.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_SymbTwf_hpp__ 4 | #define __fon9_fmkt_SymbTwf_hpp__ 5 | #include "fon9/fmkt/SymbTwfBase.hpp" 6 | #include "fon9/fmkt/Symb.hpp" 7 | 8 | namespace fon9 { namespace fmkt { 9 | 10 | /// \ingroup fmkt 11 | /// 台灣期交所預設的基本商品類別. 12 | /// - Symb + SymbTwfBase 13 | class fon9_API SymbTwf : public Symb, public SymbTwfBase { 14 | fon9_NON_COPY_NON_MOVE(SymbTwf); 15 | using base = Symb; 16 | 17 | public: 18 | using base::base; 19 | ~SymbTwf(); 20 | 21 | bool IsExpired(unsigned tdayYYYYMMDD) const override; 22 | void OnSymbDailyClear(SymbTree& tree, const Symb& symb) override; 23 | void OnSymbSessionClear(SymbTree& tree, const Symb& symb) override; 24 | 25 | /// base::MakeFields(); and: 26 | /// - FlowGroup, PriceOrigDiv, StrikePriceDiv, ExgSymbSeq 27 | /// - EndDate 28 | static seed::Fields MakeFields(); 29 | }; 30 | using SymbTwfSP = intrusive_ptr; 31 | 32 | } } // namespaces 33 | #endif//__fon9_fmkt_SymbTwf_hpp__ 34 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwfBase.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwfBase.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbTwfBase.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | void SymbTwfBase::AddFields(int ofsadj, seed::Fields& flds) { 9 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwfBase, FlowGroup)); 10 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwfBase, PriceOrigDiv)); 11 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwfBase, StrikePriceDiv)); 12 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwfBase, ExgSymbSeq)); 13 | flds.Add(fon9_MakeField_OfsAdj (ofsadj, SymbTwfBase, EndYYYYMMDD_, "EndDate")); 14 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwfBase, SettleYYYYMM)); 15 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwfBase, StrikePrice)); 16 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwfBase, CallPut)); 17 | } 18 | 19 | } } // namespaces 20 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTws.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTws.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbTws.hpp" 4 | 5 | namespace fon9 { namespace fmkt { 6 | 7 | SymbTws::~SymbTws() { 8 | } 9 | void SymbTws::OnSymbDailyClear(SymbTree& tree, const Symb& symb) { 10 | base::OnSymbDailyClear(tree, symb); 11 | this->SymbTwsBaseDailyClear(); 12 | } 13 | void SymbTws::SessionClear(SymbTree& owner, f9fmkt_TradingSessionId tsesId) { 14 | (void)owner; 15 | this->TradingSessionId_ = tsesId; 16 | this->TradingSessionSt_ = f9fmkt_TradingSessionSt_Clear; 17 | this->SymbTwsBaseSessionClear(); 18 | } 19 | seed::Fields SymbTws::MakeFields() { 20 | seed::Fields flds = base::MakeFields(); 21 | SymbTwsBase::AddFields(flds); 22 | return flds; 23 | } 24 | 25 | } } // namespaces 26 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTws.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTws.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_SymbTws_hpp__ 4 | #define __fon9_fmkt_SymbTws_hpp__ 5 | #include "fon9/fmkt/SymbTwsBase.hpp" 6 | #include "fon9/fmkt/Symb.hpp" 7 | 8 | namespace fon9 { namespace fmkt { 9 | 10 | /// \ingroup fmkt 11 | /// 台灣證券預設的基本商品類別. 12 | /// - Symb + SymbTwsBase 13 | class fon9_API SymbTws : public Symb, public SymbTwsBase { 14 | fon9_NON_COPY_NON_MOVE(SymbTws); 15 | using base = Symb; 16 | 17 | public: 18 | using base::base; 19 | ~SymbTws(); 20 | 21 | void OnSymbDailyClear(SymbTree& tree, const Symb& symb) override; 22 | /// 台灣證券的換盤, 不應清除 SymbData(Open/High/Low...); 23 | /// - 設定 this->TradingSessionId_ = tsesId; 24 | /// - 設定 this->TradingSessionSt_ = f9fmkt_TradingSessionSt_Clear; 25 | /// - 不會觸發 this->GetSymbData(tabid=0..N)->OnSymbSessionClear(); 26 | void SessionClear(SymbTree& owner, f9fmkt_TradingSessionId tsesId) override; 27 | 28 | /// base::MakeFields(); and: 29 | /// - ShUnit 30 | /// - TwsFlags 31 | static seed::Fields MakeFields(); 32 | }; 33 | using SymbTwsSP = intrusive_ptr; 34 | 35 | } } // namespaces 36 | #endif//__fon9_fmkt_SymbTws_hpp__ 37 | -------------------------------------------------------------------------------- /fon9/fmkt/SymbTwsBase.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/fmkt/SymbTwsBase.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/fmkt/SymbTwsBase.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | void SymbTwsBase::AddFields(int ofsadj, seed::Fields& flds) { 9 | flds.Add(fon9_MakeField2_OfsAdj(ofsadj, SymbTwsBase, ShUnit)); 10 | flds.Add(seed::FieldSP{new seed::FieldIntHx>( 11 | Named("TwsFlags"), ofsadj + fon9_OffsetOfRawPointer(SymbTwsBase, TwsFlags_))}); 12 | } 13 | 14 | } } // namespaces 15 | -------------------------------------------------------------------------------- /fon9/fmkt/TradingLineGroup.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/fmkt/TradingLineGroup.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/fmkt/TradingLineGroup.hpp" 4 | 5 | namespace fon9 { namespace fmkt { 6 | 7 | TradingLgMgrBase::~TradingLgMgrBase() { 8 | } 9 | TradingLgMgrBase::LgItemBaseSP TradingLgMgrBase::MakeLgItem(StrView tag, StrView cfgln) { 10 | if (tag.size() != fon9_kSIZE_LgTAG_LEAD + 1) 11 | return nullptr; 12 | const char* ptag = tag.begin(); 13 | // Unknown tag. 14 | if (memcmp(ptag, fon9_kCSTR_LgTAG_LEAD, fon9_kSIZE_LgTAG_LEAD) != 0) 15 | return nullptr; 16 | const LgOut lgId = static_cast(ptag[fon9_kSIZE_LgTAG_LEAD]); 17 | // Unknown LgId. 18 | if (!IsValidateLgOut(lgId)) 19 | return nullptr; 20 | const uint8_t lgIdx = LgOutToIndex(lgId); 21 | // Dup Lg. 22 | if (this->LgItems_[lgIdx].get() != nullptr) 23 | return nullptr; 24 | StrView title = SbrFetchNoTrim(cfgln, ','); 25 | LgItemBaseSP retval = this->CreateLgItem(Named( 26 | tag.ToString(), 27 | StrView_ToNormalizeStr(StrTrimRemoveQuotes(title)), 28 | StrView_ToNormalizeStr(StrTrimRemoveQuotes(cfgln)) 29 | )); 30 | this->LgItems_[lgIdx] = retval; 31 | this->Sapling_->Add(retval); 32 | return retval; 33 | } 34 | 35 | } } // namespaces 36 | -------------------------------------------------------------------------------- /fon9/fmkt/TradingLineManagerSeed.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/fmkt/TradingLineManagerSeed.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/fmkt/TradingLineManagerSeed.hpp" 4 | #include "fon9/fmkt/TradingLine.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | TradingLineManagerSeed::~TradingLineManagerSeed() { 9 | } 10 | void TradingLineManagerSeed::OnSeedCommand(seed::SeedOpResult& res, StrView cmdln, seed::FnCommandResultHandler resHandler, 11 | seed::MaTreeBase::Locker&& ulk, seed::SeedVisitor* visitor) { 12 | if (cmdln == "?") { 13 | res.OpResult_ = seed::OpResult::no_error; 14 | resHandler(res, 15 | //"xx" fon9_kCSTR_CELLSPL "需要輸入參數的指令" fon9_kCSTR_CELLSPL "輸入參數的提示字串." fon9_kCSTR_ROWSPL 16 | "st" fon9_kCSTR_CELLSPL "State info" 17 | ); 18 | return; 19 | } 20 | if (iequals(cmdln, "st")) { 21 | if (auto* lmgr = dynamic_cast(this->Sapling_.get())) { 22 | fon9::RevBufferList rbuf{256}; 23 | lmgr->Lock()->GetStInfo(rbuf); 24 | resHandler(res, ToStrView(BufferTo(rbuf.MoveOut()))); 25 | return; 26 | } 27 | } 28 | base::OnSeedCommand(res, cmdln, std::move(resHandler), std::move(ulk), visitor); 29 | } 30 | 31 | } } // namespaces 32 | -------------------------------------------------------------------------------- /fon9/fmkt/TradingLineManagerSeed.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/fmkt/TradingLineManagerSeed.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_fmkt_TradingLineManagerSeed_hpp__ 4 | #define __fon9_fmkt_TradingLineManagerSeed_hpp__ 5 | #include "fon9/seed/MaTree.hpp" 6 | 7 | namespace fon9 { namespace fmkt { 8 | 9 | class fon9_API TradingLineManagerSeed : public seed::NamedSapling { 10 | fon9_NON_COPY_NON_MOVE(TradingLineManagerSeed); 11 | using base = seed::NamedSapling; 12 | public: 13 | using base::base; 14 | ~TradingLineManagerSeed(); 15 | /// 提供現在的 [線路 & Helper] 狀態 16 | void OnSeedCommand(seed::SeedOpResult& res, StrView cmdln, seed::FnCommandResultHandler resHandler, 17 | seed::MaTreeBase::Locker&& ulk, seed::SeedVisitor* visitor) override; 18 | }; 19 | 20 | 21 | } } // namespaces 22 | #endif//__fon9_fmkt_TradingLineManagerSeed_hpp__ 23 | -------------------------------------------------------------------------------- /fon9/fmkt/TradingRequest.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/fmkt/TradingRequest.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/fmkt/TradingRequest.hpp" 4 | #include "fon9/fmkt/TradingLine.hpp" 5 | 6 | namespace fon9 { namespace fmkt { 7 | 8 | TradingRxItem::~TradingRxItem() { 9 | } 10 | void TradingRxItem::FreeThis() { 11 | delete this; 12 | } 13 | void TradingRxItem::RevPrint(RevBuffer&) const { 14 | } 15 | const TradingRxItem* TradingRxItem::CastToRequest() const { 16 | return nullptr; 17 | } 18 | const TradingRxItem* TradingRxItem::CastToOrder() const { 19 | return nullptr; 20 | } 21 | const TradingRxItem* TradingRxItem::CastToEvent() const { 22 | return nullptr; 23 | } 24 | //--------------------------------------------------------------------------// 25 | TradingRequest::~TradingRequest() { 26 | } 27 | bool TradingRequest::PreOpQueuingRequest(TradingLineManager& from) const { 28 | (void)from; 29 | return false; 30 | } 31 | TradingRequest::OpQueuingRequestResult TradingRequest::OpQueuingRequest(TradingLineManager& from, 32 | TradingRequest& queuingRequest) { 33 | (void)from; (void)queuingRequest; 34 | return Op_NotSupported; 35 | } 36 | bool TradingRequest::IsPreferTradingLine(TradingLine& tline) const { 37 | return tline.IsOrigSender(*this); 38 | } 39 | 40 | } } // namespaces 41 | -------------------------------------------------------------------------------- /fon9/framework/Fon9Co_main.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/framework/Fon9Co_main.cpp 2 | // fon9 console: 直接轉呼叫 fon9::Fon9CoRun(); 3 | // \author fonwinz@gmail.com 4 | #include "fon9/framework/Framework.hpp" 5 | 6 | int main(int argc, const char* argv[]) { 7 | return fon9::Fon9CoRun(argc, argv, nullptr); 8 | } 9 | -------------------------------------------------------------------------------- /fon9/framework/FrameworkFlag.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/framework/FrameworkFlag.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/framework/FrameworkFlag.hpp" 4 | 5 | namespace fon9 { 6 | 7 | fon9_API bool IsFrameworkInitializing = false; 8 | 9 | } // namespaces 10 | -------------------------------------------------------------------------------- /fon9/framework/FrameworkFlag.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/framework/FrameworkFlag.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_framework_FrameworkFlag_hpp__ 4 | #define __fon9_framework_FrameworkFlag_hpp__ 5 | #include "fon9/sys/Config.hpp" 6 | 7 | namespace fon9 { 8 | 9 | /// 預設為 false, 10 | /// - 當 Framework::Initialize() 開始執行時設為 true; 11 | /// - 在 Framework::Start() 返回前設為 false; 12 | /// - 在有需要 MaAuth 的環境下(例: MaIo), 啟動前應判斷此旗標. 13 | extern fon9_API bool IsFrameworkInitializing; 14 | 15 | } // namespaces 16 | #endif//__fon9_framework_FrameworkFlag_hpp__ 17 | -------------------------------------------------------------------------------- /fon9/framework/NamedIoManager.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/framework/NamedIoManager.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/framework/IoManagerTree.hpp" 4 | #include "fon9/seed/SysEnv.hpp" 5 | #include "fon9/seed/Plugins.hpp" 6 | 7 | namespace fon9 { 8 | 9 | static bool NamedIoManager_Start(seed::PluginsHolder& holder, StrView args) { 10 | IoManagerArgs iomArgs; 11 | StrView tag, value; 12 | while (fon9::SbrFetchTagValue(args, tag, value)) { 13 | iomArgs.SetTagValue(holder, tag, value); 14 | } 15 | if (!iomArgs.Name_.empty() && IoManagerTree::Plant(*holder.Root_, iomArgs)) 16 | return true; 17 | holder.SetPluginsSt(fon9::LogLevel::Error, "Name=", iomArgs.Name_, "|err='Name' is dup or empty"); 18 | return false; 19 | } 20 | 21 | } // namespaces 22 | 23 | extern "C" fon9_API fon9::seed::PluginsDesc f9p_NamedIoManager; 24 | static fon9::seed::PluginsPark f9pAutoPluginsReg{"NamedIoManager", &f9p_NamedIoManager}; 25 | 26 | fon9::seed::PluginsDesc f9p_NamedIoManager{ 27 | "", 28 | &fon9::NamedIoManager_Start, 29 | nullptr, 30 | nullptr, 31 | }; 32 | -------------------------------------------------------------------------------- /fon9/framework/SessionFactoryConfigWithAuthMgr.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/framework/SessionFactoryConfigWithAuthMgr.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/framework/SessionFactoryConfigWithAuthMgr.hpp" 4 | 5 | namespace fon9 { 6 | 7 | bool SessionFactoryConfigWithAuthMgr::OnUnknownTag(seed::PluginsHolder& holder, StrView tag, StrView value) { 8 | if (tag == "AuthMgr") { 9 | this->AuthMgrName_ = value; 10 | return true; 11 | } 12 | return base::OnUnknownTag(holder, tag, value); 13 | } 14 | auth::AuthMgrSP SessionFactoryConfig_GetAuthMgr(IoFactoryConfigParser& parser, 15 | seed::MaTree& root, 16 | const StrView& authMgrName) { 17 | if (auto authMgr = root.Get(authMgrName)) 18 | return authMgr; 19 | parser.ErrMsg_ += "|err=Unknown AuthMgr"; 20 | if (!authMgrName.empty()) { 21 | parser.ErrMsg_.push_back('='); 22 | authMgrName.AppendTo(parser.ErrMsg_); 23 | } 24 | return nullptr; 25 | } 26 | 27 | } // namespaces 28 | -------------------------------------------------------------------------------- /fon9/intrusive_ref_counter.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fonwin/libfon9/c07ca2ffb3547a03a31c41db5ad036ab6ee859bc/fon9/intrusive_ref_counter.hpp -------------------------------------------------------------------------------- /fon9/io/FdrDgram.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/FdrDgram.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/sys/Config.h" 4 | #ifdef fon9_POSIX 5 | #include "fon9/io/FdrDgram.hpp" 6 | 7 | namespace fon9 { namespace io { 8 | 9 | bool FdrDgramImpl::OpImpl_ConnectTo(const SocketAddress& addr, SocketResult& soRes) { 10 | this->State_ = State::Connecting; 11 | if (!addr.IsEmpty()) { 12 | // connect(remote address) for send: writev() 的對方位置. 13 | if (::connect(this->GetFD(), &addr.Addr_, addr.GetAddrLen()) != 0) { 14 | soRes = SocketResult{"connect"}; 15 | return false; 16 | } 17 | } 18 | this->State_ = State::Connected; 19 | this->Owner_->OpImpl_Connected(this->GetFD()); 20 | return true; 21 | } 22 | 23 | void FdrDgramImpl::OnFdrEvent_Handling(FdrEventFlag evs) { 24 | FdrEventProcessor(this, *this->Owner_, evs); 25 | } 26 | void FdrDgramImpl::OnFdrEvent_StartSend() { 27 | this->StartSend(*this->Owner_); 28 | } 29 | void FdrDgramImpl::OnFdrSocket_Error(std::string errmsg) { 30 | this->Owner_->OnSocketError(this, std::move(errmsg)); 31 | } 32 | void FdrDgramImpl::SocketError(StrView fnName, int eno) { 33 | switch (eno) { 34 | case ECONNREFUSED: /* 111:Connection refused */ 35 | // 若對方(如果對方為本機ip)沒有 listen udp port, 則在 writev() 時會有此錯誤! 36 | return; 37 | } 38 | base::SocketError(fnName, eno); 39 | } 40 | 41 | } } // namespaces 42 | #endif 43 | -------------------------------------------------------------------------------- /fon9/io/FdrDgram.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/FdrDgram.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_io_FdrDgram_hpp__ 4 | #define __fon9_io_FdrDgram_hpp__ 5 | #include "fon9/io/DgramBase.hpp" 6 | #include "fon9/io/FdrSocketClient.hpp" 7 | 8 | namespace fon9 { namespace io { 9 | 10 | struct FdrDgramImpl : public FdrSocketClientImpl { 11 | fon9_NON_COPY_NON_MOVE(FdrDgramImpl); 12 | using base = FdrSocketClientImpl; 13 | virtual void OnFdrEvent_Handling(FdrEventFlag evs) override; 14 | virtual void OnFdrEvent_StartSend() override; 15 | virtual void OnFdrSocket_Error(std::string errmsg) override; 16 | virtual void SocketError(StrView fnName, int eno) override; 17 | 18 | public: 19 | using OwnerDevice = DgramT; 20 | using OwnerDeviceSP = intrusive_ptr; 21 | const OwnerDeviceSP Owner_; 22 | 23 | FdrDgramImpl(OwnerDevice* owner, Socket&& so, SocketResult&) 24 | : base{*owner->IoService_, std::move(so)} 25 | , Owner_{owner} { 26 | } 27 | bool OpImpl_ConnectTo(const SocketAddress& addr, SocketResult& soRes); 28 | }; 29 | 30 | //--------------------------------------------------------------------------// 31 | 32 | /// \ingroup io 33 | /// 使用 fd 的實作的 Dgram. 34 | using FdrDgram = DeviceImpl_DeviceStartSend; 35 | 36 | } } // namespaces 37 | #endif//__fon9_io_FdrDgram_hpp__ 38 | -------------------------------------------------------------------------------- /fon9/io/FdrServiceEpoll.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/FdrServiceEpoll.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_io_FdrServiceEpoll_hpp__ 4 | #define __fon9_io_FdrServiceEpoll_hpp__ 5 | #ifdef __linux__ 6 | #include "fon9/io/FdrService.hpp" 7 | #include "fon9/ObjPool.hpp" 8 | 9 | namespace fon9 { namespace io { 10 | 11 | struct FdrServiceEpoll { 12 | using MakeResult = Result2; 13 | static FdrServiceSP MakeService(const IoServiceArgs& ioArgs, const std::string& thrName, MakeResult& err); 14 | }; 15 | 16 | /// \ingroup io 17 | /// 提供使用 epoll 處理 non-blocking fd 讀寫事件服務. 18 | class FdrThreadEpoll : public FdrThread { 19 | const FdrAuto FdrEpoll_; 20 | struct EvHandler : public FdrEventHandlerSP { 21 | using FdrEventHandlerSP::FdrEventHandlerSP; 22 | FdrEventFlag Events_{FdrEventFlag::None}; 23 | }; 24 | using EvHandlers = ObjPool; 25 | 26 | void ProcessPendings(Fdr::fdr_t epFdr, EvHandlers& evHandlers); 27 | virtual void ThrRunImpl(const ServiceThreadArgs& args) override; 28 | 29 | public: 30 | FdrThreadEpoll(FdrServiceEpoll::MakeResult& res); 31 | 32 | virtual ~FdrThreadEpoll(); 33 | }; 34 | 35 | } } // namespaces 36 | #endif//__linux__ 37 | #endif//__fon9_io_FdrServiceEpoll_hpp__ 38 | -------------------------------------------------------------------------------- /fon9/io/FdrSocketClient.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/FdrSocketClient.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/sys/Config.h" 4 | #ifdef fon9_POSIX 5 | #include "fon9/io/FdrSocketClient.hpp" 6 | 7 | namespace fon9 { namespace io { 8 | 9 | void FdrSocketClientImpl::OnFdrEvent_AddRef() { 10 | intrusive_ptr_add_ref(static_cast(this)); 11 | } 12 | void FdrSocketClientImpl::OnFdrEvent_ReleaseRef() { 13 | intrusive_ptr_release(static_cast(this)); 14 | } 15 | void FdrSocketClientImpl::OpImpl_Close() { 16 | this->State_ = State::Closing; 17 | this->EnabledEvents_.store(0, std::memory_order_relaxed); 18 | this->RemoveFdrEvent(); 19 | ::shutdown(this->GetFD(), SHUT_WR); 20 | } 21 | 22 | } } // namespaces 23 | #endif 24 | -------------------------------------------------------------------------------- /fon9/io/FdrTcpClient.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/FdrTcpClient.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/sys/Config.h" 4 | #ifdef fon9_POSIX 5 | #include "fon9/io/FdrTcpClient.hpp" 6 | 7 | namespace fon9 { namespace io { 8 | 9 | bool FdrTcpClientImpl::OpImpl_ConnectTo(const SocketAddress& addr, SocketResult& soRes) { 10 | this->State_ = State::Connecting; 11 | if (::connect(this->GetFD(), &addr.Addr_, addr.GetAddrLen()) == 0) { 12 | this->Owner_->OpImpl_Connected(this->GetFD()); 13 | } 14 | else { 15 | int eno = errno; 16 | if (eno != EINPROGRESS) { 17 | soRes = SocketResult{"connect", GetSocketErrC(eno)}; 18 | return false; 19 | } 20 | this->EnableEventBit(FdrEventFlag::Writable); 21 | } 22 | return true; 23 | } 24 | 25 | void FdrTcpClientImpl::OnFdrSocket_Error(std::string errmsg) { 26 | this->Owner_->OnSocketError(this, std::move(errmsg)); 27 | } 28 | void FdrTcpClientImpl::OnFdrEvent_Handling(FdrEventFlag evs) { 29 | FdrEventProcessor(this, *this->Owner_, evs); 30 | } 31 | void FdrTcpClientImpl::OnFdrEvent_StartSend() { 32 | this->StartSend(*this->Owner_); 33 | } 34 | 35 | } } // namespaces 36 | #endif 37 | -------------------------------------------------------------------------------- /fon9/io/FdrTcpClient.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/FdrTcpClient.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_io_FdrTcpClient_hpp__ 4 | #define __fon9_io_FdrTcpClient_hpp__ 5 | #include "fon9/io/TcpClientBase.hpp" 6 | #include "fon9/io/FdrSocketClient.hpp" 7 | 8 | namespace fon9 { namespace io { 9 | 10 | struct FdrTcpClientImpl : public FdrSocketClientImpl { 11 | fon9_NON_COPY_NON_MOVE(FdrTcpClientImpl); 12 | using base = FdrSocketClientImpl; 13 | virtual void OnFdrEvent_Handling(FdrEventFlag evs) override; 14 | virtual void OnFdrEvent_StartSend() override; 15 | virtual void OnFdrSocket_Error(std::string errmsg) override; 16 | 17 | public: 18 | using OwnerDevice = TcpClientT; 19 | using OwnerDeviceSP = intrusive_ptr; 20 | const OwnerDeviceSP Owner_; 21 | 22 | FdrTcpClientImpl(OwnerDevice* owner, Socket&& so, SocketResult&) 23 | : base{*owner->IoService_, std::move(so)} 24 | , Owner_{owner} { 25 | } 26 | bool OpImpl_ConnectTo(const SocketAddress& addr, SocketResult& soRes); 27 | }; 28 | 29 | //--------------------------------------------------------------------------// 30 | 31 | /// \ingroup io 32 | /// 使用 fd 的實作的 TcpClient. 33 | using FdrTcpClient = DeviceImpl_DeviceStartSend; 34 | 35 | } } // namespaces 36 | #endif//__fon9_io_FdrTcpClient_hpp__ 37 | -------------------------------------------------------------------------------- /fon9/io/Manager.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/Manager.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/io/Manager.hpp" 4 | 5 | namespace fon9 { namespace io { 6 | 7 | Manager::~Manager() { 8 | } 9 | 10 | unsigned ManagerC::IoManagerAddRef() { 11 | return intrusive_ptr_add_ref(static_cast(this)); 12 | } 13 | unsigned ManagerC::IoManagerRelease() { 14 | return intrusive_ptr_release(static_cast(this)); 15 | } 16 | 17 | } } // namespaces 18 | -------------------------------------------------------------------------------- /fon9/io/SendBuffer.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/io/SendBuffer.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/io/SendBuffer.hpp" 4 | 5 | namespace fon9 { namespace io { 6 | 7 | } } // namespaces 8 | -------------------------------------------------------------------------------- /fon9/io/Session.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/Session.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/io/Session.hpp" 4 | 5 | namespace fon9 { namespace io { 6 | 7 | Session::~Session() { 8 | } 9 | void Session::OnDevice_Initialized(Device& dev) { 10 | (void)dev; 11 | } 12 | void Session::OnDevice_Destructing(Device& dev) { 13 | (void)dev; 14 | } 15 | bool Session::OnDevice_BeforeOpen(Device& dev, std::string& cfgstr) { 16 | (void)dev; (void)cfgstr; 17 | return true; 18 | } 19 | void Session::OnDevice_StateChanged(Device& dev, const StateChangedArgs& e) { 20 | (void)dev; (void)e; 21 | } 22 | void Session::OnDevice_StateUpdated(Device& dev, const StateUpdatedArgs& e) { 23 | (void)dev; (void)e; 24 | } 25 | RecvBufferSize Session::OnDevice_LinkReady(Device& dev) { 26 | (void)dev; 27 | return RecvBufferSize::Default; 28 | } 29 | RecvBufferSize Session::OnDevice_Recv(Device& dev, DcQueue& rxbuf) { 30 | (void)dev; (void)rxbuf; 31 | return RecvBufferSize::Default; 32 | } 33 | void Session::OnDevice_CommonTimer(Device& dev, TimeStamp now) { 34 | (void)dev; (void)now; 35 | } 36 | //void Session::OnDevice_SendBufferEmpty(Device& dev) { 37 | // (void)dev; 38 | //} 39 | std::string Session::SessionCommand(Device& dev, StrView cmdln) { 40 | (void)dev; (void)cmdln; 41 | return "unknown session command"; 42 | } 43 | 44 | } } // namespaces 45 | -------------------------------------------------------------------------------- /fon9/io/TcpClientBase.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/TcpClientBase.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/io/TcpClientBase.hpp" 4 | 5 | namespace fon9 { namespace io { 6 | 7 | bool TcpClientBase::CreateSocket(Socket& so, const SocketAddress& addr, SocketResult& soRes) { 8 | return so.CreateDeviceSocket(addr.GetAF(), SocketType::Stream, soRes); 9 | } 10 | void TcpClientBase::OpImpl_Connected(Socket::socket_t so) { 11 | auto errc = Socket::LoadSocketErrC(so); 12 | if (errc) { 13 | OpThr_SetBrokenState(*this, RevPrintTo("err=", errc)); 14 | return; 15 | } 16 | SocketAddress addrLocal; 17 | socklen_t addrLen = sizeof(addrLocal); 18 | getsockname(so, &addrLocal.Addr_, &addrLen); 19 | char uidbuf[kMaxTcpConnectionUID]; 20 | StrView uidstr = MakeTcpConnectionUID(uidbuf, &this->RemoteAddress_, &addrLocal); 21 | if (this->RemoteAddress_ == addrLocal) { 22 | std::string errmsg{"err=self-connect|id="}; 23 | uidstr.AppendTo(errmsg); 24 | OpThr_SetBrokenState(*this, std::move(errmsg)); 25 | } 26 | else { 27 | this->OpImpl_SetConnected(uidstr.ToString()); 28 | } 29 | } 30 | 31 | } } // namespaces 32 | -------------------------------------------------------------------------------- /fon9/io/TcpClientBase.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/TcpClientBase.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_io_TcpClientBase_hpp__ 4 | #define __fon9_io_TcpClientBase_hpp__ 5 | #include "fon9/io/SocketClientDevice.hpp" 6 | 7 | namespace fon9 { namespace io { 8 | 9 | /// \ingroup io 10 | /// TcpClient 基底, 衍生者: IocpTcpClient, FdrTcpClient; 11 | class fon9_API TcpClientBase : public SocketClientDevice { 12 | fon9_NON_COPY_NON_MOVE(TcpClientBase); 13 | TcpClientBase() = delete; 14 | using base = SocketClientDevice; 15 | 16 | protected: 17 | bool CreateSocket(Socket& so, const SocketAddress& addr, SocketResult& soRes) override; 18 | void OpImpl_Connected(Socket::socket_t so); 19 | 20 | public: 21 | TcpClientBase(SessionSP ses, ManagerSP mgr) 22 | : base(std::move(ses), std::move(mgr), Style::Client) { 23 | } 24 | }; 25 | 26 | template 27 | using TcpClientT = SocketClientDeviceT; 28 | 29 | } } // namespaces 30 | #endif//__fon9_io_TcpClientBase_hpp__ 31 | -------------------------------------------------------------------------------- /fon9/io/TcpServerBase.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/TcpServerBase.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/io/TcpServerBase.hpp" 4 | 5 | namespace fon9 { namespace io { 6 | 7 | 8 | } } // namespaces 9 | -------------------------------------------------------------------------------- /fon9/io/win/IocpSocketClient.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/win/IocpSocketClient.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/io/win/IocpSocketClient.hpp" 4 | 5 | namespace fon9 { namespace io { 6 | 7 | unsigned IocpSocketClientImpl::IocpSocketAddRef() { 8 | return intrusive_ptr_add_ref(this); 9 | } 10 | unsigned IocpSocketClientImpl::IocpSocketReleaseRef() { 11 | return intrusive_ptr_release(this); 12 | } 13 | 14 | } } // namespaces 15 | -------------------------------------------------------------------------------- /fon9/io/win/IocpSocketClient.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/io/win/IocpSocketClient.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_io_win_IocpSocketClient_hpp__ 4 | #define __fon9_io_win_IocpSocketClient_hpp__ 5 | #include "fon9/io/win/IocpSocket.hpp" 6 | 7 | namespace fon9 { namespace io { 8 | 9 | struct fon9_API IocpSocketClientImpl : public IocpSocket, public intrusive_ref_counter { 10 | fon9_NON_COPY_NON_MOVE(IocpSocketClientImpl); 11 | 12 | virtual unsigned IocpSocketAddRef() override; 13 | virtual unsigned IocpSocketReleaseRef() override; 14 | 15 | protected: 16 | enum class State { 17 | Idle, 18 | Closing, 19 | Connecting, 20 | Connected, 21 | }; 22 | State State_{}; 23 | 24 | public: 25 | IocpSocketClientImpl(IocpServiceSP iosv, Socket&& so, SocketResult& soRes) 26 | : IocpSocket(std::move(iosv), std::move(so), soRes) { 27 | } 28 | bool IsClosing() const { 29 | return this->State_ == State::Closing; 30 | } 31 | }; 32 | 33 | } } // namespaces 34 | #endif//__fon9_io_win_IocpSocketClient_hpp__ 35 | -------------------------------------------------------------------------------- /fon9/rc/Rc.h: -------------------------------------------------------------------------------- 1 | // \file fon9/rc/Rc.h 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_rc_Rc_h__ 4 | #define __fon9_rc_Rc_h__ 5 | #include "fon9/sys/Config.h" 6 | #include "fon9/CStrView.h" 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif//__cplusplus 12 | 13 | fon9_ENUM(f9rc_RcFlag, uint16_t) { 14 | f9rc_RcFlag_NoChecksum = 0x01, 15 | }; 16 | 17 | fon9_ENUM(f9rc_FunctionCode, uint8_t) { 18 | f9rc_FunctionCode_Connection = 0, 19 | f9rc_FunctionCode_SASL = 1, 20 | f9rc_FunctionCode_Logout = 2, 21 | f9rc_FunctionCode_Heartbeat = 3, 22 | 23 | f9rc_FunctionCode_SeedVisitor = 6, 24 | f9rc_FunctionCode_OmsApi = 7, 25 | 26 | /// 這裡提供一個暫時的最大值, 可減少一些記憶體用量. 27 | /// 目前規劃: 28 | /// - admin 功能(登入、Heartbeat...) 29 | /// - SeedVisitor 30 | /// - OmsRc 31 | /// - 其他請參考 fon9/rc/README.md 32 | f9rc_FunctionCode_Count = 8, 33 | }; 34 | 35 | #ifdef __cplusplus 36 | }//extern "C" 37 | #endif//__cplusplus 38 | #endif//__fon9_rc_Rc_h__ 39 | -------------------------------------------------------------------------------- /fon9/rc/RcFuncConn.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/rc/RcFuncConn.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/rc/RcFuncConn.hpp" 4 | 5 | namespace fon9 { namespace rc { 6 | 7 | RcFuncConnection::~RcFuncConnection() { 8 | } 9 | 10 | } } // namespace 11 | -------------------------------------------------------------------------------- /fon9/rc/RcMdRtsDecoder.h: -------------------------------------------------------------------------------- 1 | // \file fon9/rc/RcMdRtsDecoder.h 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_rc_RcMdRtsDecoder_h__ 4 | #define __fon9_rc_RcMdRtsDecoder_h__ 5 | #include "fon9/rc/RcSeedVisitor.h" 6 | #include "fon9/fmkt/FmdTypes.h" 7 | #include "fon9/fmkt/FmdRtsPackType.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif//__cplusplus 12 | 13 | /// 將 "MdRts" 加入 StreamDecoder; 之後可以使用: "$TabName:MdRts:Args"; 的格式. 14 | /// - 在 f9sv_Initialize() 之後, f9sv_Subscribe() 之前, 執行一次即可. 15 | /// - 行情訂閱: 訂閱參數=? 如何回補? 如何區分日夜盤? 16 | /// 回補應可到「前一盤」, 不論前一盤是日盤或夜盤. 17 | f9sv_CAPI_FN(f9sv_Result) f9sv_AddStreamDecoder_MdRts(void); 18 | 19 | #ifdef __cplusplus 20 | }//extern "C" 21 | #endif//__cplusplus 22 | #endif//__fon9_rc_RcMdRtsDecoder_h__ 23 | -------------------------------------------------------------------------------- /fon9/rc/RcSvStreamDecoder.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/rc/RcSvStreamDecoder.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/rc/RcSvStreamDecoder.hpp" 4 | 5 | namespace fon9 { namespace rc { 6 | 7 | RcSvStreamDecoderNote::~RcSvStreamDecoderNote() { 8 | } 9 | RcSvStreamDecoder::~RcSvStreamDecoder() { 10 | } 11 | RcSvStreamDecoderFactory::~RcSvStreamDecoderFactory() { 12 | } 13 | RcSvStreamDecoderFactory* RcSvStreamDecoderPark::Register(StrView name, RcSvStreamDecoderFactory* factory) { 14 | return SimpleFactoryRegister(name, factory); 15 | } 16 | 17 | 18 | } } // namespaces 19 | -------------------------------------------------------------------------------- /fon9/seed/Field.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/seed/Field.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/seed/Field.hpp" 4 | #include "fon9/seed/FieldTimeStamp.hpp" 5 | 6 | namespace fon9 { namespace seed { 7 | 8 | Field::~Field() { 9 | } 10 | uint32_t Field::GetAvailSize() const { 11 | return this->Size_; 12 | } 13 | FieldNumberT Field::GetNullValue() const { 14 | return 0; 15 | } 16 | OpResult Field::SetNull(const RawWr& wr) const { 17 | (void)wr; 18 | return OpResult::not_supported_null; 19 | } 20 | bool Field::IsNull(const RawRd& rd) const { 21 | (void)rd; 22 | return false; 23 | } 24 | 25 | //--------------------------------------------------------------------------// 26 | 27 | StrView FieldTimeStamp::GetTypeId(NumOutBuf&) const { 28 | return StrView{"Ts"}; 29 | } 30 | StrView FieldTimeInterval::GetTypeId(NumOutBuf&) const { 31 | return StrView{"Ti"}; 32 | } 33 | StrView FieldDayTime::GetTypeId(NumOutBuf&) const { 34 | return StrView{"Td"}; 35 | } 36 | 37 | } } // namespaces 38 | -------------------------------------------------------------------------------- /fon9/seed/FieldSchCfgStr.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/seed/FieldSchCfgStr.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/seed/FieldSchCfgStr.hpp" 4 | #include "fon9/seed/FieldDyBlob.hpp" 5 | 6 | namespace fon9 { namespace seed { 7 | 8 | StrView FieldSchCfgStr::GetTypeId(NumOutBuf&) const { 9 | return StrView{fon9_kCSTR_UDStrFieldMaker_Head fon9_kCSTR_UDFieldMaker_SchCfgStr}; 10 | } 11 | 12 | static FieldSP SchCfgStrFieldMaker(StrView& fldcfg, char chSpl, char chTail) { 13 | Named named{DeserializeNamed(fldcfg, chSpl, chTail)}; 14 | if (named.Name_.empty()) 15 | return FieldSP{}; 16 | using FieldSchCfgStr_Dy = FieldSchCfgStrT; 17 | return FieldSP{new FieldSchCfgStr_Dy(std::move(named), f9sv_FieldType_Chars)}; 18 | } 19 | 20 | static FieldMakerRegister reg{StrView{fon9_kCSTR_UDFieldMaker_SchCfgStr}, &SchCfgStrFieldMaker}; 21 | 22 | } } // namespaces 23 | -------------------------------------------------------------------------------- /fon9/seed/FieldType.h: -------------------------------------------------------------------------------- 1 | // \file fon9/seed/FieldType.h 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_seed_FieldType_h__ 4 | #define __fon9_seed_FieldType_h__ 5 | #include "fon9/rc/RcClientApi.h" 6 | #include "fon9/Assert.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /// \ingroup seed 13 | /// 欄位儲存的資料類型. 14 | fon9_ENUM(f9sv_FieldType, uint8_t) { 15 | /// 類型不明, 或自訂欄位. 16 | f9sv_FieldType_Unknown, 17 | /// bytes 陣列. 18 | /// 顯示字串 = 需要額外轉換(例: HEX, Base64...) 19 | f9sv_FieldType_Bytes, 20 | /// 字元串(尾端不一定會有EOS). 21 | /// 顯示字串 = 直接使用內含字元, 直到EOS or 最大長度. 22 | f9sv_FieldType_Chars, 23 | 24 | /// 整數欄位. 25 | /// >= f9sv_FieldType_Integer 之後皆為數字型別. 26 | f9sv_FieldType_Integer = 10, 27 | /// 固定小數位欄位: fon9::Decimal 28 | f9sv_FieldType_Decimal, 29 | /// 時間戳. 30 | f9sv_FieldType_TimeStamp, 31 | /// 時間間隔. 32 | f9sv_FieldType_TimeInterval, 33 | /// 時間: 距離 00:00:00 的時間間隔. 34 | /// 輸出格式 `days-hh:mm:ss.uuuuuu` 35 | f9sv_FieldType_DayTime, 36 | }; 37 | static inline int f9sv_IsFieldTypeNumber(f9sv_FieldType v) { 38 | return v >= f9sv_FieldType_Integer; 39 | } 40 | 41 | /// 小數位數. 42 | typedef uint8_t f9sv_DecScale; 43 | 44 | #ifdef __cplusplus 45 | }//extern "C" 46 | #endif 47 | #endif//__fon9_seed_FieldType_h__ 48 | -------------------------------------------------------------------------------- /fon9/seed/NamedPark.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/seed/NamedPark.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/seed/NamedPark.hpp" 4 | 5 | namespace fon9 { namespace seed { 6 | 7 | void ParkTree::OnMaTree_AfterRemove(Locker&, NamedSeed& seed) { 8 | this->Subj_.Publish(&seed, EventType::Remove); 9 | } 10 | void ParkTree::OnMaTree_AfterAdd(Locker&, NamedSeed& seed) { 11 | this->Subj_.Publish(&seed, EventType::Add); 12 | } 13 | void ParkTree::OnMaTree_AfterClear() { 14 | Locker locker{this->Container_}; 15 | this->Subj_.Publish(nullptr, EventType::Clear); 16 | } 17 | 18 | } } // namespaces 19 | -------------------------------------------------------------------------------- /fon9/seed/Raw.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/seed/Raw.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/seed/Raw.hpp" 4 | #include "fon9/Blob.h" 5 | 6 | namespace fon9 { namespace seed { 7 | 8 | Raw::~Raw() { 9 | if (uint32_t L = this->GetDyBlobCount()) { 10 | byte* blobPtr = reinterpret_cast(this) + this->DyMemPos_; 11 | do { 12 | // 為了避免 blobPtr 記憶體沒有對齊, 所以複製一份處理. 13 | fon9_Blob blob = GetUnaligned(reinterpret_cast(blobPtr)); 14 | fon9_Blob_Free(&blob); 15 | blobPtr += sizeof(fon9_Blob); 16 | } while (--L > 0); 17 | } 18 | } 19 | 20 | } } // namespaces 21 | -------------------------------------------------------------------------------- /fon9/seed/SeedAclTree.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/seed/SeedAclTree.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/seed/SeedAcl.hpp" 4 | #include "fon9/seed/FieldMaker.hpp" 5 | 6 | namespace fon9 { namespace seed { 7 | 8 | static Fields MakeAclTreeFields() { 9 | Fields fields; 10 | fields.Add(fon9_MakeField(AccessList::value_type, second.Rights_, "Rights")); 11 | fields.Add(fon9_MakeField(AccessList::value_type, second.MaxSubrCount_, "MaxSubrCount")); 12 | return fields; 13 | } 14 | static LayoutSP MakeAclTreeLayout(TabFlag tabFlags, TreeFlag treeFlags) { 15 | return LayoutSP{new Layout1(fon9_MakeField(AccessList::value_type, first, "Path"), 16 | new Tab{Named{"AclRights"}, MakeAclTreeFields(), tabFlags}, 17 | treeFlags)}; 18 | } 19 | fon9_API LayoutSP MakeAclTreeLayout() { 20 | static LayoutSP aclLayout{MakeAclTreeLayout(TabFlag::NoSapling, TreeFlag{})}; 21 | return aclLayout; 22 | } 23 | fon9_API LayoutSP MakeAclTreeLayoutWritable() { 24 | static LayoutSP aclLayout{MakeAclTreeLayout(TabFlag::NoSapling | TabFlag::Writable, TreeFlag::AddableRemovable)}; 25 | return aclLayout; 26 | } 27 | 28 | } } // namespaces 29 | -------------------------------------------------------------------------------- /fon9/seed/Tree.cpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/seed/Tree.cpp 2 | /// \author fonwinz@gmail.com 3 | #include "fon9/seed/Tree.hpp" 4 | 5 | namespace fon9 { namespace seed { 6 | 7 | Tree::~Tree() { 8 | } 9 | 10 | void Tree::OnTreeReleased() { 11 | if (this->use_count() == 0) 12 | delete this; 13 | } 14 | 15 | void Tree::OnTreeOp(FnTreeOp fnCallback) { 16 | fnCallback(TreeOpResult{this, OpResult::not_supported_tree_op}, nullptr); 17 | } 18 | 19 | void Tree::OnTabTreeOp(FnTreeOp fnCallback) { 20 | fnCallback(TreeOpResult{this, OpResult::not_supported_tree_op}, nullptr); 21 | } 22 | 23 | void Tree::OnParentSeedClear() { 24 | } 25 | 26 | } } // namespaces 27 | -------------------------------------------------------------------------------- /fon9/sys/OnWindowsMainExit.hpp: -------------------------------------------------------------------------------- 1 | /// \file fon9/sys/OnWindowsMainExit.hpp 2 | /// \author fonwinz@gmail.com 3 | #ifndef __fon9_sys_OnWindowsMainExit_hpp__ 4 | #define __fon9_sys_OnWindowsMainExit_hpp__ 5 | 6 | namespace fon9 { namespace sys { 7 | 8 | #if defined(_MSC_VER) && defined(_DLL) 9 | #define fon9_HAVE_OnWindowsMainExitHandle 10 | /// 如果 libfon9 是 Windows DLL, 則需要: 11 | /// - 在 exe.main() 結束後 & libfon9.dll 卸載前: 主動關閉 fon9 內部的 thread(例: MemBlock::Center). 12 | /// - 否則在 libfon9.dll 卸載前, thread 會被強制結束! 無法安全的清理 thread 裡面的資源! 13 | struct OnWindowsMainExitHandle { 14 | OnWindowsMainExitHandle(); 15 | virtual void OnWindowsMainExit_Notify() = 0; 16 | virtual void OnWindowsMainExit_ThreadJoin() = 0; 17 | protected: 18 | virtual ~OnWindowsMainExitHandle(); 19 | }; 20 | /// 通常在 API 結束時呼叫, 例如: RcClientApi.cpp: fon9_Finalize(); 21 | void OnWindowsMainExit_When_No_atexit(); 22 | #else 23 | struct OnWindowsMainExitHandle { 24 | }; 25 | #endif 26 | 27 | } } // namespaces 28 | 29 | #endif//__fon9_sys_OnWindowsMainExit_hpp__ 30 | -------------------------------------------------------------------------------- /fon9/web/HtmlEncoder.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/web/HtmlEncoder.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/web/HtmlEncoder.hpp" 4 | #include "fon9/RevPrint.hpp" 5 | 6 | namespace fon9 { namespace web { 7 | 8 | fon9_API void RevEncodeHtml(RevBuffer& rbuf, StrView str) { 9 | const char* const pbeg = str.begin(); 10 | for (const char* pend = str.end(); pend != pbeg;) { 11 | const char ch = *--pend; 12 | switch (ch) { 13 | case '&': RevPrint(rbuf, "&"); break; 14 | case '<': RevPrint(rbuf, "<"); break; 15 | case '>': RevPrint(rbuf, ">"); break; 16 | default: RevPutChar(rbuf, ch); break; 17 | } 18 | } 19 | } 20 | 21 | } } // namespace 22 | -------------------------------------------------------------------------------- /fon9/web/HtmlEncoder.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/web/HtmlEncoder.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_web_HtmlEncoder_hpp__ 4 | #define __fon9_web_HtmlEncoder_hpp__ 5 | #include "fon9/buffer/RevBuffer.hpp" 6 | 7 | namespace fon9 { namespace web { 8 | 9 | /// 將 str 的特殊字元(例: '<', '>', '&') 轉換成 HTML 編碼(例: "<", ">", "&"). 10 | fon9_API void RevEncodeHtml(RevBuffer& rbuf, StrView str); 11 | 12 | } } // namespaces 13 | #endif//__fon9_web_HtmlEncoder_hpp__ 14 | -------------------------------------------------------------------------------- /fon9/web/HttpDate.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/web/HttpDate.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_web_HttpDate_hpp__ 4 | #define __fon9_web_HttpDate_hpp__ 5 | #include "fon9/TimeStamp.hpp" 6 | 7 | namespace fon9 { namespace web { 8 | 9 | fon9_API TimeStamp HttpDateTo(StrView str); 10 | 11 | enum : size_t { 12 | kHttpDateWidth = sizeof("Sun, 06 Nov 1994 08:49:37 GMT") -1, 13 | }; 14 | /// day-name "," SP date1 SP time-of-day SP GMT 15 | fon9_API char* ToHttpDateRev(char* pout, TimeStamp ts); 16 | 17 | struct FmtHttpDate { 18 | TimeStamp TS_; 19 | }; 20 | inline char* ToStrRev(char* pout, const FmtHttpDate& httpts) { 21 | return ToHttpDateRev(pout, httpts.TS_); 22 | } 23 | 24 | } } // namespaces 25 | #endif//__fon9_web_HttpDate_hpp__ 26 | -------------------------------------------------------------------------------- /fon9/web/HttpParser.hpp: -------------------------------------------------------------------------------- 1 | // \file fon9/web/HttpParser.hpp 2 | // \author fonwinz@gmail.com 3 | #ifndef __fon9_web_HttpParser_hpp__ 4 | #define __fon9_web_HttpParser_hpp__ 5 | #include "fon9/web/HttpMessage.hpp" 6 | #include "fon9/buffer/DcQueue.hpp" 7 | 8 | namespace fon9 { namespace web { 9 | 10 | enum : size_t { 11 | /// strlen("chunk-size[chunk-ext]\r\n"); 12 | kHttpMaxChunkLineLength = 64, 13 | kHttpMaxChunkedSize = 1024 * 1024 * 8, 14 | }; 15 | 16 | enum class HttpResult { 17 | HeaderTooLarge = -1, 18 | BadChunked = -2, 19 | /// chunked size 超過 kHttpMaxChunkedSize 20 | ChunkSizeTooLarge = -3, 21 | ChunkSizeLineTooLong = -4, 22 | Incomplete = 0, 23 | FullMessage = 1, 24 | ChunkAppended = 2, 25 | }; 26 | 27 | struct fon9_API HttpParser { 28 | static HttpResult Feed(HttpMessage& msg, DcQueue& buf); 29 | static HttpResult ContinueEat(HttpMessage& msg); 30 | 31 | private: 32 | static HttpResult AfterFeedBody(HttpMessage& msg); 33 | static HttpResult AfterFeedHeader(HttpMessage& msg, size_t bfsz); 34 | static HttpResult ParseChunk(HttpMessage& msg); 35 | static HttpResult CheckChunkAppend(HttpMessage& msg); 36 | static HttpResult FetchNextChunkSize(HttpMessage& msg); 37 | static HttpResult FetchChunkTrailer(HttpMessage& msg); 38 | }; 39 | 40 | } } // namespaces 41 | #endif//__fon9_web_HttpParser_hpp__ 42 | -------------------------------------------------------------------------------- /fon9/web/UrlCodec.cpp: -------------------------------------------------------------------------------- 1 | // \file fon9/web/UrlCodec.cpp 2 | // \author fonwinz@gmail.com 3 | #include "fon9/web/UrlCodec.hpp" 4 | 5 | namespace fon9 { namespace web { 6 | 7 | fon9_API void UrlEncodeAppend(std::string& dst, const StrView& src) { 8 | UrlEncodeAppend(dst, src); 9 | } 10 | fon9_API void UrlEncodeAppend(CharVector& dst, const StrView& src) { 11 | UrlEncodeAppend(dst, src); 12 | } 13 | 14 | //--------------------------------------------------------------------------// 15 | 16 | fon9_API void UrlDecodeAppend(std::string& dst, const StrView& src) { 17 | UrlDecodeAppend(dst, src); 18 | } 19 | fon9_API void UrlDecodeAppend(CharVector& dst, const StrView& src) { 20 | UrlDecodeAppend(dst, src); 21 | } 22 | 23 | } } // namespace 24 | -------------------------------------------------------------------------------- /fon9/web/ma/gv.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fonwin/libfon9/c07ca2ffb3547a03a31c41db5ad036ab6ee859bc/fon9/web/ma/gv.css -------------------------------------------------------------------------------- /fon9/web/ma/logo-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fonwin/libfon9/c07ca2ffb3547a03a31c41db5ad036ab6ee859bc/fon9/web/ma/logo-40.png -------------------------------------------------------------------------------- /make_proj_verinfo.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM 在指定路徑建立 proj_verinfo.h: 4 | REM - Windows 在「Build Events/Pre-Build Event/Command Line」設定: 5 | REM cd 「proj_verinfo.h 存放路徑」 (例如 cd ..\..\..\YourProjectName) 6 | REM call ..\fon9\make_proj_verinfo.bat 7 | REM - 然後可以在程式裡將版本資放入 SysEnv: 8 | REM if (auto sysEnv = holder.Root_->Get(fon9_kCSTR_SysEnv_DefaultName)) 9 | REM fon9::seed::LogSysEnv(sysEnv->Add(new fon9::seed::SysEnvItem("Version", proj_VERSION)).get()); 10 | 11 | 12 | FOR /F "usebackq tokens=1,2 delims==" %%i IN (`wmic os get LocalDateTime/VALUE 2^>NUL`) DO IF '.%%i.'=='.LocalDateTime.' SET ldt=%%j 13 | SET ldt=%ldt:~0,4%.%ldt:~4,2%.%ldt:~6,2%-%ldt:~8,2%%ldt:~10,2% 14 | 15 | pushd %~dp0 16 | FOR /F "tokens=*" %%g IN ('git rev-parse "--short=12" HEAD') DO SET FON9_HASH=%%g 17 | popd 18 | 19 | FOR /F "tokens=*" %%g IN ('git rev-parse "--short=12" HEAD') DO SET MySln_HASH=%%g 20 | 21 | SET pwd=%CD% 22 | For %%A in ("%pwd%") do SET PROJ=%%~nxA 23 | 24 | echo #ifndef proj_NAME> proj_verinfo.h 25 | echo #define proj_NAME "%PROJ%">> proj_verinfo.h 26 | echo #endif>> proj_verinfo.h 27 | echo #define proj_VERSION proj_NAME "=%MySln_HASH%|fon9=%FON9_HASH%|build=%ldt%">> proj_verinfo.h 28 | 29 | -------------------------------------------------------------------------------- /make_proj_verinfo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # 在指定路徑建立 proj_verinfo.h: 5 | # - Linux 在 CMakeLists.txt 裡面執行: 6 | # execute_process(COMMAND "../fon9/make_proj_verinfo.sh" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 7 | # RESULT_VARIABLE ret) 8 | # if(NOT ret EQUAL 0) 9 | # message(FATAL_ERROR "Run make_proj_verionf.sh ERROR: " ${ret}) 10 | # endif() 11 | # 12 | # - 然後可以在程式裡將版本資放入 SysEnv: 13 | # if (auto sysEnv = holder.Root_->Get(fon9_kCSTR_SysEnv_DefaultName)) 14 | # fon9::seed::LogSysEnv(sysEnv->Add(new fon9::seed::SysEnvItem("Version", proj_VERSION)).get()); 15 | # 16 | 17 | pushd $(dirname "$0") 18 | FON9_HASH=`git rev-parse --short=12 HEAD | xargs` 19 | popd 20 | 21 | MySln_HASH=`git rev-parse --short=12 HEAD | xargs` 22 | 23 | BUILDTM=`date +"%Y.%m.%d-%H%M"` 24 | 25 | PROJ=`basename "${PWD}"` 26 | 27 | echo "#ifndef proj_NAME" > proj_verinfo.h 28 | echo "#define proj_NAME \"${PROJ}\"" >> proj_verinfo.h 29 | echo "#endif" >> proj_verinfo.h 30 | echo "#define proj_VERSION proj_NAME \"=${MySln_HASH}|fon9=${FON9_HASH}|build=${BUILDTM}\"" >> proj_verinfo.h 31 | -------------------------------------------------------------------------------- /make_static_o.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 因為無法指定 .a 檔案的 export symbols; (我不知到有什麼更簡單的方法). 4 | # 所以用底下的方法, 建立一個特殊的 .o 檔案, 用來取代 .a; 5 | # 執行時必須提供3個參數: 6 | # dst.o src.a 建立so時的version-script 7 | # 8 | 9 | set -e 10 | dst=$1 11 | src=$2 12 | expsrc=$3 13 | 14 | echo Building [$dst] for static link. 15 | 16 | tmpdir=$dst.tmpd 17 | rm -rf $tmpdir 18 | mkdir $tmpdir 19 | cp $src $tmpdir/tmp.a 20 | pushd $tmpdir >/dev/null 21 | ar x tmp.a 22 | ld -r -o tmp.ro *.o 23 | popd >/dev/null 24 | 25 | sed 's/[ {}]//g' $expsrc |sed 's/;/\n/g' >$tmpdir/exports.txt 26 | objcopy $tmpdir/tmp.ro $dst --keep-global-symbols=$tmpdir/exports.txt 27 | strip -x $dst 28 | 29 | rm -rf $tmpdir 30 | 31 | echo [$dst] is ready for static link. 32 | --------------------------------------------------------------------------------