25 grudnia 2014

clang-modernize

Ciekawe narzędzie przedstawione przez Chandlera Carrutha na GoingNative 2013:
Jego głównym zadaniem jest przerobienie istniejącego kodu, wprowadzając nowe mechanizmy ze standardu C++11. Nie jest tego wiele, ale pokazuje, jakie moce drzemią w samym clang-u. Testy przeprowadzałem na wersji 3.5
clang-modernize -add-override \
                -loop-convert \
                -pass-by-value \
                -replace-auto_ptr \
                -use-auto \
                -use-nullptr \
                cpp_modernize.cpp
Niestety nie udało mi się zmusić do działania opcji "pass-by-value", które ma pozwolić na zadziałanie move sementic.
#include <iostream>
#include <memory>
#include <vector>
#include <map>

class ICar {
public:
    virtual ~ICar() {};
    virtual int engine(const std::string& name) = 0;
};

class Car : public ICar {
public:
-   virtual int engine(const std::string& name) {
+   virtual int engine(const std::string& name) override {
        std::cout << "Engine " << name << " start" << std::endl;
        return 44;
    }
};

std::vector<std::string> rewrite(const std::map<std::string, int> m) {
    std::vector<std::string> out;
-   for (std::map<std::string, int>::const_iterator it = m.cbegin(); it != m.cend(); ++it) {
+   for (auto it = m.cbegin(); it != m.cend(); ++it) {
        out.push_back(it->first);
    }

    return out;
}

int main() {
    std::map<std::string, int> m = {{"3", 3}, {"4", 4}, {"8", 8}};
    std::vector<std::string> v = rewrite(m);
-   std::auto_ptr<ICar> ferrari(new Car());
+   std::unique_ptr<ICar> ferrari(new Car());

    int oil_counter = 0;
-   for (int i = 0; i < v.size(); ++i) {
-       if (ferrari.get() != NULL) {
-           int result = ferrari->engine(v[i]);
+   for (auto & elem : v) {
+       if (ferrari.get() != nullptr) {
+           int result = ferrari->engine(elem);
            oil_counter += result;
        }
    }
    return 0;
}

24 grudnia 2014

[Defrag] procdump

Kolejny fajna porcja podcastów z Defrag dostępna na channel9, dotycząca narzędzia ProcDump (sysinternals).
ProcDump jest programem konsolowym do zrzucania dump-ów pamięci (zdolności takie posiada też TaskManager, czy Process Explorer, ale nie tak zaawansowane). To co w nim najfajniejsze to tworzenie dump-ów programów w wyniku wystąpienia określonych warunków (pojawienie się wyjątku, określone zużycie pracy procesora/pamięci). Warto zacząć do przeglądnięcia dostępnych przykładów:
procdump.exe -? -e
Trzeba pamiętać o podaniu nazwy pliku gdzie dump zostanie zrzucony, jakoś przykłady o tym nie wspominają, a komunikat zwrotny nie jest intuicyjny. Kilka użytecznych przełączników:
  • -mp, -ma - domyślnie procdump, tworzy mini-dump, czasami jest to wystarczające, ale jeżeli będzie potrzebna nam większa ilość pamięci, można skorzystać z opcji Mini-Plus (-mp), lub do zrzutu całej pamięci (-ma)
  • -r - opcja tworzy klon pamięci, dzięki czemu proces tworzenia dumpa, nie przerywa działania oryginalnego programu
  • -w - jeżeli proces jeszcze nie jest odpalony, poczekaj na niego
  • -e - zrzuć dump w razie wystąpienie wyjątku. Domyślnie zadziała, gdy nie obsłużona zostanie druga szansa na złapanie wyjątku. Np. program zgłosi wyjątku access violation, na który system nie będzie umiał zareagować, więc nastąpi crash aplikacji. W ten sposób w dump-ie pojawi się miejsce, z którego pierwszy wyjątek został złapany, a nie gdzie został rzucony. Aby reagować na pierwsze pojawienie się wyjątku można skorzystać z opcji "-e 1"
  • -f - filter na wyjątki i debug logi
Przykład użycia:
#include "stdafx.h"
#include <iostream>

int main() {
    std::cout << "Hello crash" << std::endl;
    int *ptr = new((int *)0xdeadbeaf) int(44);
    return 0;
}
C:\userdata\>procdump.exe -mp -e 1 -f "ACCESS_VIOLATION" -w ConsoleCrash.exe crash.dmp

ProcDump v7.1 - Writes process dump files
Copyright (C) 2009-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
With contributions from Andrew Richards

Waiting for process named ConsoleCrash.exe...

Process:               ConsoleCrash.exe (3344)
CPU threshold:         n/a
Performance counter:   n/a
Commit threshold:      n/a
Threshold seconds:     10
Hung window check:     Disabled
Log debug strings:     Disabled
Exception monitor:     First Chance+Unhandled
Exception filter:      *ACCESS_VIOLATION*
Terminate monitor:     Disabled
Cloning type:          Disabled
Concurrent limit:      n/a
Avoid outage:          n/a
Number of dumps:       1
Dump folder:           C:\userdata\
Dump filename/mask:    crash


Press Ctrl-C to end monitoring without terminating the process.

[22:33:05] Exception: C0000005.ACCESS_VIOLATION
[22:33:05] Dump 1 initiated: C:\userdata\crash.dmp
[22:33:06] Dump 1 complete: 1 MB written in 0.5 seconds
[22:33:06] Waiting for dump to complete...
[22:33:07] Dump count reached.

23 grudnia 2014

[C++11] Elementy nowoczesnego C++

Kilka porad (http://herbsutter.com/elements-of-modern-c-style/) od Herba Shuttera dotyczące najistotniejszych elementów nowego C++.
  • Używaj auto, gdy tylko się da
  • Korzystaj z inteligentnych wskaźników i surowych wskaźników (nie mających prawa własności)
  • Stosuje nullptr. Nigdy 0 albo NULL
  • Korzystaj z "range for"
  • Korzystaj z wersji begin(), end() (free function) nie będącymi metodami klasy
  • Korzystanie z lambd wpływa na elegancję i szybkość kodu
  • Korzystaj z move semantic, zamiast kopiować obiekty
  • Uniform Initialization. Korzystaj z operatora przypisania (=) dla prostych typów oraz auto - po staremu. Dla wszystkich innych przypadków lepiej korzystać z {}. Nowa składnia chroni przed kilkoma starymi problemami, jak niepożądana konwersja, niezainicjowane zmienne lub przypadkowe stworzenie deklaracji funkcji.

22 grudnia 2014

[python] Beautiful Soup 4

Biblioteka do wyciągania danych z HTML-a i XML-a.
Różne ścieżki instalacji:
$ sudo apt-get install python-bs4
$ sudo apt-get install python3-bs4
$ pip install beautifulsoup4
BeautifulSoup zwraca obiekt reprezentujący dokument jako zagnieżdżone obiekty (kolejne pola) - każdy odpowiada prawdziwemu tag-owi. Najczęściej używane funkcji to find() i find_all(), pozwalające filtrować interesujące nas treści, ale istnieje też możliwość edytowanie struktury dokumentu.
soup = BeautifulSoup('<html>' \
                     '<a>' \
                        '<b>info1</b>' \
                        '<b>info2</b>' \
                     '</a>' \
                     '<c>text2</c>' \
                     '</html>')
print(soup.a.b.string)

tag = soup.find('a')
print(tag)
Wynik:
info1
<a><b>info1</b><b>info2</b></a>
Istnieje też możliwość tworzenia bardziej wyrafinowanych filtrów.
def filter_c_tag(tag):
    return tag.name == 'c' and tag.has_attr('item') and tag.attrs['item'] == 'bar'

soup = BeautifulSoup('<c item="bar">text1</c>' \
                     '<c item="foo">text2</c>' \
                     '<c item="bar">text3</c>')
tags = soup.find_all(filter_c_tag)
for t in tags:
    print(t.string)
Wynik
text1
text3

17 grudnia 2014

Upgrade do Ubuntu 14.10 bez Unity

Aktualizacja z konsoli, bez wykorzystania narządzie dostępnych w Unity.
Konfiguracja proxy, jest niestety skomplikowana, brak jest centralnego punktu, który mógłby propagować zmiany dla wszystkich programów w systemie. Dla większości programów wystarczy wyedytować plik /etc/environment. Dla apt-get należy stworzyć specjalny plik /etc/apt/apt.conf.d/95proxies.
$ sudo vim /etc/environment

http_proxy="http://example.com:8080/"
https_proxy="https://example.com:8080/"
ftp_proxy="ftp://example.com:8080/"
no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com"
HTTP_PROXY="http://example.com:8080/"
HTTPS_PROXY="https://example.com:8080/"
FTP_PROXY="ftp://example.com:8080/"
NO_PROXY="localhost,127.0.0.1,localaddress,.localdomain.com"

# Dla apt-get
$ sudo touch /etc/apt/apt.conf.d/95proxies
$ sudo vim /etc/apt/apt.conf.d/95proxies

Acquire::http::proxy "http://example.com:8080/";
Acquire::ftp::proxy "ftp://example.com:8080/";
Acquire::https::proxy "https://example.com:8080/";
Upgrade do nowej wersji:
# Ustawienie Prompt=normal, jeżeli jest taka potrzeba
sudo vim /etc/update-manager/release-upgrades

# Instalacja narzędzia update-manager-core jeżeli jest to potrzebne
sudo apt-get install update-manager-core

# Właściwy upgrade
do-release-upgrade
Instalacja brakujących sterowników z płyty:
sudo mount /dev/cdrom /media/mydrivers/
sudo /media/mydrivers/run.sh

14 grudnia 2014

Migracja repozytorium svn do git-a

Nie jest to nawet takie skomplikowane. Dodatkowo, skonfigurowałem msysGit-a pod windows-em. Wymagało to wygenerowania kluczy i skonfigurowania kilku dodatkowych narzędzi (plink/pageant). Przydatne okazały się dwa poniższe linki:
Powtarzając częściowo za poradnikiem, zaczynamy od wygenerowania listy użytkowników svn-a, na tej podstawie tworzymy plik user.txt, w którym mapujemy ich na użytkowników git-a
$ svn log --xml | grep author | sort -u | perl -pe 's/.*>(.*?)<.*/$1 = /'
$ cat users.txt
kungfurry = Robert <robert@example.com>
Następnie klonujemy repozytorium (flaga -s umożliwia śledzenie gałęzi trunk/branch/tags, ale ja nie utrzymywałem tej konwencji i nie testowałem tej opcji). Poradnik zaleca też skasowanie jakiś śmieci z katalogu .git
$ git svn clone svn+ssh://kungfurry@example.com/svn/some_project \
      --authors-file=users.txt --no-metadata my_project
$ rm -Rf my_project/.git/refs/remotes
Wybrałem najprostszą z możliwych ścieżek, chodziło mi bowiem o przeniesienie się na git-a całkowicie. Z tego co już miałem stworzyłem gołego klona i wypchnąłem go na zdalny serwer. Po skasowaniu lokalnego repo, zrobiłem klona z serwera, w ten sposób automatycznie zostały stworzone odniesienie do zdalnego repozytorium.
$ git clone --bare my_project my_project.git
$ scp -r my_project.git kungfurry@example.com:/home/kungfurry/git_repos/
$ rm -rf my_project
$ git clone kungfurry@example.com:/home/kungfurry/git_repos/my_project.git

8 grudnia 2014

[python] pip i virtualenv

Fajny wpis na temat pip oraz virtualenv. Od wersji 3.4, pip jest instalowany razem z pythonem:
Paczki instalowane są standardowo w Lib\site-packages. Instalacja BeautifulSoup4 i sprawdzenie działania:
c:\Python34\Scripts>pip install beautifulsoup4
c:\>dir c:\Python34\Lib\site-packages\bs4\
c:\>python
>>> from bs4 import BeautifulSoup
virtualenv można wykorzystać do testowej instalacji paczek, jeżeli nie chcemy zaśmiecać sobie środowiska produkcyjnego.
mkdir project
cd project
virtualenv env
source env/bin/activate

pip install beautifulsoup4

6 grudnia 2014

md5 w python-ie

Obliczanie funkcji skrótu MD5, z pomocą standardowej biblioteki hashlib. Istnieje różnica między wersjami. Funkcja update() w wersji 2, przyjmuje jako argument string, w wersji trzeciej argument musi być interpretowany jako bufor bajtów:
Python 2:
# -*- coding: utf-8 -*-
import hashlib

s = 'jeżeli nie popełniłeś błędu tzn. że się niczego nie nauczyłeś'
print(type(s))

m = hashlib.md5()
m.update(s)
print(m.hexdigest())
Wyniki:
<type 'str'>
f9e58600ead7130b26fab4f1b943b79b
Python 3:
import hashlib

s = 'jeżeli nie popełniłeś błędu tzn. że się niczego nie nauczyłeś'
s = s.encode('utf-8')
print(type(s))

m = hashlib.md5()
m.update(s)
print(m.hexdigest())
Wyniki:
<class 'bytes'>
f9e58600ead7130b26fab4f1b943b79b