@@ -380,6 +380,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
380380 return 0 ;
381381}
382382
383+ /*! ZSTD_isSkippableFrame() :
384+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
385+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
386+ */
387+ unsigned ZSTD_isSkippableFrame (const void * buffer , size_t size )
388+ {
389+ if (size < ZSTD_FRAMEIDSIZE ) return 0 ;
390+ { U32 const magic = MEM_readLE32 (buffer );
391+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK ) == ZSTD_MAGIC_SKIPPABLE_START ) return 1 ;
392+ }
393+ return 0 ;
394+ }
395+
383396/** ZSTD_frameHeaderSize_internal() :
384397 * srcSize must be large enough to reach header size fields.
385398 * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
@@ -503,7 +516,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
503516 return ZSTD_getFrameHeader_advanced (zfhPtr , src , srcSize , ZSTD_f_zstd1 );
504517}
505518
506-
507519/** ZSTD_getFrameContentSize() :
508520 * compatible with legacy mode
509521 * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
@@ -544,6 +556,59 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
544556 }
545557}
546558
559+ /*! ZSTD_findFrameSize() :
560+ * Returns the raw size of the first frame in a buffer. Advancing the pointer by this amount will move to the next frame.
561+ * `src` should point to the start of a buffer with one or more ZSTD encoded frames.
562+ * `srcSize` must be at least as large as the frame header.
563+ * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.
564+ * @return : - size of `src` of the first frame, if known. Advancing the pointer by this amount will move to the next frame.
565+ * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
566+ * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)
567+ */
568+ unsigned long long ZSTD_findFrameSize (const void * src , size_t srcSize )
569+ {
570+ ZSTD_frameHeader zfh ;
571+ if (ZSTD_getFrameHeader (& zfh , src , srcSize ) != 0 )
572+ return ZSTD_CONTENTSIZE_ERROR ;
573+ if (zfh .frameType == ZSTD_skippableFrame ) {
574+ return readSkippableFrameSize (src , srcSize );
575+ } else {
576+ return ZSTD_findFrameCompressedSize (src , srcSize );
577+ }
578+ }
579+
580+ /*! ZSTD_readSkippableFrame() :
581+ * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
582+ *
583+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
584+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START
585+ *
586+ * Returns an error if destination buffer is not large enough, if the source size is not representable
587+ * with a 4-byte unsigned int, or if the frame is not skippable.
588+ *
589+ * @return : number of bytes written or a ZSTD error.
590+ */
591+
592+ ZSTDLIB_API size_t ZSTD_readSkippableFrame (void * dst , size_t dstCapacity , unsigned * magicVariant ,
593+ const void * src , size_t srcSize )
594+ {
595+ U32 const magicNumber = MEM_readLE32 (src );
596+ size_t skippableFrameSize = readSkippableFrameSize (src , srcSize );
597+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE ;
598+
599+ /* check input validity */
600+ RETURN_ERROR_IF (!ZSTD_isSkippableFrame (src , srcSize ), frameParameter_unsupported , "" );
601+ RETURN_ERROR_IF (skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize , srcSize_wrong , "" );
602+ RETURN_ERROR_IF (skippableContentSize > dstCapacity , dstSize_tooSmall , "" );
603+
604+ /* deliver payload */
605+ if (skippableContentSize > 0 && dst != NULL )
606+ ZSTD_memcpy (dst , (const BYTE * )src + ZSTD_SKIPPABLEHEADERSIZE , skippableContentSize );
607+ if (magicVariant != NULL )
608+ * magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START ;
609+ return skippableContentSize ;
610+ }
611+
547612/** ZSTD_findDecompressedSize() :
548613 * compatible with legacy mode
549614 * `srcSize` must be the exact length of some number of ZSTD compressed and/or
0 commit comments