LINUX.ORG.RU

Конвертация кода с Python в С++ или С

 , ,


0

1

Приветствую уважаемых гуру. Не может ли мне кто нибудь помочь с конвертированием кода на Python в С++?

class ISO7811_2(codecs.Codec):
    TRACK1_CHARS = ' !"#$%&\'()*+`,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'
    TRACK23_CHARS = '0123456789:;<=>?'

    @classmethod
    def _reverse_bits(cls, value, nbits):
        return sum(
            1 << (nbits - 1 - i)
            for i in xrange(nbits)
            if (value >> i) & 1
        )

    @classmethod
    def _with_parity(cls, value, nbits):
        if sum(1 for i in xrange(nbits) if (value >> i) & 1) % 2 != 0:
            return value
        return value | (1 << (nbits - 1))

    @classmethod
    def _iso_encode_data(cls, data, mapping, nbits):
        def make_data():
            lrc = 0
            for v in map(mapping.index, data):
                lrc ^= v
                yield chr(cls._with_parity(v, nbits))
            yield chr(cls._with_parity(lrc, nbits))
        enc = ''.join(make_data())
        return enc, len(enc)

    @classmethod
    def _iso_decode_data(cls, data, mapping, nbits):
        dec = ''.join(
            mapping[cls._reverse_bits(ord(c) >> 1, nbits - 1)]
            for c in data
        )
        return dec, len(dec)

    @classmethod
    def encode_track1(cls, data):
        return cls._iso_encode_data(data, cls.TRACK1_CHARS, 7)

    @classmethod
    def encode_track23(cls, data):
        return cls._iso_encode_data(data, cls.TRACK23_CHARS, 5)

    @classmethod
    def decode_track1(cls, data):
        return cls._iso_decode_data(data, cls.TRACK1_CHARS, 7)

    @classmethod
    def decode_track23(cls, data):
        return cls._iso_decode_data(data, cls.TRACK23_CHARS, 5)

    @classmethod
    def codec_search(cls, name):
        return {
            'iso7811-2-track1': (cls.encode_track1, cls.decode_track1, None, None),
            'iso7811-2-track2': (cls.encode_track23, cls.decode_track23, None, None),
            'iso7811-2-track3': (cls.encode_track23, cls.decode_track23, None, None),
        }.get(name, None)
codecs.register(ISO7811_2.codec_search)

Из-за того, что с Python ранее не работал, заглядывая каждый раз в мануал по питону, конвертация алгоритма - взрывает мозг и идёт крайне медленно. Если кто-то готов помочь - благодарю, если кто-то готов за денюжку - то готов и за денюжку в разумных пределах.

и в каком месте тебе не понятен этот код? яб даже не сказал, что тут много питоно-специфического. просто чистое описалово алгоритма «как есть»

anonymous
()
Ответ на: комментарий от anonymous

Ну например:

def _iso_encode_data(cls, data, mapping, nbits):
        def make_data():
            lrc = 0
            for v in map(mapping.index, data):
                lrc ^= v
                yield chr(cls._with_parity(v, nbits))
            yield chr(cls._with_parity(lrc, nbits))
        enc = ''.join(make_data())
        return enc, len(enc)
получется, что...для каждого кода символа V в строке Data мы, считаем lrc xor v. А...затем возвращаем генератор. И начиная курить мануалы, возникает затык - yield. насколько я понимаю, тут возвращается символ с битом чётности? а где оно тогда храниться? Получается make_data возвращает набор битов с битом чётности и lrc в конце? А сама функция возвращает байтовый массив с длинной?

CynicRus
() автор топика
Ответ на: комментарий от iSage

По ссылке только декод, и то странный. По хорошему мне нужен енкод\декод ISO-7811.

CynicRus
() автор топика

Что интересно, decode поворачивает биты, а encode не поворачивает (это делает write_raw). Из-за этого кодек получился не симметричный.

pftBest ★★★★
()
Ответ на: комментарий от pftBest

Так я и не спорю, просто у меня мозг плавится от синтаксиса типа:

sum(
            1 << (nbits - 1 - i)
            for i in xrange(nbits)
            if (value >> i) & 1
        )
в попытке осознать, что с чем суммируется возникает SIGSEGV.

CynicRus
() автор топика
Ответ на: комментарий от CynicRus

Это просто подсчет бит, ничего сложного. Вот накидал побыстрому енкод:

    pub fn encode(&self, text: &str, out: &mut Vec<u8>) -> Result<usize, Box<Error>> {
        let mut lrc = 0;
        let mut count = 0;
        for &byte in text.as_bytes() {
            if let Ok(index) = self.chars.binary_search(&byte) {
                lrc ^= index;
                out.push(self.with_parity(index as u8));
                count += 1;
            } else {
                Err("invalid symbol")?;
            }
        }
        out.push(self.with_parity(lrc as u8));
        Ok(count + 1)
    }

    fn with_parity(&self, byte: u8) -> u8 {
        let p = (byte.count_ones() & 1) ^ 1;
        byte | (p << self.bits) as u8
    }

pftBest ★★★★
()

А человеческим языком описания алгоритма нет нигде что ли? Это ж смерти подобно из этого говна в нормальный ЯП конвертировать! Проще с нуля написать!!!

anonymous
()
Ответ на: комментарий от anonymous

Eddy_Em, залогинься ты уже наконец.

EXL ★★★★★
()
Ответ на: комментарий от CynicRus

Я не пользовался, ибо на питоне почти ничего не писал.

И да, в ссылке говорится, что в PyPy конпелятор в Си, который карашо работает в том случае, если коде не использует всякие там либы.

В твоем коде, вроде бы, именно такой случай, так что рекомендую попробовать.

shkolnick-kun ★★★★★
()
Последнее исправление: shkolnick-kun (всего исправлений: 1)
Ответ на: комментарий от CynicRus

Обычное функци-анальное программирование на Python, ничего особенного.

shkolnick-kun ★★★★★
()
Последнее исправление: shkolnick-kun (всего исправлений: 1)
Ответ на: комментарий от pftBest

Спасибо, добрый человек! Если не трудно, подскажи пожалуйста - как вот это распарить:

def _reverse_bits(cls, value, nbits):
        return sum(
            1 << (nbits - 1 - i)
            for i in xrange(nbits)
            if (value >> i) & 1
        )

CynicRus
() автор топика
Ответ на: комментарий от shkolnick-kun

Cython генерирует вообще какую-то дичь с использованием Python.h и всяких питоновых типов , PyObject * etc. После просмотра экземплового выхлопа, мне даже стало жалко GCC, который вынужден этим калом давиться.

CynicRus
() автор топика
Ответ на: комментарий от CynicRus

Это просто переворот бит задом наперед. Бежим в цикле по всем битам и меняем их местами.

pub fn reverse_bits(&self, mut byte: u8) -> u8 {
  let mut result = 0;
  for i in 0..self.bits {
    let bit = byte & 1;
    byte >>= 1;
    result <<= 1;
    result |= bit;
  }
  result
}

pftBest ★★★★
()
Ответ на: комментарий от anonymous

Извини, анон, но спать тоже надо.

nuitka генерирует лютую хрень в духе cyphon.

shedskin генерирует лютую нерабочую хрень (не может распарсить mapping.index).

Есть еще Py2с, который, по утверждению авторов, должен генерировать человекочитаемые исходники, но как его завести - тайна покрытая мраком.

shkolnick-kun ★★★★★
()
Ответ на: комментарий от CynicRus

Не, у него есть jit, что какбе ускоряет процесс, то есть питон ускоряется!

А ещё там есть есть хрень для «сборки» исходников PyPy, назывеается rpython, вот она генерирует Си на основе анализа графа вызовов с добавлением в исходники всего библиотечного кода.

Тут проблема в том, что надо сделать main и вызвать оттуда кодек (например - обработать файлы всеми 4 методами).

Попробую вечером сделать, вчера потратил время на другие генераторы кода.

shkolnick-kun ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.