From 3d00af282ffa9cd897ab745c84c8d5191d63d3f6 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Sun, 3 Mar 2024 13:42:55 +0100 Subject: [PATCH 1/4] delete unused Makefile It references a folder that it not there anymore. --- test/Makefile | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 test/Makefile diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index a99616f4..00000000 --- a/test/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -## libmatroska Makefile -## (c) 2002 Steve Lhomme -## This software is licensed under the LGPL, see LICENSE.LGPL - -all: endian - echo "Making endianess tests" - (cd endian; make) -clean: - echo "Cleaning all tests" - (cd endian; make $@) From 02811bb295bf6edc239836613b3d7bc687f1945f Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Sun, 3 Mar 2024 13:46:48 +0100 Subject: [PATCH 2/4] add libmatroska2 mkvtree ported to libmatroska --- CMakeLists.txt | 4 + test/mkvtree/mkvtree.cpp | 319 +++++++++++++++++++++++++++++++++++++++ test/mkvtree/porting.h | 304 +++++++++++++++++++++++++++++++++++++ 3 files changed, 627 insertions(+) create mode 100644 test/mkvtree/mkvtree.cpp create mode 100644 test/mkvtree/porting.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d97c2480..af7c3866 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,10 @@ if(NOT BUILD_SHARED_LIBS) endif() if(BUILD_EXAMPLES) + add_executable(mkvtree test/mkvtree/mkvtree.cpp) + target_link_libraries(mkvtree matroska) + target_include_directories(mkvtree PRIVATE $) + add_executable(test00 test/ebml/test00.cpp) target_link_libraries(test00 matroska) target_include_directories(test00 PRIVATE $) diff --git a/test/mkvtree/mkvtree.cpp b/test/mkvtree/mkvtree.cpp new file mode 100644 index 00000000..1b429c8a --- /dev/null +++ b/test/mkvtree/mkvtree.cpp @@ -0,0 +1,319 @@ +// Copyright © 2008-2024 Matroska (non-profit organisation). +// SPDX-License-Identifier: BSD-3-Clause + +#include "porting.h" + +using namespace libebml; + +static int ShowPos = 0; + +DEFINE_START_SEMANTIC(KaxStream) +DEFINE_SEMANTIC_ITEM(true, true, libebml::EbmlHead) +DEFINE_SEMANTIC_ITEM(true, true, libmatroska::KaxSegment) +DEFINE_END_SEMANTIC(KaxStream) + +DEFINE_xxx_CONTEXT(KaxStream,libmatroska::GetKaxGlobal_Context) + +#define MATROSKA_getContextStream() EBML_CLASS_SEMCONTEXT(KaxStream) + +#ifdef TARGET_WIN +#include +void DebugMessage(const tchar_t* Msg,...) +{ +#if !defined(NDEBUG) || defined(LOGFILE) || defined(LOGTIME) + va_list Args; + tchar_t Buffer[1024],*s=Buffer; + + va_start(Args,Msg); + vstprintf_s(Buffer,TSIZEOF(Buffer), Msg, Args); + va_end(Args); + tcscat_s(Buffer,TSIZEOF(Buffer),T("\r\n")); +#endif + +#ifdef LOGTIME + { + tchar_t timed[1024]; + SysTickToString(timed,TSIZEOF(timed),GetTimeTick(),1,1,0); + stcatprintf_s(timed,TSIZEOF(timed),T(" %s"),s); + s = timed; + } +#endif + +#if !defined(NDEBUG) + OutputDebugString(s); +#endif + +#if defined(LOGFILE) +{ + static FILE* f=NULL; + static char s8[1024]; + size_t i; + if (!f) + f=fopen("\\corelog.txt","a+b"); + for (i=0;s[i];++i) + s8[i]=(char)s[i]; + s8[i]=0; + fputs(s8,f); + fflush(f); +} +#endif +} +#endif + +static void EndLine(ebml_element *Element) +{ + if (ShowPos && EBML_ElementPosition(Element)!=INVALID_FILEPOS_T) + fprintf(stdout," at %" PRId64 "\r\n",EBML_ElementPosition(Element)); + else + fprintf(stdout,"\r\n"); +} + +static ebml_element *OutputElement(ebml_element *Element, const ebml_parser_context *Context, stream *Input, unsigned int *Level) +{ + assert(*Level < 10); // safety check + int LevelPrint; + for (LevelPrint=0;LevelPrint<*Level;++LevelPrint) + fprintf(stdout,"+ "); + fprintf(stdout,"%s: ", EBML_ElementGetClassName(Element)); + if (Node_IsPartOf(Element,EBML_MASTER_CLASS)) + { + int UpperElement = 0; + ebml_element *SubElement,*NewElement; + // ebml_parser_context SubContext; + + if (EBML_ElementDataSize(Element, 1) == INVALID_FILEPOS_T) + fprintf(stdout,"(master)"); + else if (!EBML_ElementIsFiniteSize(Element)) + fprintf(stdout,"(master) [unknown size]"); + else + fprintf(stdout,"(master) [%" PRId64 " bytes]",EBML_ElementDataSize(Element, 1)); + EndLine(Element); + // SubContext.UpContext = Context; + // SubContext.Context = EBML_ElementContext(Element); + // SubContext.EndPosition = EBML_ElementPositionEnd(Element); + // SubContext.Profile = Context->Profile; + // SubElement = EBML_FindNextElement(Input, &SubContext, &UpperElement, 1); + SubElement = EBML_FindNextElement(Input, EBML_ElementContext(Element), &UpperElement, 1); + while (SubElement != NULL && UpperElement<=0 && (!EBML_ElementIsFiniteSize(Element) || EBML_ElementPosition(SubElement) <= EBML_ElementPositionEnd(Element))) + { + // a sub element == not higher level and contained inside the current element + (*Level)++; + NewElement = OutputElement(SubElement, &EBML_ElementContext(Element), Input, Level); + NodeDelete((node*)SubElement); + if (NewElement) + SubElement = NewElement; + else + { + if (EBML_ElementIsFiniteSize(Element) && Input->I_O().getFilePointer() >= EBML_ElementPositionEnd(Element)) + { + SubElement = nullptr; + // break; + } + else + SubElement = EBML_FindNextElement(Input, EBML_ElementContext(Element), &UpperElement, 1); + } + assert(*Level > 0); + (*Level)--; + + if (UpperElement < 0) + { + // global element + // assert(*Level + UpperElement >= 0); + // *Level += UpperElement; + } + else if (UpperElement != 0 && *Level>0) + { + assert(*Level >= UpperElement-1); + *Level -= UpperElement-1; + } + } + return SubElement; + //EBML_ElementSkipData(Element, Input, Element->Context, NULL, 0); + } + else if (Node_IsPartOf(Element,EBML_VOID_CLASS)) + { + fprintf(stdout,"[%" PRId64 " bytes]",EBML_ElementDataSize(Element, 1)); + EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + EndLine(Element); + } + else if (Node_IsPartOf(Element,EBML_CRC_CLASS)) + { + // TODO: handle crc32 + fprintf(stdout,"[%" PRId64 " bytes]",EBML_ElementDataSize(Element, 1)); + EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + EndLine(Element); + } + else if (Node_IsPartOf(Element,EBML_STRING_CLASS) || Node_IsPartOf(Element,EBML_UNISTRING_CLASS)) + { + //tchar_t UnicodeString[MAXDATA]; + //EBML_StringRead((ebml_string*)Element,Input,UnicodeString,TSIZEOF(UnicodeString)); + if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) + { + tchar_t String[MAXDATA]; + char cString[MAXDATA]; + if (Node_IsPartOf(Element,EBML_STRING_CLASS)) + EBML_StringGet((ebml_string*)Element, String, TSIZEOF(String)); + else + EBML_StringGetUnicode((ebml_unistring*)Element, String, TSIZEOF(String)); + Node_ToUTF8(Element, cString, sizeof(cString), String); + fprintf(stdout,"'%s'",cString); + } else + fprintf(stdout,""); + EndLine(Element); + } + else if (Node_IsPartOf(Element,EBML_DATE_CLASS)) + { + if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) + { + datepack_t Date; + datetime_t DateTime = EBML_DateTime((ebml_date*)Element); + GetDatePacked(DateTime,&Date,1); + fprintf(stdout,"%04" PRIdPTR "-%02" PRIdPTR "-%02" PRIdPTR " %02" PRIdPTR ":%02" PRIdPTR ":%02" PRIdPTR " UTC",Date.Year,Date.Month,Date.Day,Date.Hour,Date.Minute,Date.Second); + } + else + fprintf(stdout,""); + EndLine(Element); + } + else if (Node_IsPartOf(Element,EBML_INTEGER_CLASS) || Node_IsPartOf(Element,EBML_SINTEGER_CLASS)) + { + if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) + { + if (Node_IsPartOf(Element,EBML_SINTEGER_CLASS)) + fprintf(stdout,"%" PRId64,EBML_IntegerValue((ebml_integer*)Element)); + else + fprintf(stdout,"%" PRIu64,EBML_IntegerValue((ebml_integer*)Element)); + } + else + fprintf(stdout,""); + EndLine(Element); + } + else if (Node_IsPartOf(Element,EBML_FLOAT_CLASS)) + { + if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) + fprintf(stdout,"%f",EBML_FloatValue((ebml_float*)Element)); + else + fprintf(stdout,""); + EndLine(Element); + } + else if (EBML_ElementIsDummy(Element)) + { + fprintf(stdout,"[%X] [%" PRId64 " bytes]",EBML_ElementClassID(Element),EBML_ElementDataSize(Element, 1)); + EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + EndLine(Element); + } + else if (Node_IsPartOf(Element,EBML_BINARY_CLASS)) + { + if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_PARTIAL_DATA,0)==ERR_NONE) + { + const uint8_t *Data = EBML_BinaryGetData((ebml_binary*)Element); + if (EBML_ElementDataSize(Element, 1) != 0) + { + if (Data==NULL) + fprintf(stdout,"[data too large] (%" PRId64 ")",EBML_ElementDataSize(Element, 1)); + else if (EBML_ElementDataSize(Element, 1) == 1) + fprintf(stdout,"%02X (%" PRId64 ")",Data[0],EBML_ElementDataSize(Element, 1)); + else if (EBML_ElementDataSize(Element, 1) == 2) + fprintf(stdout,"%02X %02X (%" PRId64 ")",Data[0],Data[1],EBML_ElementDataSize(Element, 1)); + else if (EBML_ElementDataSize(Element, 1) == 3) + fprintf(stdout,"%02X %02X %02X (%" PRId64 ")",Data[0],Data[1],Data[2],EBML_ElementDataSize(Element, 1)); + else if (EBML_ElementDataSize(Element, 1) == 4) + fprintf(stdout,"%02X %02X %02X %02X (%" PRId64 ")",Data[0],Data[1],Data[2],Data[3],EBML_ElementDataSize(Element, 1)); + else + fprintf(stdout,"%02X %02X %02X %02X.. (%" PRId64 ")",Data[0],Data[1],Data[2],Data[3],EBML_ElementDataSize(Element, 1)); + } + } + else + fprintf(stdout,""); + EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + EndLine(Element); + } + else + { +#ifdef IS_BIG_ENDIAN + fprintf(stdout,"\r\n",EBML_ElementClassID(Element)); +#else + fourcc_t Id = EBML_ElementClassID(Element); + fprintf(stdout,">= 8; + } + fprintf(stdout,"%X>",EBML_ElementClassID(Element)); +#endif + EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + EndLine(Element); + } + return NULL; +} + +static void OutputEbmlhead(stream *Input) +{ + // ebml_element *Element = EBML_ElementCreate(Input,libebml::EbmlHead,0,PROFILE_MATROSKA_ANY,NULL); + ebml_element *Element = Input->FindNextID(UINT64_MAX); + // ebml_element *Element = EBML_FindNextElement(Input, EBML_CONTEXT(libebml::EbmlHead), &UpperElement, 1); + if (Element) + { + unsigned int Level = 0; + // EBML_ElementSetInfiniteSize(Element,1); + OutputElement(Element, NULL, Input, &Level); + NodeDelete((node*)Element); + } +} + +static void OutputTree(stream *Input) +{ + // ebml_element *Element = EBML_ElementCreate(Input,libmatroska::KaxSegment,0,PROFILE_MATROSKA_ANY,NULL); + ebml_element *Element = Input->FindNextID(UINT64_MAX); + // ebml_element *Element = EBML_FindNextElement(Input, EBML_CONTEXT(libmatroska::KaxSegment), &UpperElement, 1); + if (Element) + { + unsigned int Level = 0; + // EBML_ElementSetInfiniteSize(Element,1); + OutputElement(Element, NULL, Input, &Level); + NodeDelete((node*)Element); + } +} + +int main(int argc, const char *argv[]) +{ + // parsercontext p; + stream *Input; + tchar_t Path[MAXPATHFULL]; + + if ((argc!=2 && argc!=3) || (argc==3 && strcmp(argv[1],"--pos"))) + { + fprintf(stderr, "Usage: mkvtree --pos [matroska_file]\r\n"); + fprintf(stderr, "Options:\r\n"); + fprintf(stderr, " --pos output the position of elements\r\n"); + return 1; + } + + if (argc==3) + ShowPos = 1; + + // Core-C init phase + ParserContext_Init(&p,NULL,NULL,NULL); + // EBML & Matroska Init + MATROSKA_Init(&p); + + // open the file to parse + Node_FromStr(&p,Path,TSIZEOF(Path),argv[argc-1]); + Input = StreamOpen(&p,Path,SFLAG_RDONLY/*|SFLAG_BUFFERED*/); + if (Input == NULL) + fprintf(stderr, "error: mkvtree cannot open file \"%s\"\r\n",argv[1]); + else + { + OutputEbmlhead(Input); + OutputTree(Input); + + StreamClose(Input); + } + + // EBML & Matroska ending + MATROSKA_Done(&p); + // Core-C ending + ParserContext_Done(&p); + + return 0; +} diff --git a/test/mkvtree/porting.h b/test/mkvtree/porting.h new file mode 100644 index 00000000..535a31d2 --- /dev/null +++ b/test/mkvtree/porting.h @@ -0,0 +1,304 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// FIXME remove ? +using tchar_t = char; +#define T(x) x +#define TSIZEOF(x) sizeof(x) +#define TPRId64 PRId64 +#define TPRIx64 PRIx64 +#define tcslen(s) strlen(s) +#define tcscpy_s(d,dn,s) strcpy(d,s) +#define tcscat_s(d,dn,s) strcat(d,s) +#define tcscmp(a,b) strcmp(a,b) +#define tcsnicmp_ascii(a,b,n) strncmp(a,b,n) +#define stprintf_s std::snprintf +#define stcatprintf_s(d,dn,f,a1) std::snprintf(d+tcslen(d),dn-tcslen(d),f,a1) +#define stcatprintf_s2(d,dn,f,a1,a2) std::snprintf(d+tcslen(d),dn-tcslen(d),f,a1,a2) +#define StringToInt(s,r) std::atoi(s) + +#define TextPrintf fprintf +#define TextWrite fprintf +using textwriter = FILE; +#define StdErr stderr + +#define SFLAG_RDONLY MODE_READ +#define SFLAG_WRONLY MODE_WRITE +#define SFLAG_CREATE MODE_CREATE +#define StreamOpen(c,p,f) new libebml::EbmlStream(*(new libebml::StdIOCallback(p, (libebml::open_mode)(f)))) +static inline void StreamClose(libebml::EbmlStream *s) +{ + s->I_O().close(); + delete &(s->I_O()); + delete s; +} +static inline libebml::filepos_t Stream_Seek(libebml::IOCallback *s, std::uint64_t l, int w) +{ + (s)->setFilePointer(l,(libebml::seek_mode)w); + return (s)->getFilePointer(); +} +#define Stream_Write(s,b,l,p) (s)->writeFully(b,l) + +#define Node_FromStr(c,d,dn,s) strcpy(d,s) +#define Node_FromUTF8(c,d,dn,s) strcpy(d,s) +#define Node_ToUTF8(c,d,dn,s) strcpy(d,s) + +#define MAXPATH 1024 +#define MAXPATHFULL 1024 +#define MAXLINE 2048 +#define MAXDATA 2048 + +using bool_t = bool; + +#define ARRAYBEGIN(v,t) (v).begin() +#define ARRAYEND(v,t) (v).end() +#define ARRAYCOUNT(v,t) (v).size() +#define ARRAYAT(v,t,i) (&((v).at(i))) +#define ArrayInit(v) (v)->clear() +#define ArrayClear(v) (v)->clear() +#define ArrayResize(v,s,t,a) (v)->resize(s) +#define ArrayRemove(v,t,i,c,o) // TODO +#define ArrayZero(v) // nothing, it's always used after resize +#define ArrayAppend(v,e,s,a) (v)->push_back(e) +#define ArrayShrink(v,l) (v)->resize((v)->size() - l); (v)->shrink_to_fit() + +#define NodeDelete(o) delete o + +using ebml_element = libebml::EbmlElement; +using ebml_master = libebml::EbmlMaster; +using ebml_integer = libebml::EbmlUInteger; +using ebml_float = libebml::EbmlFloat; +using ebml_string = libebml::EbmlString; +using ebml_unistring = libebml::EbmlUnicodeString; +using ebml_date = libebml::EbmlDate; +using ebml_binary = libebml::EbmlBinary; +using nodetree = libebml::EbmlMaster; + +using matroska_cluster = libmatroska::KaxCluster; + +using EBML_MASTER_CLASS = libebml::EbmlMaster; +using EBML_STRING_CLASS = libebml::EbmlString; +using EBML_UNISTRING_CLASS = libebml::EbmlUnicodeString; +using EBML_DATE_CLASS = libebml::EbmlDate; +using EBML_SINTEGER_CLASS = libebml::EbmlSInteger; +using EBML_INTEGER_CLASS = libebml::EbmlUInteger; +using EBML_FLOAT_CLASS = libebml::EbmlFloat; +using EBML_BINARY_CLASS = libebml::EbmlBinary; +using EBML_VOID_CLASS = libebml::EbmlVoid; +using EBML_CRC_CLASS = libebml::EbmlCrc32; + +#define Node_IsPartOf(n,c) (dynamic_cast(n) != nullptr) + +using node = libebml::EbmlElement; +using fourcc_t = std::uint32_t; + +using ebml_parser_context = libebml::EbmlSemanticContext; +using parsercontext = void *; +#define ParserContext_Init(a,b,c,d) +#define ParserContext_Done(c) +#define EBML_Init(x) +#define EBML_Done(x) +#define MATROSKA_Init(x) +#define MATROSKA_Done(x) + +using stream = libebml::EbmlStream; + +#define ERR_NONE (!INVALID_FILEPOS_T) +#define ERR_INVALID_DATA INVALID_FILEPOS_T +using err_t = libebml::filepos_t; + +#define EBML_getContextHead() libebml::EbmlHead +#define EBML_getContextReadVersion() libebml::EReadVersion +#define EBML_getContextMaxIdLength() libebml::EMaxIdLength +#define EBML_getContextMaxSizeLength() libebml::EMaxSizeLength +#define EBML_getContextDocType() libebml::EDocType +#define EBML_getContextDocTypeVersion() libebml::EDocTypeVersion +#define EBML_getContextDocTypeReadVersion() libebml::EDocTypeReadVersion +#define EBML_getContextEbmlVoid() libebml::EbmlVoid + +#define MATROSKA_getContextInfo() libmatroska::KaxInfo +#define MATROSKA_getContextTimestampScale() libmatroska::KaxTimestampScale +#define MATROSKA_getContextSeek() libmatroska::KaxSeek +#define MATROSKA_getContextSegment() libmatroska::KaxSegment +#define MATROSKA_getContextSeekID() libmatroska::KaxSeekID +#define MATROSKA_getContextSeekPosition() libmatroska::KaxSeekPosition +#define MATROSKA_getContextBlock() libmatroska::KaxBlock +#define MATROSKA_getContextSimpleBlock() libmatroska::KaxSimpleBlock +#define MATROSKA_getContextBlockGroup() libmatroska::KaxBlockGroup +#define MATROSKA_getContextTrackNumber() libmatroska::KaxTrackNumber + +#define EBML_CodedSizeLength CodedSizeLength + +#define EBML_ElementCreate(n,c,d,p,o) new (c)() + +#define EBML_ElementGetName(e,d,dn) strcpy(d,EBML_NAME(e)) +#define EBML_ElementClassID(e) (*e).GetClassId().GetValue() +#define EBML_ElementPosition(e) (e)->GetElementPosition() +#define EBML_ElementDataSize(e,u) (e)->GetSize() +#define EBML_ElementFullSize(e,u) (e)->ElementSize((u != 0) ? libebml::EbmlElement::WriteAll : libebml::EbmlElement::WriteSkipDefault) +#define EBML_ElementPositionEnd(e) (e)->GetEndPosition() +#define EBML_ElementPositionData(e) ((e)->GetEndPosition() - (e)->GetSize()) +#define EBML_ElementIsType(e,t) ((e)->GetClassId() == EBML_ID(t)) +#define EBML_ElementGetClassName(e) EBML_NAME(e) +#define EBML_ElementContext(e) EBML_CONTEXT(e) +#define EBML_ElementIsDummy(e) (e)->IsDummy() +#define EBML_ElementReadData(e,i,b,c,s,f) (e)->ReadData(*i,s), ERR_NONE +#define EBML_ElementSkipData(e,s,c,p,d) (e)->SkipData(*(s),c,p,d) +#define EBML_FindNextElement(stream, sem, level, dummy) (stream)->FindNextElement(sem, *level, UINT64_MAX, dummy) +#define EBML_ElementSizeLength(e) (e)->GetSizeLength() +#define EBML_ElementSetSizeLength(e,s) (e)->SetSizeLength(s) +#define EBML_ElementIsFiniteSize(e) (e)->IsFiniteSize() +#define EBML_ElementSetInfiniteSize(e,i) (e)->SetSizeInfinite(i) +#define EBML_ElementUpdateSize(e,d,f,p) (e)->UpdateSize(p,f) +#define EBML_ElementForceDataSize(e,s) (e)->ForceSize(s) +#define EBML_ElementForcePosition(e,p) (e)->ForcePosition(p) +#define EBML_ElementForceContext(e,c) // FIXME turn OldStereo to new Stereo +static inline err_t EBML_ElementRenderHead(libebml::EbmlMaster *e, libebml::IOCallback *o, bool_t bKeepPosition, libebml::filepos_t *Rendered, const libebml::EbmlElement::ShouldWrite &p) +{ + return (e)->WriteHead(*o, 0, p); +} + +static inline std::vector::iterator EBML_MasterChildren(ebml_master * m) +{ + return m->begin(); +} +static inline std::vector::const_iterator EBML_MasterChildren(const ebml_master * m) +{ + return m->begin(); +} +static inline std::vector::iterator EBML_MasterChildren(matroska_cluster * c) +{ + return reinterpret_cast(c).begin(); +} + +static inline bool EBML_MasterEnd(std::vector::iterator i, ebml_master * m) +{ + return i != (m)->end(); +} +static inline bool EBML_MasterEnd(std::vector::const_iterator i, const ebml_master * m) +{ + return i != (m)->end(); +} +static inline bool EBML_MasterEnd(std::vector::iterator i, matroska_cluster * c) +{ + return i != reinterpret_cast(c).end(); +} +static inline bool EBML_MasterEnd(std::vector::const_iterator i, const matroska_cluster * c) +{ + return i != reinterpret_cast(c).end(); +} + +#define EBML_MasterNext(i) (i)++ +#define EBML_MasterEmpty(m) ((static_cast(m))->begin() == (static_cast(m))->end()) +#define EBML_MasterRemove(m,e) (m)->Remove(e) +#define EBML_MasterAppend(m,e) (m)->PushElement(*(e)) + +#define EBML_MasterFindChild(m,c) FindChild(*(libebml::EbmlMaster *)(m)) +#define EBML_MasterGetChild(m,c,u) &GetChild(*(libebml::EbmlMaster *)(m)) +#define EBML_MasterNextChild(m,p) FindNextChild(*(libebml::EbmlMaster *)(m), *p) +#define EBML_MasterIsChecksumValid(m) (m)->VerifyChecksum() +#define EBML_MasterFindFirstElt(m,c,n,d,p) &GetChild(*(libebml::EbmlMaster *)(m)) +#define EBML_MasterAddElt(m,c,d,p) (m)->AddNewElt(EBML_INFO(c)) + +#define NodeTree_Clear(m) (m)->RemoveAll() +#define NodeTree_SetParent(e,p,u) (static_cast(p))->PushElement(*(e)) + +#define EBML_IntegerValue(e) (reinterpret_cast(e))->GetValue() +#define EBML_IntegerSetValue(e,v) (reinterpret_cast(e))->SetValue(v) + +#define EBML_StringGet(e,d,dn) strcpy(d,(e)->GetValue().c_str()) +#define EBML_StringGetUnicode(e,d,dn) strcpy(d,(e)->GetValueUTF8().c_str()) +static inline err_t EBML_StringSetValue(libebml::EbmlString *e, const char *v) +{ + (e)->SetValue(v); + return ERR_NONE; +} +static inline err_t EBML_UniStringSetValue(libebml::EbmlUnicodeString *e, const char *v) +{ + (e)->SetValueUTF8(v); + return ERR_NONE; +} + +#define EBML_FloatValue(e) (reinterpret_cast(e))->GetValue() +#define EBML_FloatSetValue(e,v) (e)->SetValue(v) + +#define EBML_BinaryGetData(e) (e)->GetBuffer() + + + +////// ebml_date /////// + +#include + +using datetime_t = time_t; +struct datepack_t +{ + intptr_t Year; // 2001, 2007, etc + intptr_t Month; // 1-12 + intptr_t Day; // 1-31 + intptr_t Hour; // 24-hour + intptr_t Minute; // 0-59 + intptr_t Second; // 0-59 + intptr_t WeekDay; // 1 = Sunday, 2 = Monday, etc +}; + +static inline datetime_t GetTimeDate() +{ + return time(NULL); +} + +static inline void EBML_DateSetDateTime(libebml::EbmlDate *e, datetime_t d) +{ + e->SetEpochDate(d); +} + +#define EBML_DateTime(d) ((d)->GetValue() / UINT64_C(1'000'000'000)) + +#define INVALID_DATETIME_T 0 +#define DATETIME_OFFSET 0x3A4FC880 + +static inline bool_t GetDatePacked(datetime_t t, datepack_t *tp, bool_t Local) +{ + time_t ot; + struct tm *date; + + if (!tp || t == INVALID_DATETIME_T) + return 0; + + ot = t + DATETIME_OFFSET; + if (Local) + date = localtime(&ot); + else + date = gmtime(&ot); + + if (date) + { + tp->Second = date->tm_sec; + tp->Minute = date->tm_min; + tp->Hour = date->tm_hour; + tp->Day = date->tm_mday; + tp->Month = date->tm_mon + 1; + tp->Year = date->tm_year + 1900; + tp->WeekDay = date->tm_wday + 1; + return 1; + } + + return 0; +} From c69b33ae97463030e2ef71dfc90929ef2bd445e9 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Sun, 3 Mar 2024 14:28:01 +0100 Subject: [PATCH 3/4] mkvtree: only use libebml/libmatroska API's replace the ported API's to the actual API's. --- test/mkvtree/mkvtree.cpp | 265 ++++++++++++++++------------------ test/mkvtree/porting.h | 304 --------------------------------------- 2 files changed, 123 insertions(+), 446 deletions(-) delete mode 100644 test/mkvtree/porting.h diff --git a/test/mkvtree/mkvtree.cpp b/test/mkvtree/mkvtree.cpp index 1b429c8a..9e22c898 100644 --- a/test/mkvtree/mkvtree.cpp +++ b/test/mkvtree/mkvtree.cpp @@ -1,116 +1,103 @@ // Copyright © 2008-2024 Matroska (non-profit organisation). // SPDX-License-Identifier: BSD-3-Clause -#include "porting.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include using namespace libebml; static int ShowPos = 0; +#if 0 // TODO allowing find top level elements using an EbmlSemanticContextMaster DEFINE_START_SEMANTIC(KaxStream) DEFINE_SEMANTIC_ITEM(true, true, libebml::EbmlHead) DEFINE_SEMANTIC_ITEM(true, true, libmatroska::KaxSegment) DEFINE_END_SEMANTIC(KaxStream) DEFINE_xxx_CONTEXT(KaxStream,libmatroska::GetKaxGlobal_Context) - -#define MATROSKA_getContextStream() EBML_CLASS_SEMCONTEXT(KaxStream) - -#ifdef TARGET_WIN -#include -void DebugMessage(const tchar_t* Msg,...) -{ -#if !defined(NDEBUG) || defined(LOGFILE) || defined(LOGTIME) - va_list Args; - tchar_t Buffer[1024],*s=Buffer; - - va_start(Args,Msg); - vstprintf_s(Buffer,TSIZEOF(Buffer), Msg, Args); - va_end(Args); - tcscat_s(Buffer,TSIZEOF(Buffer),T("\r\n")); -#endif - -#ifdef LOGTIME - { - tchar_t timed[1024]; - SysTickToString(timed,TSIZEOF(timed),GetTimeTick(),1,1,0); - stcatprintf_s(timed,TSIZEOF(timed),T(" %s"),s); - s = timed; - } -#endif - -#if !defined(NDEBUG) - OutputDebugString(s); #endif -#if defined(LOGFILE) +struct datepack_t { - static FILE* f=NULL; - static char s8[1024]; - size_t i; - if (!f) - f=fopen("\\corelog.txt","a+b"); - for (i=0;s[i];++i) - s8[i]=(char)s[i]; - s8[i]=0; - fputs(s8,f); - fflush(f); -} -#endif -} -#endif + intptr_t Year; // 2001, 2007, etc + intptr_t Month; // 1-12 + intptr_t Day; // 1-31 + intptr_t Hour; // 24-hour + intptr_t Minute; // 0-59 + intptr_t Second; // 0-59 + intptr_t WeekDay; // 1 = Sunday, 2 = Monday, etc +}; + -static void EndLine(ebml_element *Element) +static void EndLine(EbmlElement *Element) { - if (ShowPos && EBML_ElementPosition(Element)!=INVALID_FILEPOS_T) - fprintf(stdout," at %" PRId64 "\r\n",EBML_ElementPosition(Element)); + if (ShowPos && (Element)->GetElementPosition()!=INVALID_FILEPOS_T) + fprintf(stdout," at %" PRId64 "\r\n",(Element)->GetElementPosition()); else fprintf(stdout,"\r\n"); } -static ebml_element *OutputElement(ebml_element *Element, const ebml_parser_context *Context, stream *Input, unsigned int *Level) +static EbmlElement *OutputElement(EbmlElement *Element, const EbmlSemanticContext *Context, EbmlStream *Input, unsigned int *Level) { assert(*Level < 10); // safety check - int LevelPrint; + unsigned int LevelPrint; for (LevelPrint=0;LevelPrint<*Level;++LevelPrint) fprintf(stdout,"+ "); - fprintf(stdout,"%s: ", EBML_ElementGetClassName(Element)); - if (Node_IsPartOf(Element,EBML_MASTER_CLASS)) + fprintf(stdout,"%s: ", EBML_NAME(Element)); + if (dynamic_cast(Element) != nullptr) { int UpperElement = 0; - ebml_element *SubElement,*NewElement; - // ebml_parser_context SubContext; + EbmlElement *SubElement,*NewElement; + // EbmlSemanticContext SubContext; - if (EBML_ElementDataSize(Element, 1) == INVALID_FILEPOS_T) + if (Element->GetSize() == INVALID_FILEPOS_T) fprintf(stdout,"(master)"); - else if (!EBML_ElementIsFiniteSize(Element)) + else if (!(Element)->IsFiniteSize()) fprintf(stdout,"(master) [unknown size]"); else - fprintf(stdout,"(master) [%" PRId64 " bytes]",EBML_ElementDataSize(Element, 1)); + fprintf(stdout,"(master) [%" PRId64 " bytes]",Element->GetSize()); EndLine(Element); // SubContext.UpContext = Context; - // SubContext.Context = EBML_ElementContext(Element); - // SubContext.EndPosition = EBML_ElementPositionEnd(Element); + // SubContext.Context = EBML_CONTEXT(Element); + // SubContext.EndPosition = Element->GetEndPosition(); // SubContext.Profile = Context->Profile; // SubElement = EBML_FindNextElement(Input, &SubContext, &UpperElement, 1); - SubElement = EBML_FindNextElement(Input, EBML_ElementContext(Element), &UpperElement, 1); - while (SubElement != NULL && UpperElement<=0 && (!EBML_ElementIsFiniteSize(Element) || EBML_ElementPosition(SubElement) <= EBML_ElementPositionEnd(Element))) + SubElement = Input->FindNextElement(EBML_CONTEXT(Element), UpperElement, UINT64_MAX, true); + while (SubElement != NULL && UpperElement<=0 && (!(Element)->IsFiniteSize() || (SubElement)->GetElementPosition() <= Element->GetEndPosition())) { // a sub element == not higher level and contained inside the current element (*Level)++; - NewElement = OutputElement(SubElement, &EBML_ElementContext(Element), Input, Level); - NodeDelete((node*)SubElement); + NewElement = OutputElement(SubElement, &EBML_CONTEXT(Element), Input, Level); + delete SubElement; if (NewElement) SubElement = NewElement; else { - if (EBML_ElementIsFiniteSize(Element) && Input->I_O().getFilePointer() >= EBML_ElementPositionEnd(Element)) + if ((Element)->IsFiniteSize() && Input->I_O().getFilePointer() >= Element->GetEndPosition()) { SubElement = nullptr; // break; } else - SubElement = EBML_FindNextElement(Input, EBML_ElementContext(Element), &UpperElement, 1); + SubElement = Input->FindNextElement(EBML_CONTEXT(Element), UpperElement, UINT64_MAX, true); } assert(*Level > 0); (*Level)--; @@ -123,108 +110,119 @@ static ebml_element *OutputElement(ebml_element *Element, const ebml_parser_cont } else if (UpperElement != 0 && *Level>0) { - assert(*Level >= UpperElement-1); + assert((int)*Level >= UpperElement-1); *Level -= UpperElement-1; } } return SubElement; //EBML_ElementSkipData(Element, Input, Element->Context, NULL, 0); } - else if (Node_IsPartOf(Element,EBML_VOID_CLASS)) + else if (dynamic_cast(Element) != nullptr) { - fprintf(stdout,"[%" PRId64 " bytes]",EBML_ElementDataSize(Element, 1)); - EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + fprintf(stdout,"[%" PRId64 " bytes]",Element->GetSize()); + Element->SkipData(*Input, *Context, nullptr, 0); EndLine(Element); } - else if (Node_IsPartOf(Element,EBML_CRC_CLASS)) + else if (dynamic_cast(Element) != nullptr) { // TODO: handle crc32 - fprintf(stdout,"[%" PRId64 " bytes]",EBML_ElementDataSize(Element, 1)); - EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + fprintf(stdout,"[%" PRId64 " bytes]",Element->GetSize()); + Element->SkipData(*Input, *Context, nullptr, 0); EndLine(Element); } - else if (Node_IsPartOf(Element,EBML_STRING_CLASS) || Node_IsPartOf(Element,EBML_UNISTRING_CLASS)) + else if (dynamic_cast(Element) != nullptr || dynamic_cast(Element) != nullptr) { //tchar_t UnicodeString[MAXDATA]; - //EBML_StringRead((ebml_string*)Element,Input,UnicodeString,TSIZEOF(UnicodeString)); - if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) + if (Element->ReadData(Input->I_O(),SCOPE_ALL_DATA) != INVALID_FILEPOS_T) { - tchar_t String[MAXDATA]; - char cString[MAXDATA]; - if (Node_IsPartOf(Element,EBML_STRING_CLASS)) - EBML_StringGet((ebml_string*)Element, String, TSIZEOF(String)); + if (dynamic_cast(Element) != nullptr) + fprintf(stdout,"'%s'",static_cast(Element)->GetValue().c_str()); else - EBML_StringGetUnicode((ebml_unistring*)Element, String, TSIZEOF(String)); - Node_ToUTF8(Element, cString, sizeof(cString), String); - fprintf(stdout,"'%s'",cString); + fprintf(stdout,"'%s'",static_cast(Element)->GetValueUTF8().c_str()); } else fprintf(stdout,""); EndLine(Element); } - else if (Node_IsPartOf(Element,EBML_DATE_CLASS)) + else if (dynamic_cast(Element) != nullptr) { - if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) + if (Element->ReadData(Input->I_O(),SCOPE_ALL_DATA) != INVALID_FILEPOS_T) { + auto DateTime = static_cast(Element)->GetEpochDate(); datepack_t Date; - datetime_t DateTime = EBML_DateTime((ebml_date*)Element); - GetDatePacked(DateTime,&Date,1); + time_t ot; + struct tm *date; + + ot = DateTime; + date = localtime(&ot); + + if (date) + { + Date.Second = date->tm_sec; + Date.Minute = date->tm_min; + Date.Hour = date->tm_hour; + Date.Day = date->tm_mday; + Date.Month = date->tm_mon + 1; + Date.Year = date->tm_year + 1900; + Date.WeekDay = date->tm_wday + 1; + } + fprintf(stdout,"%04" PRIdPTR "-%02" PRIdPTR "-%02" PRIdPTR " %02" PRIdPTR ":%02" PRIdPTR ":%02" PRIdPTR " UTC",Date.Year,Date.Month,Date.Day,Date.Hour,Date.Minute,Date.Second); } else fprintf(stdout,""); EndLine(Element); } - else if (Node_IsPartOf(Element,EBML_INTEGER_CLASS) || Node_IsPartOf(Element,EBML_SINTEGER_CLASS)) + else if (dynamic_cast(Element) != nullptr || dynamic_cast(Element) != nullptr) { - if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) + if (Element->ReadData(Input->I_O(),SCOPE_ALL_DATA) != INVALID_FILEPOS_T) { - if (Node_IsPartOf(Element,EBML_SINTEGER_CLASS)) - fprintf(stdout,"%" PRId64,EBML_IntegerValue((ebml_integer*)Element)); + if (dynamic_cast(Element) != nullptr) + fprintf(stdout,"%" PRId64,static_cast(Element)->GetValue()); else - fprintf(stdout,"%" PRIu64,EBML_IntegerValue((ebml_integer*)Element)); + fprintf(stdout,"%" PRIu64,static_cast(Element)->GetValue()); } else fprintf(stdout,""); EndLine(Element); } - else if (Node_IsPartOf(Element,EBML_FLOAT_CLASS)) + else if (dynamic_cast(Element) != nullptr) { - if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_ALL_DATA,0)==ERR_NONE) - fprintf(stdout,"%f",EBML_FloatValue((ebml_float*)Element)); + if (Element->ReadData(Input->I_O(),SCOPE_ALL_DATA) != INVALID_FILEPOS_T) + fprintf(stdout,"%f",static_cast(Element)->GetValue()); else fprintf(stdout,""); EndLine(Element); } - else if (EBML_ElementIsDummy(Element)) + else if (Element->IsDummy()) { - fprintf(stdout,"[%X] [%" PRId64 " bytes]",EBML_ElementClassID(Element),EBML_ElementDataSize(Element, 1)); - EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + fprintf(stdout,"[%X] [%" PRId64 " bytes]",static_cast(Element)->GetClassId().GetValue(),Element->GetSize()); + Element->SkipData(*Input, *Context, nullptr, 0); EndLine(Element); } - else if (Node_IsPartOf(Element,EBML_BINARY_CLASS)) + else if (dynamic_cast(Element) != nullptr) { - if (EBML_ElementReadData(Element,Input,NULL,0,SCOPE_PARTIAL_DATA,0)==ERR_NONE) + if (Element->ReadData(Input->I_O(),SCOPE_PARTIAL_DATA) != INVALID_FILEPOS_T) { - const uint8_t *Data = EBML_BinaryGetData((ebml_binary*)Element); - if (EBML_ElementDataSize(Element, 1) != 0) + const uint8_t *Data = static_cast(Element)->GetBuffer(); + if (Element->GetSize() != 0) { if (Data==NULL) - fprintf(stdout,"[data too large] (%" PRId64 ")",EBML_ElementDataSize(Element, 1)); - else if (EBML_ElementDataSize(Element, 1) == 1) - fprintf(stdout,"%02X (%" PRId64 ")",Data[0],EBML_ElementDataSize(Element, 1)); - else if (EBML_ElementDataSize(Element, 1) == 2) - fprintf(stdout,"%02X %02X (%" PRId64 ")",Data[0],Data[1],EBML_ElementDataSize(Element, 1)); - else if (EBML_ElementDataSize(Element, 1) == 3) - fprintf(stdout,"%02X %02X %02X (%" PRId64 ")",Data[0],Data[1],Data[2],EBML_ElementDataSize(Element, 1)); - else if (EBML_ElementDataSize(Element, 1) == 4) - fprintf(stdout,"%02X %02X %02X %02X (%" PRId64 ")",Data[0],Data[1],Data[2],Data[3],EBML_ElementDataSize(Element, 1)); + fprintf(stdout,"[data too large] (%" PRId64 ")",Element->GetSize()); + else if (Element->GetSize() == 1) + fprintf(stdout,"%02X (%" PRId64 ")",Data[0],Element->GetSize()); + else if (Element->GetSize() == 2) + fprintf(stdout,"%02X %02X (%" PRId64 ")",Data[0],Data[1],Element->GetSize()); + else if (Element->GetSize() == 3) + fprintf(stdout,"%02X %02X %02X (%" PRId64 ")",Data[0],Data[1],Data[2],Element->GetSize()); + else if (Element->GetSize() == 4) + fprintf(stdout,"%02X %02X %02X %02X (%" PRId64 ")",Data[0],Data[1],Data[2],Data[3],Element->GetSize()); else - fprintf(stdout,"%02X %02X %02X %02X.. (%" PRId64 ")",Data[0],Data[1],Data[2],Data[3],EBML_ElementDataSize(Element, 1)); + fprintf(stdout,"%02X %02X %02X %02X.. (%" PRId64 ")",Data[0],Data[1],Data[2],Data[3],Element->GetSize()); } } else fprintf(stdout,""); - EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + Element->SkipData(*Input, *Context, nullptr, 0); EndLine(Element); } else @@ -232,54 +230,46 @@ static ebml_element *OutputElement(ebml_element *Element, const ebml_parser_cont #ifdef IS_BIG_ENDIAN fprintf(stdout,"\r\n",EBML_ElementClassID(Element)); #else - fourcc_t Id = EBML_ElementClassID(Element); + auto Id = Element->GetClassId().GetValue(); fprintf(stdout,">= 8; } - fprintf(stdout,"%X>",EBML_ElementClassID(Element)); + fprintf(stdout,"%X>",Element->GetClassId().GetValue()); #endif - EBML_ElementSkipData(Element, Input, *Context, NULL, 0); + Element->SkipData(*Input, *Context, nullptr, 0); EndLine(Element); } return NULL; } -static void OutputEbmlhead(stream *Input) +static void OutputEbmlhead(EbmlStream *Input) { - // ebml_element *Element = EBML_ElementCreate(Input,libebml::EbmlHead,0,PROFILE_MATROSKA_ANY,NULL); - ebml_element *Element = Input->FindNextID(UINT64_MAX); - // ebml_element *Element = EBML_FindNextElement(Input, EBML_CONTEXT(libebml::EbmlHead), &UpperElement, 1); + EbmlElement *Element = Input->FindNextID(UINT64_MAX); if (Element) { unsigned int Level = 0; - // EBML_ElementSetInfiniteSize(Element,1); OutputElement(Element, NULL, Input, &Level); - NodeDelete((node*)Element); + delete Element; } } -static void OutputTree(stream *Input) +static void OutputTree(EbmlStream *Input) { - // ebml_element *Element = EBML_ElementCreate(Input,libmatroska::KaxSegment,0,PROFILE_MATROSKA_ANY,NULL); - ebml_element *Element = Input->FindNextID(UINT64_MAX); - // ebml_element *Element = EBML_FindNextElement(Input, EBML_CONTEXT(libmatroska::KaxSegment), &UpperElement, 1); + EbmlElement *Element = Input->FindNextID(UINT64_MAX); if (Element) { unsigned int Level = 0; - // EBML_ElementSetInfiniteSize(Element,1); OutputElement(Element, NULL, Input, &Level); - NodeDelete((node*)Element); + delete Element; } } int main(int argc, const char *argv[]) { - // parsercontext p; - stream *Input; - tchar_t Path[MAXPATHFULL]; + EbmlStream *Input; if ((argc!=2 && argc!=3) || (argc==3 && strcmp(argv[1],"--pos"))) { @@ -292,14 +282,8 @@ int main(int argc, const char *argv[]) if (argc==3) ShowPos = 1; - // Core-C init phase - ParserContext_Init(&p,NULL,NULL,NULL); - // EBML & Matroska Init - MATROSKA_Init(&p); - // open the file to parse - Node_FromStr(&p,Path,TSIZEOF(Path),argv[argc-1]); - Input = StreamOpen(&p,Path,SFLAG_RDONLY/*|SFLAG_BUFFERED*/); + Input = new EbmlStream(*(new StdIOCallback(argv[argc-1], MODE_READ))); if (Input == NULL) fprintf(stderr, "error: mkvtree cannot open file \"%s\"\r\n",argv[1]); else @@ -307,13 +291,10 @@ int main(int argc, const char *argv[]) OutputEbmlhead(Input); OutputTree(Input); - StreamClose(Input); + Input->I_O().close(); + delete &(Input->I_O()); + delete Input; } - // EBML & Matroska ending - MATROSKA_Done(&p); - // Core-C ending - ParserContext_Done(&p); - return 0; } diff --git a/test/mkvtree/porting.h b/test/mkvtree/porting.h deleted file mode 100644 index 535a31d2..00000000 --- a/test/mkvtree/porting.h +++ /dev/null @@ -1,304 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -// FIXME remove ? -using tchar_t = char; -#define T(x) x -#define TSIZEOF(x) sizeof(x) -#define TPRId64 PRId64 -#define TPRIx64 PRIx64 -#define tcslen(s) strlen(s) -#define tcscpy_s(d,dn,s) strcpy(d,s) -#define tcscat_s(d,dn,s) strcat(d,s) -#define tcscmp(a,b) strcmp(a,b) -#define tcsnicmp_ascii(a,b,n) strncmp(a,b,n) -#define stprintf_s std::snprintf -#define stcatprintf_s(d,dn,f,a1) std::snprintf(d+tcslen(d),dn-tcslen(d),f,a1) -#define stcatprintf_s2(d,dn,f,a1,a2) std::snprintf(d+tcslen(d),dn-tcslen(d),f,a1,a2) -#define StringToInt(s,r) std::atoi(s) - -#define TextPrintf fprintf -#define TextWrite fprintf -using textwriter = FILE; -#define StdErr stderr - -#define SFLAG_RDONLY MODE_READ -#define SFLAG_WRONLY MODE_WRITE -#define SFLAG_CREATE MODE_CREATE -#define StreamOpen(c,p,f) new libebml::EbmlStream(*(new libebml::StdIOCallback(p, (libebml::open_mode)(f)))) -static inline void StreamClose(libebml::EbmlStream *s) -{ - s->I_O().close(); - delete &(s->I_O()); - delete s; -} -static inline libebml::filepos_t Stream_Seek(libebml::IOCallback *s, std::uint64_t l, int w) -{ - (s)->setFilePointer(l,(libebml::seek_mode)w); - return (s)->getFilePointer(); -} -#define Stream_Write(s,b,l,p) (s)->writeFully(b,l) - -#define Node_FromStr(c,d,dn,s) strcpy(d,s) -#define Node_FromUTF8(c,d,dn,s) strcpy(d,s) -#define Node_ToUTF8(c,d,dn,s) strcpy(d,s) - -#define MAXPATH 1024 -#define MAXPATHFULL 1024 -#define MAXLINE 2048 -#define MAXDATA 2048 - -using bool_t = bool; - -#define ARRAYBEGIN(v,t) (v).begin() -#define ARRAYEND(v,t) (v).end() -#define ARRAYCOUNT(v,t) (v).size() -#define ARRAYAT(v,t,i) (&((v).at(i))) -#define ArrayInit(v) (v)->clear() -#define ArrayClear(v) (v)->clear() -#define ArrayResize(v,s,t,a) (v)->resize(s) -#define ArrayRemove(v,t,i,c,o) // TODO -#define ArrayZero(v) // nothing, it's always used after resize -#define ArrayAppend(v,e,s,a) (v)->push_back(e) -#define ArrayShrink(v,l) (v)->resize((v)->size() - l); (v)->shrink_to_fit() - -#define NodeDelete(o) delete o - -using ebml_element = libebml::EbmlElement; -using ebml_master = libebml::EbmlMaster; -using ebml_integer = libebml::EbmlUInteger; -using ebml_float = libebml::EbmlFloat; -using ebml_string = libebml::EbmlString; -using ebml_unistring = libebml::EbmlUnicodeString; -using ebml_date = libebml::EbmlDate; -using ebml_binary = libebml::EbmlBinary; -using nodetree = libebml::EbmlMaster; - -using matroska_cluster = libmatroska::KaxCluster; - -using EBML_MASTER_CLASS = libebml::EbmlMaster; -using EBML_STRING_CLASS = libebml::EbmlString; -using EBML_UNISTRING_CLASS = libebml::EbmlUnicodeString; -using EBML_DATE_CLASS = libebml::EbmlDate; -using EBML_SINTEGER_CLASS = libebml::EbmlSInteger; -using EBML_INTEGER_CLASS = libebml::EbmlUInteger; -using EBML_FLOAT_CLASS = libebml::EbmlFloat; -using EBML_BINARY_CLASS = libebml::EbmlBinary; -using EBML_VOID_CLASS = libebml::EbmlVoid; -using EBML_CRC_CLASS = libebml::EbmlCrc32; - -#define Node_IsPartOf(n,c) (dynamic_cast(n) != nullptr) - -using node = libebml::EbmlElement; -using fourcc_t = std::uint32_t; - -using ebml_parser_context = libebml::EbmlSemanticContext; -using parsercontext = void *; -#define ParserContext_Init(a,b,c,d) -#define ParserContext_Done(c) -#define EBML_Init(x) -#define EBML_Done(x) -#define MATROSKA_Init(x) -#define MATROSKA_Done(x) - -using stream = libebml::EbmlStream; - -#define ERR_NONE (!INVALID_FILEPOS_T) -#define ERR_INVALID_DATA INVALID_FILEPOS_T -using err_t = libebml::filepos_t; - -#define EBML_getContextHead() libebml::EbmlHead -#define EBML_getContextReadVersion() libebml::EReadVersion -#define EBML_getContextMaxIdLength() libebml::EMaxIdLength -#define EBML_getContextMaxSizeLength() libebml::EMaxSizeLength -#define EBML_getContextDocType() libebml::EDocType -#define EBML_getContextDocTypeVersion() libebml::EDocTypeVersion -#define EBML_getContextDocTypeReadVersion() libebml::EDocTypeReadVersion -#define EBML_getContextEbmlVoid() libebml::EbmlVoid - -#define MATROSKA_getContextInfo() libmatroska::KaxInfo -#define MATROSKA_getContextTimestampScale() libmatroska::KaxTimestampScale -#define MATROSKA_getContextSeek() libmatroska::KaxSeek -#define MATROSKA_getContextSegment() libmatroska::KaxSegment -#define MATROSKA_getContextSeekID() libmatroska::KaxSeekID -#define MATROSKA_getContextSeekPosition() libmatroska::KaxSeekPosition -#define MATROSKA_getContextBlock() libmatroska::KaxBlock -#define MATROSKA_getContextSimpleBlock() libmatroska::KaxSimpleBlock -#define MATROSKA_getContextBlockGroup() libmatroska::KaxBlockGroup -#define MATROSKA_getContextTrackNumber() libmatroska::KaxTrackNumber - -#define EBML_CodedSizeLength CodedSizeLength - -#define EBML_ElementCreate(n,c,d,p,o) new (c)() - -#define EBML_ElementGetName(e,d,dn) strcpy(d,EBML_NAME(e)) -#define EBML_ElementClassID(e) (*e).GetClassId().GetValue() -#define EBML_ElementPosition(e) (e)->GetElementPosition() -#define EBML_ElementDataSize(e,u) (e)->GetSize() -#define EBML_ElementFullSize(e,u) (e)->ElementSize((u != 0) ? libebml::EbmlElement::WriteAll : libebml::EbmlElement::WriteSkipDefault) -#define EBML_ElementPositionEnd(e) (e)->GetEndPosition() -#define EBML_ElementPositionData(e) ((e)->GetEndPosition() - (e)->GetSize()) -#define EBML_ElementIsType(e,t) ((e)->GetClassId() == EBML_ID(t)) -#define EBML_ElementGetClassName(e) EBML_NAME(e) -#define EBML_ElementContext(e) EBML_CONTEXT(e) -#define EBML_ElementIsDummy(e) (e)->IsDummy() -#define EBML_ElementReadData(e,i,b,c,s,f) (e)->ReadData(*i,s), ERR_NONE -#define EBML_ElementSkipData(e,s,c,p,d) (e)->SkipData(*(s),c,p,d) -#define EBML_FindNextElement(stream, sem, level, dummy) (stream)->FindNextElement(sem, *level, UINT64_MAX, dummy) -#define EBML_ElementSizeLength(e) (e)->GetSizeLength() -#define EBML_ElementSetSizeLength(e,s) (e)->SetSizeLength(s) -#define EBML_ElementIsFiniteSize(e) (e)->IsFiniteSize() -#define EBML_ElementSetInfiniteSize(e,i) (e)->SetSizeInfinite(i) -#define EBML_ElementUpdateSize(e,d,f,p) (e)->UpdateSize(p,f) -#define EBML_ElementForceDataSize(e,s) (e)->ForceSize(s) -#define EBML_ElementForcePosition(e,p) (e)->ForcePosition(p) -#define EBML_ElementForceContext(e,c) // FIXME turn OldStereo to new Stereo -static inline err_t EBML_ElementRenderHead(libebml::EbmlMaster *e, libebml::IOCallback *o, bool_t bKeepPosition, libebml::filepos_t *Rendered, const libebml::EbmlElement::ShouldWrite &p) -{ - return (e)->WriteHead(*o, 0, p); -} - -static inline std::vector::iterator EBML_MasterChildren(ebml_master * m) -{ - return m->begin(); -} -static inline std::vector::const_iterator EBML_MasterChildren(const ebml_master * m) -{ - return m->begin(); -} -static inline std::vector::iterator EBML_MasterChildren(matroska_cluster * c) -{ - return reinterpret_cast(c).begin(); -} - -static inline bool EBML_MasterEnd(std::vector::iterator i, ebml_master * m) -{ - return i != (m)->end(); -} -static inline bool EBML_MasterEnd(std::vector::const_iterator i, const ebml_master * m) -{ - return i != (m)->end(); -} -static inline bool EBML_MasterEnd(std::vector::iterator i, matroska_cluster * c) -{ - return i != reinterpret_cast(c).end(); -} -static inline bool EBML_MasterEnd(std::vector::const_iterator i, const matroska_cluster * c) -{ - return i != reinterpret_cast(c).end(); -} - -#define EBML_MasterNext(i) (i)++ -#define EBML_MasterEmpty(m) ((static_cast(m))->begin() == (static_cast(m))->end()) -#define EBML_MasterRemove(m,e) (m)->Remove(e) -#define EBML_MasterAppend(m,e) (m)->PushElement(*(e)) - -#define EBML_MasterFindChild(m,c) FindChild(*(libebml::EbmlMaster *)(m)) -#define EBML_MasterGetChild(m,c,u) &GetChild(*(libebml::EbmlMaster *)(m)) -#define EBML_MasterNextChild(m,p) FindNextChild(*(libebml::EbmlMaster *)(m), *p) -#define EBML_MasterIsChecksumValid(m) (m)->VerifyChecksum() -#define EBML_MasterFindFirstElt(m,c,n,d,p) &GetChild(*(libebml::EbmlMaster *)(m)) -#define EBML_MasterAddElt(m,c,d,p) (m)->AddNewElt(EBML_INFO(c)) - -#define NodeTree_Clear(m) (m)->RemoveAll() -#define NodeTree_SetParent(e,p,u) (static_cast(p))->PushElement(*(e)) - -#define EBML_IntegerValue(e) (reinterpret_cast(e))->GetValue() -#define EBML_IntegerSetValue(e,v) (reinterpret_cast(e))->SetValue(v) - -#define EBML_StringGet(e,d,dn) strcpy(d,(e)->GetValue().c_str()) -#define EBML_StringGetUnicode(e,d,dn) strcpy(d,(e)->GetValueUTF8().c_str()) -static inline err_t EBML_StringSetValue(libebml::EbmlString *e, const char *v) -{ - (e)->SetValue(v); - return ERR_NONE; -} -static inline err_t EBML_UniStringSetValue(libebml::EbmlUnicodeString *e, const char *v) -{ - (e)->SetValueUTF8(v); - return ERR_NONE; -} - -#define EBML_FloatValue(e) (reinterpret_cast(e))->GetValue() -#define EBML_FloatSetValue(e,v) (e)->SetValue(v) - -#define EBML_BinaryGetData(e) (e)->GetBuffer() - - - -////// ebml_date /////// - -#include - -using datetime_t = time_t; -struct datepack_t -{ - intptr_t Year; // 2001, 2007, etc - intptr_t Month; // 1-12 - intptr_t Day; // 1-31 - intptr_t Hour; // 24-hour - intptr_t Minute; // 0-59 - intptr_t Second; // 0-59 - intptr_t WeekDay; // 1 = Sunday, 2 = Monday, etc -}; - -static inline datetime_t GetTimeDate() -{ - return time(NULL); -} - -static inline void EBML_DateSetDateTime(libebml::EbmlDate *e, datetime_t d) -{ - e->SetEpochDate(d); -} - -#define EBML_DateTime(d) ((d)->GetValue() / UINT64_C(1'000'000'000)) - -#define INVALID_DATETIME_T 0 -#define DATETIME_OFFSET 0x3A4FC880 - -static inline bool_t GetDatePacked(datetime_t t, datepack_t *tp, bool_t Local) -{ - time_t ot; - struct tm *date; - - if (!tp || t == INVALID_DATETIME_T) - return 0; - - ot = t + DATETIME_OFFSET; - if (Local) - date = localtime(&ot); - else - date = gmtime(&ot); - - if (date) - { - tp->Second = date->tm_sec; - tp->Minute = date->tm_min; - tp->Hour = date->tm_hour; - tp->Day = date->tm_mday; - tp->Month = date->tm_mon + 1; - tp->Year = date->tm_year + 1900; - tp->WeekDay = date->tm_wday + 1; - return 1; - } - - return 0; -} From 360398dec3874e6eda28a3908524992d1baeea48 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Sun, 3 Mar 2024 14:57:04 +0100 Subject: [PATCH 4/4] disable most verbose warnings in MSVC They are very noisy and not very useful. the list of warnings can be found at https://learn.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default Same as https://github.com/Matroska-Org/libebml/commit/f9af4fd060443d5ebbf615999863d77ced56bdc3 --- CMakeLists.txt | 3 ++- test/mkvtree/mkvtree.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af7c3866..8267ba5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,8 @@ if(DEV_MODE) add_cxx_flag_if_supported(-Wno-error=unused-command-line-argument -Wall -Wextra -Wpedantic -Wfatal-errors -fstack-protector-strong -Wno-self-assign - -Wcast-align) + -Wcast-align + -W4) endif() set(libmatroska_SOURCES diff --git a/test/mkvtree/mkvtree.cpp b/test/mkvtree/mkvtree.cpp index 9e22c898..ee0e88d8 100644 --- a/test/mkvtree/mkvtree.cpp +++ b/test/mkvtree/mkvtree.cpp @@ -24,6 +24,12 @@ using namespace libebml; +#ifdef _WIN32 +# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#define localtime(x) nullptr +# endif // UWP, Xbox, etc +#endif // win32 + static int ShowPos = 0; #if 0 // TODO allowing find top level elements using an EbmlSemanticContextMaster