U
    Nf                      @   s  d Z ddlmZmZ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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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 )!u&  
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.root_object["/PageLabels"]["/Nums"]
[0, IndirectObject(18, 0, 139929798197504),
 8, IndirectObject(19, 0, 139929798197504)]
>>> reader.get_object(reader.root_object["/PageLabels"]["/Nums"][1])
{'/S': '/r'}
>>> reader.get_object(reader.root_object["/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ListOptionalTuplecast   )PdfCommonDocProtocol)logger_warning)ArrayObjectDictionaryObject
NullObjectNumberObjectnumreturnc                    sH   ddddddddd	d
dddg t tt d fdd}dt|| 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-zevpxvmc/pypdf/_page_labels.py	roman_numT   s    
z1number2uppercase_roman_numeral.<locals>.roman_num )intr   strjoinlist)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    r2   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).0ir%   r%   r&   
<listcomp>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@   r0   r1   r%   r%   r&   number2lowercase_letters   s    rA   )dictionary_objectindexr   c           	      C   s   t t| d }d}d }d}|t|k rl|| }||d   }|d t|krPql||d  |krbql|d7 }qdd dd ttttd}t|t	st
|d S |d	d}|d
d}|||d || |  S )N/Numsr   r      c                 S   s   dS )Nr(   r%   nr%   r%   r&   <lambda>       z%get_label_from_nums.<locals>.<lambda>c                 S   s   t | S r/   )r*   rF   r%   r%   r&   rH      rI   )Nz/Dz/Rz/rz/Az/az/Stz/Pr(   z/S)r   r
   len
get_objectr-   r2   r@   rA   
isinstancedictr*   get)	rB   rC   numsr5   valuestart_indexmstartprefixr%   r%   r&   get_label_from_numsw   s0    
	
rU   )readerrC   r   c                 C   s  t t| j}d|kr t|d S t t|d  }d|krDt||S d|krt|d tsd}|dk rt tt |d }|D ]t}t tt	 |d }|d |  kr|d kr|n q||
dddk	r|d7 }|dkrtd	|} q^t||  S q|qq^td
| 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/PageLabelsr   rD   z/Kidsr   r   z/LimitsNz"Too deep nesting is not supported.z,Could not reliably determine page label for .)r   r   Zroot_objectr*   rK   rU   rL   r   r   r)   rN   NotImplementedErrorr	   __name__)rV   rC   rootZnumber_treelevelZkidsZkidZlimitsr%   r%   r&   index2label   s4    
 
r\   N)keyrP   rO   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
    rE   r   6a nums like array must have an even number of elementsr   N)rJ   r:   insert)r]   rP   rO   r5   r%   r%   r&   nums_insert   s    
r`   )r]   page_index_torO   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
    rE   r   r^   z/page_index_to must be greater or equal than keyN)rJ   r:   rC   pop)r]   ra   rO   r5   r%   r%   r&   nums_clear_range   s    
rc   )r]   rO   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
    rE   r   r^   r   )NNN)rJ   r:   rC   )r]   rO   r5   r%   r%   r&   	nums_next  s    rd   )__doc__typingr   r   r   r   r   Z
_protocolsr   _utilsr	   Zgenericr
   r   r   r   r)   r*   r-   r2   r@   rA   rU   r\   r`   rc   rd   r%   r%   r%   r&   <module>   s0   ;$2