o
    h4                     @   sx   d Z ddlZddlZddlmZmZ ddlmZ g dZdd Zdd	 ZG d
d dZ	G dd dZ
G dd deZdS )zlModule containing a memory memory manager which provides a sliding window on a number of memory mapped files    N)mmapACCESS_READALLOCATIONGRANULARITY)align_to_mmap	is_64_bit	MapWindow	MapRegionMapRegionListr   c                 C   s$   | t  t  }|r|| kr|t 7 }|S )a=  
    Align the given integer number to the closest page offset, which usually is 4096 bytes.

    :param round_up: if True, the next higher multiple of page size is used, otherwise
        the lower page_size will be used (i.e. if True, 1 becomes 4096, otherwise it becomes 0)
    :return: num rounded to closest pager   )numround_upres r   >/var/www/vscode/kcb/lib/python3.10/site-packages/smmap/util.pyr      s   r   c                   C   s
   t jdkS )zO:return: True if the system is 64 bit. Otherwise it can be assumed to be 32 bitl    )sysmaxsizer   r   r   r   r      s   
r   c                   @   sP   e Zd ZdZdZdd Zdd Zedd Zd	d
 Z	dd Z
dd Zdd ZdS )r   zWUtility type which is used to snap windows towards each other, and to adjust their sizeofssizec                 C   s   || _ || _d S Nr   )selfoffsetr   r   r   r   __init__-      
zMapWindow.__init__c                 C   s   d| j | jf S )NzMapWindow(%i, %i)r   r   r   r   r   __repr__1   s   zMapWindow.__repr__c                 C   s   | |j | S )z!:return: new window from a region_br   )clsregionr   r   r   from_region4   s   zMapWindow.from_regionc                 C      | j | j S r   r   r   r   r   r   ofs_end9      zMapWindow.ofs_endc                 C   s8   t | jd}|  j| j| 7  _|| _t | jd| _dS )z<Assures the previous window area is contained in the new oner      N)r   r   r   )r   nofsr   r   r   align<   s   zMapWindow.alignc                 C   sJ   | j |  }|| j }||t|| 8 }|  j |8  _ |  j|7  _dS )zAdjust the offset to start where the given window on our left ends if possible,
        but don't make yourself larger than max_size.
        The resize will assure that the new window still contains the old window areaN)r   r"   r   min)r   windowmax_sizerofsnsizer   r   r   extend_left_toC   s
   
zMapWindow.extend_left_toc                 C   s    t | j|j|    || _dS )zpAdjust the size to make our window end where the right window begins, but don't
        get larger than max_sizeN)r'   r   r   r"   )r   r(   r)   r   r   r   extend_right_toM   s    zMapWindow.extend_right_toN)__name__
__module____qualname____doc__	__slots__r   r   classmethodr    r"   r&   r,   r-   r   r   r   r   r   %   s    

r   c                   @   st   e Zd ZdZg dZdddZdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd ZdddZdd ZdS )r	   z{Defines a mapped region of memory, aligned to pagesizes

    **Note:** deallocates used region automatically on destruction)r   _mf_uc_size__weakref__r   c           
   	   C   s   || _ d| _d| _t|tr|}nt|tjttddB |B }z1t	t
|d}|}|}tt|j| |}	t||	fi || _t| j| _W t|trQt| nt|tr]t| w w |   dS )a  Initialize a region, allocate the memory map
        :param path_or_fd: path to the file to map, or the opened file descriptor
        :param ofs: **aligned** offset into the file to be mapped
        :param size: if size is larger then the file on disk, the whole file will be
            allocated the the size automatically adjusted
        :param flags: additional flags to be given when opening the file.
        :raise Exception: if no memory can be allocatedr   O_BINARY)accessr   N)r   r6   r5   
isinstanceintosopenO_RDONLYgetattrdictr   r'   fstatst_sizer   r4   lenstrcloseincrement_client_count)
r   
path_or_fdr   r   flagsfdkwargscorrected_sizesizeofsactual_sizer   r   r   r   c   s(   



zMapRegion.__init__c                 C   s   d| j |  f S )NzMapRegion<%i, %i>r   r   r   r   r   r      s   zMapRegion.__repr__c                 C      | j S )z':return: a buffer containing the memoryr4   r   r   r   r   buffer      zMapRegion.bufferc                 C   rN   )z+:return: a memory map containing the memoryrO   r   r   r   r   map   rQ   zMapRegion.mapc                 C   rN   )z>:return: absolute byte offset to the first byte of the mapping)r   r   r   r   r   	ofs_begin   rQ   zMapRegion.ofs_beginc                 C   rN   )z1:return: total size of the mapped region in bytes)r6   r   r   r   r   r      rQ   zMapRegion.sizec                 C   r!   )zE:return: Absolute offset to one byte beyond the mapping into the filer   r6   r   r   r   r   r"      s   zMapRegion.ofs_endc                 C   s"   | j |  ko| j | j k S   S )zB:return: True if the given offset can be read in our mapped regionrT   r   r   r   r   r   includes_ofs   s   "zMapRegion.includes_ofsc                 C   rN   )z6:return: number of clients currently using this region)r5   r   r   r   r   client_count   rQ   zMapRegion.client_countr$   c                 C   sB   |  j |7  _ | j dksJ d| j  |  dkr|   dS dS )zAdjust the usage count by the given positive or negative offset.
        If usage count equals 0, we will auto-release our resources
        :return: True if we released resources, False otherwise. In the latter case, we can still be usedz<Increments must match decrements, usage counter negative: %ir   TF)r5   rW   releaserU   r   r   r   rF      s   z MapRegion.increment_client_countc                 C   s   | j   dS )zbRelease all resources this instance might hold. Must only be called if there usage_count() is zeroN)r4   rE   r   r   r   r   rY      s   zMapRegion.releaseN)r   )r$   )r.   r/   r0   r1   r2   r   r   rP   rR   rS   r   r"   rV   rW   rF   rY   r   r   r   r   r	   S   s    
'
r	   c                       s<   e Zd ZdZdZ fddZdd Zdd Zd	d
 Z  Z	S )r
   zFList of MapRegion instances associating a path with a list of regions._path_or_fd
_file_sizec                    s   t  | S r   )super__new__)r   path	__class__r   r   r^      r#   zMapRegionList.__new__c                 C   s   || _ d | _d S r   rZ   )r   rG   r   r   r   r      r   zMapRegionList.__init__c                 C   rN   )z3:return: path or file descriptor we are attached to)r[   r   r   r   r   rG      rQ   zMapRegionList.path_or_fdc                 C   sB   | j du rt| jtrt| jj| _ | j S t| jj| _ | j S )z :return: size of file we managerN)r\   r:   r[   rD   r<   statrB   rA   r   r   r   r   	file_size   s   
zMapRegionList.file_size)
r.   r/   r0   r1   r2   r^   r   rG   rc   __classcell__r   r   r`   r   r
      s    r
   )r1   r<   r   r   r   r   __all__r   r   r   r	   listr
   r   r   r   r   <module>   s    	.m