U
    c                     @   s   d Z ddlmZmZmZ ddlmZ ddlmZ ddl	m
Z
mZmZ eeddd	Zeed
ddZeed
ddZeed
ddZeeedddZeee
ddddZeee
ddddZee
eee ee f dddZdS )u5  
Page labels are shown by PDF viewers as "the page number".

A page has a numeric index, starting with 0. Additionally to that, the page
has a label. In the most simple case:
    label = index + 1

However, the title page and the table of contents might have roman numerals as
page label. This makes things more complicated.

Example 1
---------

>>> reader.trailer["/Root"]["/PageLabels"]["/Nums"]
[0, IndirectObject(18, 0, 139929798197504),
 8, IndirectObject(19, 0, 139929798197504)]
>>> reader.get_object(reader.trailer["/Root"]["/PageLabels"]["/Nums"][1])
{'/S': '/r'}
>>> reader.get_object(reader.trailer["/Root"]["/PageLabels"]["/Nums"][3])
{'/S': '/D'}

Example 2
---------
The following example shows a document with pages labeled
i, ii, iii, iv, 1, 2, 3, A-8, A-9, ...

1 0 obj
    << /Type /Catalog
    /PageLabels << /Nums [
            0 << /S /r >>
            4 << /S /D >>
            7 << /S /D
            /P ( A- )
            /St 8
            >>
            % A number tree containing
            % three page label dictionaries
        ]
        >>
    ...
    >>
endobj


PDF Specification 1.7
=====================

Table 159 – Entries in a page label dictionary
----------------------------------------------
The S-key:
D       Decimal arabic numerals
R       Uppercase roman numerals
r       Lowercase roman numerals
A       Uppercase letters (A to Z for the first 26 pages,
                           AA to ZZ for the next 26, and so on)
a       Lowercase letters (a to z for the first 26 pages,
                           aa to zz for the next 26, and so on)
    )IteratorOptionalTuple   )PdfReaderProtocol)logger_warning)ArrayObjectDictionaryObjectNumberObjectnumreturnc                    sN   ddddddddd	d
dddg t tt d fdd}ddd || D S )N)i  M)i  ZCM)i  D)i  ZCD)d   C)Z   ZXC)2   L)(   ZXL)
   X)	   ZIX)   V)   ZIV)r   Ir   c                 3   sB    D ]8\}}t | |\}}|| V  | || 8 } | dkr q>qd S )Nr   )divmod)r   decimalZ
roman_reprx_Zroman 6/tmp/pip-unpacked-wheel-u_n6aelj/pypdf/_page_labels.py	roman_numT   s    
z1number2uppercase_roman_numeral.<locals>.roman_num c                 S   s   g | ]}|qS r"   r"   ).0ar"   r"   r#   
<listcomp>\   s     z2number2uppercase_roman_numeral.<locals>.<listcomp>)intr   strjoin)r   r$   r"   r!   r#   number2uppercase_roman_numeralC   s     r,   )numberr   c                 C   s   t |  S N)r,   lowerr-   r"   r"   r#   number2lowercase_roman_numeral_   s    r1   c                 C   sv   | dkrt ddd ttdtdd D }d}| dkrr| d	 }|dkrPd	}||d  | }| |8 } | d	 } q4|S )
Nr   zExpecting a positive numberc                 S   s   g | ]}t |qS r"   )chr)r&   ir"   r"   r#   r(   f   s     z+number2uppercase_letter.<locals>.<listcomp>AZr   r%      )
ValueErrorrangeord)r-   alphabetrep	remainderr"   r"   r#   number2uppercase_letterc   s     
r=   c                 C   s   t |  S r.   )r=   r/   r0   r"   r"   r#   number2lowercase_letters   s    r>   )readerindexr   c                 C   s6  | j d }d|krt|d S |d }d|kr|d }d}d}d}|t|k r|| }||d  }|d t|krvq||d  |krq|d7 }qDdd	 d
d	 ttttd}t|ts| 	|}t|tst|d S |
dd}	|
dd}
|
||
d || |	  S d|ks d|kr*tdt t|d S )z
    See 7.9.7 "Number Trees".

    Args:
        reader: The PdfReader
        index: The index of the page

    Returns:
        The label of the page, e.g. "iv" or "4".
    z/Rootz/PageLabelsr   z/Numsr   N   c                 S   s   dS )Nr%   r"   nr"   r"   r#   <lambda>       zindex2label.<locals>.<lambda>c                 S   s   t | S r.   )r*   rB   r"   r"   r#   rD      rE   )Nz/Dz/Rz/rz/Az/az/Stz/Pr%   z/Sz/Kidsz/Limitszq/Kids or /Limits found in PageLabels. Please share this PDF with pypdf: https://github.com/py-pdf/pypdf/pull/1519)trailerr*   lenr,   r1   r=   r>   
isinstancedictZ
get_objectgetr   __name__)r?   r@   rootZnumber_treenumsr3   valuestart_indexmstartprefixr"   r"   r#   index2labelw   sJ    





	rS   N)keyrN   rM   r   c                 C   s   t |d dkrtdt |}|dkrB| ||d  krB|d }q |t |k rh| || krh|||d < n|||  ||d | dS )z
    Insert a key, value pair in a Nums array.

    See 7.9.7 "Number Trees".

    Args:
        key: number key of the entry
        value: value of the entry
        nums: Nums array to modify
    rA   r   6a nums like array must have an even number of elementsr   N)rG   r7   insert)rT   rN   rM   r3   r"   r"   r#   nums_insert   s    
rW   )rT   page_index_torM   r   c                 C   sh   t |d dkrtd|| k r(td|| d }|t |k rd|| |krd|| || q6dS )a  
    Remove all entries in a number tree in a range after an entry.

    See 7.9.7 "Number Trees".

    Args:
        key: number key of the entry before the range
        page_index_to: The page index of the upper limit of the range
        nums: Nums array to modify
    rA   r   rU   z/page_index_to must be greater or equal than keyN)rG   r7   r@   pop)rT   rX   rM   r3   r"   r"   r#   nums_clear_range   s    
rZ   )rT   rM   r   c                 C   sN   t |d dkrtd|| d }|t |k rF|| ||d  fS dS dS )z
    Return the (key, value) pair of the entry after the given one.

    See 7.9.7 "Number Trees".

    Args:
        key: number key of the entry
        nums: Nums array
    rA   r   rU   r   )NNN)rG   r7   r@   )rT   rM   r3   r"   r"   r#   	nums_next   s    r[   )__doc__typingr   r   r   Z
_protocolsr   _utilsr   Zgenericr   r	   r
   r)   r*   r,   r1   r=   r>   rS   rW   rZ   r[   r"   r"   r"   r#   <module>   s.   ;@