def _ldap_string_prep(self, string):
        """
        Implements the internationalized string preparation algorithm from
        RFC 4518. https://tools.ietf.org/html/rfc4518#section-2

        :param string:
            A unicode string to prepare

        :return:
            A prepared unicode string, ready for comparison
        """

        # Map step
        string = re.sub('[\u00ad\u1806\u034f\u180b-\u180d\ufe0f-\uff00\ufffc]+', '', string)
        string = re.sub('[\u0009\u000a\u000b\u000c\u000d\u0085]', ' ', string)
        if sys.maxunicode == 0xffff:
            # Some installs of Python 2.7 don't support 8-digit unicode escape
            # ranges, so we have to break them into pieces
            # Original was: \U0001D173-\U0001D17A and \U000E0020-\U000E007F
            string = re.sub('\ud834[\udd73-\udd7a]|\udb40[\udc20-\udc7f]|\U000e0001', '', string)
        else:
            string = re.sub('[\U0001D173-\U0001D17A\U000E0020-\U000E007F\U000e0001]', '', string)
        string = re.sub(
            '[\u0000-\u0008\u000e-\u001f\u007f-\u0084\u0086-\u009f\u06dd\u070f\u180e\u200c-\u200f'
            '\u202a-\u202e\u2060-\u2063\u206a-\u206f\ufeff\ufff9-\ufffb]+',
            '',
            string
        )
        string = string.replace('\u200b', '')
        string = re.sub('[\u00a0\u1680\u2000-\u200a\u2028-\u2029\u202f\u205f\u3000]', ' ', string)

        string = ''.join(map(stringprep.map_table_b2, string))

        # Normalize step
        string = unicodedata.normalize('NFKC', string)

        # Prohibit step
        for char in string:
            if stringprep.in_table_a1(char):
                raise ValueError(unwrap(
                    '''
                    X.509 Name objects may not contain unassigned code points
                    '''
                ))

            if stringprep.in_table_c8(char):
                raise ValueError(unwrap(
                    '''
                    X.509 Name objects may not contain change display or
                    zzzzdeprecated characters
                    '''
                ))

            if stringprep.in_table_c3(char):
                raise ValueError(unwrap(
                    '''
                    X.509 Name objects may not contain private use characters
                    '''
                ))

            if stringprep.in_table_c4(char):
                raise ValueError(unwrap(
                    '''
                    X.509 Name objects may not contain non-character code points
                    '''
                ))

            if stringprep.in_table_c5(char):
                raise ValueError(unwrap(
                    '''
                    X.509 Name objects may not contain surrogate code points
                    '''
                ))

            if char == '\ufffd':
                raise ValueError(unwrap(
                    '''
                    X.509 Name objects may not contain the replacement character
                    '''
                ))

        # Check bidirectional step - here we ensure that we are not mixing
        # left-to-right and right-to-left text in the string
        has_r_and_al_cat = False
        has_l_cat = False
        for char in string:
            if stringprep.in_table_d1(char):
                has_r_and_al_cat = True
            elif stringprep.in_table_d2(char):
                has_l_cat = True

        if has_r_and_al_cat:
            first_is_r_and_al = stringprep.in_table_d1(string[0])
            last_is_r_and_al = stringprep.in_table_d1(string[-1])

            if has_l_cat or not first_is_r_and_al or not last_is_r_and_al:
                raise ValueError(unwrap(
                    '''
                    X.509 Name object contains a malformed bidirectional
                    sequence
                    '''
                ))

        # Insignificant space handling step
        string = ' ' + re.sub(' +', '  ', string).strip() + ' '

        return string
Implements the internationalized string preparation algorithm from
        RFC 4518. https://tools.ietf.org/html/rfc4518#section-2

        :param string:
            A unicode string to prepare

        :return:
            A prepared unicode string, ready for comparison