o
    iI                     @   s  d Z ddlmZmZ ddlmZ ddlmZ ddlZddl	m
Z
mZ ddlmZmZ ddlmZ dd	lmZmZmZmZmZ dd
lmZ ddlmZmZ ddlmZmZ ee B ej!B Z"dede#deddfddZ$	d<dede de%de#de%dB f
ddZ&		d=dede#dede%e'B dB de%de dB fddZ(	d>dede#de'e%B dB de)e#e dB f fdd Z*		d<dedede#de%de#de%dB fd!d"Z+		d<dedede#de%de#de%dB fd#d$Z,d%e"eB eB eB deeB fd&d'Z-d(e d)edefd*d+Z.d,eddfd-d.Z/ed,edee%ddf fd/d0Z0dd1d,ed2e%dB dee  fd3d4Z1d,ede%fd5d6Z2d,ede%fd7d8Z3d,ed9e e4B eB de#fd:d;Z5dS )?z8Functions for reading to certain bytes, e.g. delimiters.    )	GeneratorIterator)contextmanager)BufferedIOBaseN)packunpack)BinaryIOcast)size_in_bytes)TupleTagTagSequenceDelimiterTagItemTagBaseTag)dictionary_description)ReadableBufferWriteableBuffer)loggersettingsfpis_little_endian	delimiterreturnc              	   C   s   |rd}nd}t || d\}}}t||f}||kr<tdt| d| d|  d d | |  d  dS td	|  d t| |d
krYtd|  d  dS td|  d | dS )z@Read (and ignore) undefined length sequence or item terminators.z<HHLz>HHL   z!Did not find expected delimiter 'z', instead found z at file position 0xXNz%04x: Found Delimiter '%s'r   z"%04x: Read 0 bytes after delimiter   z5%04x: Expected 0x00000000 after delimiter, found 0x%x)	r   readr   r   warnr   tellseekdebug)r   r   r   struct_formatgroupelemlengthtag r&   F/mnt/sdb/aimis/docanh/lib/python3.10/site-packages/pydicom/fileutil.pyabsorb_delimiter_item   s6   
r(      Tbytes_to_find	read_sizerewindc                 C   s   |   }t|d }d}d}|sV|   }| |}	t|	|k r4| |t|	 }
|	|
7 }	t|	|k r4d}|	|}|dkr@d}n|rK|rI| | dS | |   |  |r|| }|rc| | |S | |t|  |S )a  Read in the file until a specific byte sequence found.

    Parameters
    ----------
    fp : file-like
        The file-like to search.
    bytes_to_find : bytes
        Contains the bytes to find. Must be in correct endian order already.
    read_size : int
        Number of bytes to read at a time.
    rewind : bool
        Flag to rewind file reading position.

    Returns
    -------
    found_at : int or None
        Position where byte sequence was found, else ``None``.
       FTN)r   lenr   findr   )r   r*   r+   r,   
data_startsearch_rewindfoundeofchunk_start
bytes_read	new_bytesindexfound_atr&   r&   r'   
find_bytes7   s6   



r:       delimiter_tag
defer_sizec                 C   s  |   }t|}|tkrt| ||\}}|r|S d}|rd}	nd}	t|	|j|j}
d}d}g }d}|s|   }| |}t||k rW| |t| }||7 }t||k rWd}|	|
}|dkrd}|d| }|t|7 }|du sv||k r{|
| | || d	  | d	}|d
krd}t||   d	  n2|r| | td|d| |   |  |d|  }|t|7 }|du s||k r|
| |r3|dur||krdS d|S )aW  Read until `delimiter_tag` and return the value up to that point.

    On completion, the file will be set to the first byte after the delimiter
    and its following four zero bytes.

    Parameters
    ----------
    fp : file-like
        The file-like to read.
    is_little_endian : bool
        ``True`` if file transfer syntax is little endian, else ``False``.
    delimiter_tag : BaseTag
        Tag used as end marker for reading
    defer_size : int or None, optional
        Size to avoid loading large elements in memory. See
        :func:`~pydicom.filereader.dcmread` for more parameter info.
    read_size : int, optional
        Number of bytes to read at one time.

    Returns
    -------
    delimiter : bytes or None
        The file delimiter.

    Raises
    ------
    EOFError
        If EOF is reached before delimiter found.
          <HH   >HHFr   Tr.   Nr          EExpected 4 zero bytes after undefined length delimiter at pos {0:04x}z%End of file reached before delimiter z found    )r   r
   r   !_try_read_encapsulated_pixel_datar   r"   r#   r   r/   r0   appendr   r   errorformatEOFErrorjoin)r   r   r<   r=   r+   r1   was_value_foundvaluer2   bytes_formatr*   r3   r4   value_chunks
byte_countr5   r6   r7   r8   r$   msgr&   r&   r'   read_undefined_length_valuep   sj   $






'
rP   c              
   C   s  |rd}d}nd}d}t |tjtj}t |tjtj}|  }d}	 | d}	t|	dk r@t	d|  t|	  | 
| d	S |d7 }|	|krInm|	|kr| d}
t|
dk rlt	d
t|  t|
  | 
| d	S |d7 }t||
d }z	| 
|tj W n ty   t	d|t|  d  | 
| Y d	S w ||7 }nt	d|	 |  d  | 
| d	S q"| d}|dkrd}t	||  d  |dur||krd}n| 
| | |d }| 
|| d  d|fS )a  Attempt to read an undefined length value item as if it were
    encapsulated pixel data as defined in PS3.5 section A.4.

    On success, the file will be set to the first byte after the delimiter
    and its following four zero bytes. If unsuccessful, the file will be left
    in its original position.

    Parameters
    ----------
    fp : file-like
        The file-like to read.
    is_little_endian : bool
        ``True`` if the file transfer syntax is little endian, else ``False``.
    defer_size : int or None, optional
        Size to avoid loading large elements in memory. See
        :func:`~pydicom.filereader.dcmread` for more parameter info.

    Returns
    -------
    bool, bytes
        Whether or not the value was parsed properly and, if it was,
        the value.
    r?   s   <Lr@   s   >Lr   Tr   zEnd of input encountered while parsing undefined length value as encapsulated pixel data. Unable to find tag at position 0x%x. Falling back to byte by byte scan.)FNzEnd of input encountered while parsing undefined length value as encapsulated pixel data. Unable to find length for tag %s at position 0x%x. Falling back to byte by byte scan.zToo-long length %04x for tag %s at position 0x%x found while parsing undefined length value as encapsulated pixel data. Falling back to byte-by-byte scan.r   zUnknown tag bytes %s at position 0x%x found while parsing undefined length value as encapsulated pixel data. Falling back to byte-by-byte scan.rA   rB   N)r   r   r"   r#   r   r   r   r/   r   r    r   r   osSEEK_CUROverflowErrorhexrG   )r   r   r=   
tag_formatlength_formatsequence_delimiter_bytes
item_bytesr1   rN   	tag_byteslength_bytesr$   rO   rK   r&   r&   r'   rD      s   










?
rD   c                 C   s<   d}|sd}t |}t||jt||j }t| |||dS )a,  Return file position where 4-byte delimiter is located.

    Parameters
    ----------
    delimiter : int
        The delimiter to search for.
    is_little_endian : bool
        ``True`` if little endian, ``False`` otherwise.
    read_size : int
        See :func:`find_bytes` for parameter info.
    rewind : bool
        Flag to rewind to initial position after searching.

    Returns
    -------
    int or None
        Returns ``None`` if end of file is reached without finding the
        delimiter, otherwise the byte offset to the delimiter.
    z<Hz>H)r+   r,   )r   r   r"   r#   r:   )r   r   r   r+   r,   r!   r*   r&   r&   r'   find_delimiter\  s   r[   c                 C   s,   |   }t| |||d}|dur|| S dS )a  Search through the file to find the delimiter and return the length
    of the data element.

    Parameters
    ----------
    fp : file-like
        The file-like to read.
    delimiter :
        See :func:`find_delimiter` for parameter info.
    is_little_endian : bool
        ``True`` if little endian, ``False`` otherwise.
    read_size : int
        See :func:`find_bytes` for parameter info.
    rewind : bool
        Flag to rewind to initial position after searching.

    Returns
    -------
    int
        Byte offset to the delimiter.

    Notes
    -----
    Note the data element that the delimiter starts is not read here,
    the calling routine must handle that. Delimiter must be 4 bytes long.
    )r,   N)r   r[   )r   r   r   r+   r,   r1   delimiter_posr&   r&   r'   length_of_undefined_length  s
   !r]   file_objectc                 C   s*   zt | W S  ty   tt|  Y S w )ai  Returns the path if `file_object` is a path-like object, otherwise the
    original `file_object`.

    Parameters
    ----------
    file_object: str or PathLike or file-like

    Returns
    -------
    str or file-like
        the string representation of the given path object, or the object
        itself in case of an object not representing a path.
    )rQ   fspath	TypeErrorr	   r   )r^   r&   r&   r'   path_from_pathlike  s
   ra   b
endiannessc                 C   s"   t ttttf t| d| S )NHH)r   r	   tupleintr   )rb   rc   r&   r&   r'   _unpack_tag  s   "rg   bufferc                 C   s<   t | ts	td| jrtd|  r|  stddS )a  Raise an exception if `buffer` is not usable as an element value.

    Parameters
    ----------
    buffer : io.BufferedIOBase
        The buffer to check, must be :meth:`~io.IOBase.readable`,
        :meth:`~io.IOBase.seekable` and not be :attr:`io.IOBase.closed`.
    z0the buffer must inherit from 'io.BufferedIOBase'zthe buffer has been closedz(the buffer must be readable and seekableN)
isinstancer   r`   closed
ValueErrorreadableseekablerh   r&   r&   r'   check_buffer  s   
	ro   c                 c   s&    t |  |  }|V  | | dS )a
  Yields the initial position of the buffer and return to that position on exiting
    the context.

    Parameters
    ----------
    buffer : io.BufferedIOBase
        The buffer to use.

    Yields
    ------
    int
        The initial position of the buffer.
    N)ro   r   r   )rh   initial_offsetr&   r&   r'   reset_buffer_position  s
   rq   )
chunk_sizerr   c                c   sb    |du rt jn|}|dkrtd| dt|  | | }r/|r&|V  | | }s!dS dS )a  Read data from `buffer`.

    The buffer is NOT returned to its starting position.

    Parameters
    ----------
    buffer : io.BufferedIOBase
        The buffer to read from.
    chunk_size : int, optional
        The amount of bytes to read per iteration (default 8192). Fewer bytes may be
        yielded if there is insufficient remaining data in `buffer`.

    Yields
    -------
    bytes
        Data read from the buffer of length up to the specified chunk_size.
    Nr   zInvalid 'chunk_size' value 'z', must be greater than 0)r   buffered_read_sizerk   ro   r   )rh   rr   chunkr&   r&   r'   read_buffer  s   
ru   c                 C   s:   t |  | dtjW  d   S 1 sw   Y  dS )zReturn the total length of the buffer.

    Parameters
    ----------
    buffer : io.BufferedIOBase
        The buffer to return the remaining length for.

    Returns
    -------
    int
        The total length of the buffer.
    r   Nrq   r   rQ   SEEK_ENDrn   r&   r&   r'   buffer_length  s   
$rx   c                 C   s>   t | }| dtj| W  d   S 1 sw   Y  dS )a0  Return the remaining length of the buffer with respect to the current position.

    Parameters
    ----------
    buffer : io.BufferedIOBase
        The buffer to return the remaining length for.

    Returns
    -------
    int
        The remaining length of the buffer from the current position.
    r   Nrv   )rh   current_offsetr&   r&   r'   buffer_remaining   s   
$rz   otherc              	   C   sV  t |ttB tB sdS t|  | d t |ttB rMd}t| D ]}t|}||||  |kr; W d   dS ||7 }q"t||kW  d   S t| t|kr^	 W d   dS t|. |d t	t| t|D ]\}}||kr W d   W d   dS qqW d   n1 sw   Y  	 W d   dS 1 sw   Y  dS )zGReturn ``True`` if `buffer` and `other` are equal, ``False`` otherwise.Fr   NT)
ri   bytes	bytearrayr   rq   r   ru   r/   rx   zip)rh   r{   startdatanr_readdata_adata_br&   r&   r'   buffer_equality1  s:   


	


$r   )r)   T)Nr;   )N)6__doc__collections.abcr   r   
contextlibr   ior   rQ   structr   r   typingr   r	   pydicom.miscr
   pydicom.tagr   r   r   r   r   pydicom.datadictr   pydicom.filebaser   r   pydicom.configr   r   strr|   PathLikePathTypeboolr(   rf   r:   floatrP   re   rD   r[   r]   ra   rg   ro   rq   ru   rx   rz   r}   r   r&   r&   r&   r'   <module>   s   
"
=

v

}
)
)

 
