aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerlaender2017-01-17 20:44:31 +0100
committerAdrian Kummerlaender2017-01-17 20:44:31 +0100
commit9bb990c9a663edc43aebb87ed84b00e6d90685c0 (patch)
treefcb40f5c4f94f7e1b89d3495a20d82e4cbd6db90
parentb84e7973d91e066aa3c0e9e5660e30401916fd5f (diff)
downloadblog_content-9bb990c9a663edc43aebb87ed84b00e6d90685c0.tar
blog_content-9bb990c9a663edc43aebb87ed84b00e6d90685c0.tar.gz
blog_content-9bb990c9a663edc43aebb87ed84b00e6d90685c0.tar.bz2
blog_content-9bb990c9a663edc43aebb87ed84b00e6d90685c0.tar.lz
blog_content-9bb990c9a663edc43aebb87ed84b00e6d90685c0.tar.xz
blog_content-9bb990c9a663edc43aebb87ed84b00e6d90685c0.tar.zst
blog_content-9bb990c9a663edc43aebb87ed84b00e6d90685c0.zip
Update markdown syntax to use pandoc's peculiarities
-rw-r--r--articles/2010-02-06_debian_auf_dem_sheevaplug.md30
-rw-r--r--articles/2010-02-24_traffic_ueberwachung_mit_vnstat.md2
-rw-r--r--articles/2010-07-12_ocr_und_automatische_uebersetzung_mit_dem_n900.md6
-rw-r--r--articles/2011-03-31_sheevaplug_ueberwachung.md24
-rw-r--r--articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md32
-rw-r--r--articles/2011-09-03_die_sache_mit_dem_netzteil.md2
-rw-r--r--articles/2011-10-01_lighttpd_konfiguration_fuer_symphony.md20
-rw-r--r--articles/2011-10-02_tarsnap_backups_fuer_paranoide.md14
-rw-r--r--articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md5
-rw-r--r--articles/2011-11-08_informationen_umformen_mit_xsl.md15
-rw-r--r--articles/2012-01-25_erfahrungen_mit_openslides.md9
-rw-r--r--articles/2012-04-07_mobile_endgeraete_und_freie_software.md2
-rw-r--r--articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md5
-rw-r--r--articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md72
-rw-r--r--articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md10
-rw-r--r--articles/2013-10-06_notizen_zu_cpp_und_unicode.md26
-rw-r--r--articles/2013-11-03_mapping_binary_structures_as_tuples_using_template_metaprogramming.md35
-rw-r--r--articles/2013-12-21_musikalischer_jahresruekblick_2013.md4
-rw-r--r--articles/2014-01-05_disabling_methods_in_implicitly_instantiated_class_template_specializations_in_cpp.md15
-rw-r--r--articles/2014-07-11_mapping_arrays_using_tuples_in_cpp11.md14
-rw-r--r--articles/2014-10-30_expanding_xslt_using_xalan_and_cpp.md15
-rw-r--r--articles/2015-01-14_a_look_at_compile_time_computation_in_cpp.md20
-rw-r--r--articles/2015-03-06_using_scheme_as_a_metaphor_for_template_metaprogramming.md47
-rw-r--r--articles/2015-09-18_nokia_heir_and_hardware_keyboards.md2
-rw-r--r--articles/2015-09-24_the_joys_of_ipv6.md66
-rw-r--r--articles/2016-02-21_notes_on_function_interposition_in_cpp.md48
-rw-r--r--articles/2016-05-22_visualisierung_von_metriken_in_voronoi_diagrammen.md84
-rw-r--r--pages/about.md2
-rw-r--r--pages/impressum.md1
-rw-r--r--pages/projects/binary_mapping.md5
-rw-r--r--pages/projects/build_xslt.md10
-rw-r--r--pages/projects/codepoint_iterator.md5
-rw-r--r--pages/projects/const_list.md5
-rw-r--r--pages/projects/input_xslt.md13
-rw-r--r--pages/projects/kv.md21
-rw-r--r--pages/projects/static_xslt.md4
-rw-r--r--pages/projects/telebot.md10
-rw-r--r--pages/projects/trie.md5
-rw-r--r--pages/projects/type_as_value.md5
39 files changed, 328 insertions, 382 deletions
diff --git a/articles/2010-02-06_debian_auf_dem_sheevaplug.md b/articles/2010-02-06_debian_auf_dem_sheevaplug.md
index c7bc555..fb82abb 100644
--- a/articles/2010-02-06_debian_auf_dem_sheevaplug.md
+++ b/articles/2010-02-06_debian_auf_dem_sheevaplug.md
@@ -4,54 +4,48 @@ Auf dem herkömmlichen [Weg](http://www.cyrius.com/debian/kirkwood/sheevaplug/)
Als erstes laden wir uns den normalen SheevaInstaller herunter mit dem man Ubuntu 9.04 auf dem Sheeva installieren kann ([klick](http://www.plugcomputer.org/index.php/us/resources/downloads?func=select&id=5)). Nach dem wir den Tarball heruntergeladen haben sollte man ihn entpacken. Als nächstes laden wir ein Debian Lenny / Squeeze Prebuild von [hier](http://www.mediafire.com/sheeva-with-debian) herunter. Nun ersetzen wir die „rootfs.tar.gz“ mit der neuen Debian „rootfs.tar.gz“. Bevor wir jedoch mit der Installation beginnen müssen wir die neue „rootfs.tar.gz“ mit „tar“ entpacken. Dazu führen wir auf der Konsole
-~~~
+```sh
mkdir rootfs
cd rootfs
tar xfvz rootfs.tar.gz
-~~~
-{: .language-sh}
+```
aus. In dem Ordner führen wir nun ein
-~~~
+```sh
mknod -m 660 dev/ttyS0 c 4 64
-~~~
-{: .language-sh}
+```
aus. Mit diesem Befehl wird die fehlende serielle Konsole erstellt. Jetzt verpacken wir das Archiv wieder mit
-~~~
+```sh
tar cfvz ../rootfs.tar.gz *
-~~~
-{: .language-sh}
+```
Den gesamten Inhalt des Ordners /install im SheevaInstaller-Verzeichniss müssen wir jetzt auf einen mit FAT formatierten USB-Stick kopieren. Diesen stecken wir schon einmal in den USB-Port des Sheevas. Als nächstes verbinden wir den SheevaPlug mit einem Mini-USB Kabel mit unserem Computer und führen das Script „runme.php“ aus. Wenn alles klappt wird nun ein neuer Boot-Loader und das rootfs auf den Plug kopiert. Dannach ist unser Debian einsatzbereit.
Sollte der Plug den USB-Stick nicht erkennen und somit auch das rootfs nicht kopieren können hilft es einen anderen USB-Stick zu verwenden. Beispielsweise wurde mein SanDisk U3 Stick trotz gelöschtem U3 nicht erkannt. Mit einem anderen Stick funktionierte es jedoch tadelos. Auch sollte der Stick partitioniert sein. Der Bootloader des SheevaPlugs kann nicht gut mit direkt auf dem Stick enthalten Dateisystemen umgehen. Wenn die MiniUSB Verbindung beim Ausführen des runme-Scripts nicht funktionieren sollte hilft oft ein
-~~~
+```sh
rmmod ftdi_sio
-~~~
-{: .language-sh}
+```
und
-~~~
+```sh
modprobe ftdi_sio vendor=0x9e88 product=0x9e8f
-~~~
-{: .language-sh}
+```
(beides als root). Ebenfalls sollte kein zweites Serielles-Gerät am Computer angeschlossen sein.
Bei neueren Plugs kann man bei Problemen bei der Installation die Datei „uboot/openocd/config/interface/sheevaplug.cfg“ im SheevaInstaller-Ordner nach
-~~~
+```sh
interface ft2232
ft2232_layout sheevaplug
ft2232_vid_pid 0×0403 0×6010
#ft2232_vid_pid 0x9e88 0x9e8f
#ft2232_device_desc “SheevaPlug JTAGKey FT2232D B”
jtag_khz 2000
-~~~
-{: .language-sh}
+```
umändern.
Wenn Debian jetzt auf dem SheevaPlug läuft und man sich über SSH einloggen konnte (pwd: nosoup4u), sollte man als erstes ein Update machen.
diff --git a/articles/2010-02-24_traffic_ueberwachung_mit_vnstat.md b/articles/2010-02-24_traffic_ueberwachung_mit_vnstat.md
index 309852c..9178cab 100644
--- a/articles/2010-02-24_traffic_ueberwachung_mit_vnstat.md
+++ b/articles/2010-02-24_traffic_ueberwachung_mit_vnstat.md
@@ -3,7 +3,7 @@
Heute möchte ich euch ein kleines und praktisches Programm zum Überwachen des Netzwerkverkehrs vorstellen: [vnstat](http://humdi.net/vnstat/).
vnStat ist ein konsolenbasierter Netzwerkverkehrmonitor der Logs mit der Menge des Datenverkehrs auf beliebigen Netzwerkschnittstellen speichert. Aus diesen Logs generiert vnStat dann diverse Statistiken.
-![vnStat](https://static.kummerlaender.eu/media/vnstat.jpg){: .full}
+![vnStat](https://static.kummerlaender.eu/media/vnstat.jpg){.full}
Installieren kann man vnstat unter Debian bequem aus den Paketquellen mit `apt-get install vnstat` oder unter ArchLinux mit `pacman -S vnstat`. Gestartet wird vnStat mit `vnstat`. Sobald der Daemon läuft schreibt vnstat den aktuellen Netzwerkverkehr in eine Datenbank. Durch Anhängen von Argumenten kann man jetzt schöne Statistiken auf der Konsole ausgeben, z.B. eine Statistik über die letzten Tage mit `vnstat -d` (siehe Bild) oder über die letzten Wochen mit `vnstat -w`. Eine Übersicht über alle möglichen Argumente bekommt man wie Üblich über `vnstat –help`. Eine sehr Interessante Funktion wie ich finde ist die Möglichkeit zur live-Anzeige des Verkehrs mit `vnstat -h`.
diff --git a/articles/2010-07-12_ocr_und_automatische_uebersetzung_mit_dem_n900.md b/articles/2010-07-12_ocr_und_automatische_uebersetzung_mit_dem_n900.md
index 150f747..7ccc7ec 100644
--- a/articles/2010-07-12_ocr_und_automatische_uebersetzung_mit_dem_n900.md
+++ b/articles/2010-07-12_ocr_und_automatische_uebersetzung_mit_dem_n900.md
@@ -2,15 +2,15 @@
Heute bin ich auf einem Streifzug durch das Maemo5 testing-Repository auf ein sehr praktisches Programm gestoßen: PhotoTranslator. Mit ihm lässt sich der Text aus Bildern extrahieren und mittels Google-Translate übersetzen.
-![PhotoTranslator - Start](https://static.kummerlaender.eu/media/n900_photo_translator1.jpg){: .full width="600px"}
+![PhotoTranslator - Start](https://static.kummerlaender.eu/media/n900_photo_translator1.jpg){.full width="600px"}
Das ist z.B. praktisch um fremdsprachige Speisekarten o.ä. in die eigene Sprache zu übersetzen. Nachdem man ein Bild ausgewählt oder direkt aus dem Programm heraus eines erstellt hat (funktioniert in der aktuellen Alpha-Version von PhotoTranslator noch nicht richtig) muss man als erstes den gewünschten Textteil mittels eines Rahmens, wie man ihn auch zum Zuschneiden von Fotos im Bildbetrachter des N900 verwendet auswählen – zur Zeit geht das jedoch leider nur mit einzelnen Zeilen und nicht mit ganzen Textblöcken.
-![PhotoTranslator - Textauswahl](https://static.kummerlaender.eu/media/n900_photo_translator2.jpg){: .full width="600px"}
+![PhotoTranslator - Textauswahl](https://static.kummerlaender.eu/media/n900_photo_translator2.jpg){.full width="600px"}
Danach muss man nurnoch die Ausgangs und Zielsprache wählen, kurz warten und schon bekommt man den eingescannten Ausgangstext und die Übersetzung präsentiert. Das funktioniert auch schon in dieser frühen Alpha-Version sehr gut.
-![PhotoTranslator - Übersetzung](https://static.kummerlaender.eu/media/n900_photo_translator3.jpg){: .full width="600px"}
+![PhotoTranslator - Übersetzung](https://static.kummerlaender.eu/media/n900_photo_translator3.jpg){.full width="600px"}
PhotoTranslator lässt sich aber nicht nur zum Übersetzen von Bildern, sondern auch als einfache Oberfläche für Google-Translate mit Texteingabe über die Tastatur verwenden.
Weitere Informationen und ein Demo-Video findet ihr unter [cybercomchannel.com](http://www.cybercomchannel.com/?p=63). Installieren lässt sich PhotoTranslator bei aktivierten extras-testing Repositories bequem aus der Paketverwaltung des N900 heraus.
diff --git a/articles/2011-03-31_sheevaplug_ueberwachung.md b/articles/2011-03-31_sheevaplug_ueberwachung.md
index 89ac393..311f34c 100644
--- a/articles/2011-03-31_sheevaplug_ueberwachung.md
+++ b/articles/2011-03-31_sheevaplug_ueberwachung.md
@@ -4,15 +4,14 @@ Um den Überblick über die Auslastung und den Traffic meines SheevaPlugs zu beh
Den Systemmonitor Conky lasse ich mit dem Befehl `ssh -X -vv -Y -p 22 adrian@asterix "conky -c /home/adrian/.conkyrc"` über X-forwarding in meiner XFCE-Session anzeigen. Das klappt einwandfrei und ergibt zusammen mit dieser [Conky-Konfiguration](http://adrianktools.redirectme.net/files/.conkyrc) und einer lokalen Conky-Instanz folgendes Bild:
-![Zwei Conky-Instanzen unter XFCE](https://static.kummerlaender.eu/media/remote_conky.jpg){: .full}
+![Zwei Conky-Instanzen unter XFCE](https://static.kummerlaender.eu/media/remote_conky.jpg){.full}
Zusätzlich loggt der SheevaPlug regelmäßig die aktuellen Systemdaten wie CPU-Auslastung, Netzwerkverkehr und belegten Arbeitsspeicher und generiert sie zu Graphen die mir dann jede Nacht per eMail zugesand werden.
Zum Loggen der Daten verwende ich dstat das mit folgendem, von einem Cron-Job gestarteten Befehl aufgerufen wird:
-~~~
+```sh
dstat -tcmn 2 1 | tail -1 >> /var/log/systat.log
-~~~
-{: .language-sh}
+```
Die Argumente -tcmn geben hierbei die zu loggenden Systemdaten und deren Reihenfolge an – heraus kommen Zeilen wie diese:
@@ -20,7 +19,7 @@ Die Argumente -tcmn geben hierbei die zu loggenden Systemdaten und deren Reihenf
Um 0 Uhr wird dann die Log-Datei von einem Cron-Job mit diesem Script wegkopiert, Graphen werden von gnuplot generiert und dann mit einem kleinen Python-Programm versendet.
-~~~
+```sh
#!/bin/sh
mv /var/log/systat.log /root/sys_graph/stat.dat
cd /root/sys_graph/
@@ -28,12 +27,11 @@ cd /root/sys_graph/
./generate_memory.plot
./generate_network.plot
./send_report.py
-~~~
-{: .language-sh}
+```
Hier das gnuplot-Script zur Erzeugung des CPU-Graphen als Beispiel:
-~~~
+```sh
#!/usr/bin/gnuplot
set terminal png
set output "cpu.png"
@@ -46,12 +44,11 @@ set format x "%H:%M"
plot "stat.dat" using 1:4 title "system" with lines, \
"stat.dat" using 1:3 title "user" with lines, \
"stat.dat" using 1:5 title "idle" with lines
-~~~
-{: .language-sh}
+```
… und hier noch das Python-Programm zum Versenden per Mail:
-~~~
+```python
#!/usr/bin/python2
import smtplib
from time import *
@@ -82,12 +79,11 @@ s.login('mail@mail.mail', '#####')
s.sendmail('mail@mail.mail', 'mail@mail.mail', msg.as_string())
s.quit()
-~~~
-{: .language-python}
+```
Als Endergebniss erhalte ich dann täglich solche Grafiken per Mail:
-![CPU Plot](https://static.kummerlaender.eu/media/cpu_plot.jpg){: .full .clear}
+![CPU Plot](https://static.kummerlaender.eu/media/cpu_plot.jpg){.full .clear}
Ich finde es immer wieder erstaunlich mit wie wenigen Zeilen Quelltext man interessante Sachen unter Linux erzeugen kann – oder besser wie viel Programme wie gnuplot mit nur wenigen Anweisungen erzeugen können. So hat das komplette Schreiben dieser Scripts mit Recherche nur etwa 1,5 Stunden gedauert – inklusive Testen.
Alle verwendeten Programme sind in den ArchLinux Paketquellen vorhanden – auch in denen von PlugBox-Linux, einer Portierung von ArchLinux auf ARM-Plattformen die ich nur immer wieder empfehlen kann – besonders nach den jetzt oft erscheinenden Paket-Updates. Aber dazu auch dieser Artikel: [Plugbox Linux – Ein ArchLinux Port für den SheevaPlug](/article/plugbox_linux_ein_archlinux_port_fuer_den_sheevaplug/).
diff --git a/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md b/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md
index cc97add..28c95de 100644
--- a/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md
+++ b/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md
@@ -4,19 +4,18 @@ Bei meiner letzten Wanderung in den Schweizer Alpen habe ich spaßeshalber das N
Die Daten der Messpunkte sind im XML als `trkpt`-Tags gespeichert. Enthalten sind jeweils der Längen- und Breitengrad, die Uhrzeit, der Modus (3d / 2d), die Höhe über Null und die Anzahl der zur Positionsbestimmung genutzten Satelliten. Aussehen tut das ganze dann z.B. so:
-~~~
+```xml
<trkpt lat="47.320591" lon="9.329439">
<time>2011-06-12T07:57:39Z</time>
<fix>3d</fix>
<ele>870</ele>
<sat>6</sat>
</trkpt>
-~~~
-{: .language-xml}
+```
Diese Daten lassen sich nun sehr einfach Verarbeiten – ich habe das Python `xml.dom.minidom` Modul verwendet. Um die Positionen einfacher verwenden zu können, werden sie mit dieser Funktion in Listenform gebracht:
-~~~
+```python
def getPositions(xml):
doc = minidom.parse(xml)
node = doc.documentElement
@@ -29,12 +28,11 @@ def getPositions(xml):
pos["ele"] = int(TrkPt.getElementsByTagName("ele")[0].childNodes[0].nodeValue)
positions.append(pos)
return positions
-~~~
-{: .language-python}
+```
Aus dieser Liste kann ich jetzt schon einige Kennzahlen ziehen:
-~~~
+```python
def printStats(gpxPositions):
highEle = gpxPositions[0]["ele"]
lowEle = gpxPositions[0]["ele"]
@@ -48,8 +46,7 @@ def printStats(gpxPositions):
print "Lowest elevation: " + str(lowEle)
print "Highest elevation: " + str(highEle)
print "Height difference: " + str(eleDiv)
-~~~
-{: .language-python}
+```
Die Kennzahlen für meine Testdaten wären:
@@ -61,21 +58,20 @@ Die Kennzahlen für meine Testdaten wären:
Da die Daten ja, wie schon im Titel angekündigt, mit gnuplot dargestellt werden sollen werden sie mit dieser Funktion in für gnuplot lesbares CSV gebracht:
-~~~
+```python
def printCsv(gpxPositions):
separator = ';'
for pos in gpxPositions:
print pos["lat"] + separator + pos["lon"] + separator + str(pos["ele"])
-~~~
-{: .language-python}
+```
## Plotten mit gnuplot
-![Gnuplot output](https://static.kummerlaender.eu/media/gnuplot_gpx.jpg){: .full .clear}
+![Gnuplot output](https://static.kummerlaender.eu/media/gnuplot_gpx.jpg){.full .clear}
Eine solche, dreidimensionale Ausgabe der GPS Daten zu erzeugen ist mit der `splot`-Funktion sehr einfach.
-~~~
+```sh
#!/usr/bin/gnuplot
set terminal png size 1280,1024
set output "output.png"
@@ -90,16 +86,14 @@ set datafile separator ';'
splot "/home/adrian/projects/gpxplot/wanderung_120611.csv" with impulses lt 3 lw 1
splot "/home/adrian/projects/gpxplot/wanderung_120611.csv" with lines lw 2
unset multiplot
-~~~
-{: .language-sh}
+```
Mit `set terminal png size 1280,1024` und `set output "output.png"` werden zuerst das Ausgabemedium, die Größe und der Dateiname der Ausgabe definiert. Dannach aktiviert `set multiplot` den gnuplot-Modus, bei dem mehrere Plots in einer Ausgabe angezeigt werden können. Dieses Verhalten brauchen wir hier, um sowohl die Strecke selbst als rote Line, als auch die zur Verdeutlichung verwendeten blauen Linien gleichzeitig anzuzeigen.
Mit `set [y,x,z]range` werden die Außengrenzen des zu plottenden Bereichs gesetzt. Dies ließe sich natürlich auch über ein Script automatisch erledigen. Als Nächstes wird mit `set view 28,272,1,1` die Blickrichtung und Skalierung definiert. `set ticslevel 0` sorgt dafür, dass die Z-Achse direkt auf der Grundebene beginnt. Um ein Gitter auf der Grundfläche anzuzeigen, gibt es `set grid`.
Als letztes werden jetzt die zwei Plots mit `splot` gezeichnet. Die Angaben hinter `with` steuern hierbei das Aussehen der Linien.
-Falls jemand den Artikel mit meinen Daten nachvollziehen möchte - das GPX-File kann hier heruntergeladen werden:
- [2011-06-12.gpx](https://static.kummerlaender.eu/media/2011-06-12.gpx)
+Falls jemand den Artikel mit meinen Daten nachvollziehen möchte - das GPX-File kann hier heruntergeladen werden: [2011-06-12.gpx](https://static.kummerlaender.eu/media/2011-06-12.gpx)
Zum Schluss hier noch ein Blick vom Weg auf den Kronberg Richtung Jakobsbad im Appenzell:
-![Aussicht auf Jakobsbad im Appenzell](https://static.kummerlaender.eu/media/kronberg.jpg){: .full}
+![Aussicht auf Jakobsbad im Appenzell](https://static.kummerlaender.eu/media/kronberg.jpg){.full}
diff --git a/articles/2011-09-03_die_sache_mit_dem_netzteil.md b/articles/2011-09-03_die_sache_mit_dem_netzteil.md
index c96d7d5..4da8fdb 100644
--- a/articles/2011-09-03_die_sache_mit_dem_netzteil.md
+++ b/articles/2011-09-03_die_sache_mit_dem_netzteil.md
@@ -2,6 +2,6 @@
Diese Woche hat meinen SheevaPlug das selbe Schicksal getroffen wie viele andere auch – nach dem Urlaub war das Netzteil kaputt. Mit einem externen von [Conrad](http://www.conrad.de/ce/de/product/510820/Dehner-SYS1308-Netzt-fests-5V15W%22%22) geht er jetzt aber wieder einwandfrei.
-![Der reparierte SheevaPlug](https://static.kummerlaender.eu/media/sheevaplug_repair.jpg){: .full}
+![Der reparierte SheevaPlug](https://static.kummerlaender.eu/media/sheevaplug_repair.jpg){.full}
Als sehr nützlich, um in der Zeit bis der Plug repariert war wenigstens eine _Netzteil-Kaputt_-Meldung auf der Webseite anzeigen zu können, erwies sich [Staticloud](http://staticloud.com) – ein netter Webservice um statische Webseiten per drag ‘n drop kostenlos in der Amazon-Cloud hosten zu können. Um die Inhalte zugänglich zu halten (Backup habe ich natürlich schon – aber bis jetzt nur als MySQL-Dump, ab jetzt wohl auch das ganze als HTML ) half mir Google – der gesammte Blog hängt praktischerweise dort im Cache.
diff --git a/articles/2011-10-01_lighttpd_konfiguration_fuer_symphony.md b/articles/2011-10-01_lighttpd_konfiguration_fuer_symphony.md
index fade6af..90fa82e 100644
--- a/articles/2011-10-01_lighttpd_konfiguration_fuer_symphony.md
+++ b/articles/2011-10-01_lighttpd_konfiguration_fuer_symphony.md
@@ -4,14 +4,16 @@ Da ich die Neuauflage dieser Seite nicht mehr auf Wordpress, sondern auf dem [Sy
Von den im Netz verfügbaren [Beispielen](http://blog.ryara.net/2009/12/05/lighttpd-rewrite-rules-for-symphony-cms/) hat jedoch keines ohne Einschränkungen funktioniert. Aus diesem Grund habe ich auf Basis der oben verlinkten Konfiguration ein funktionierendes Regelwerk geschrieben:
- url.rewrite-once += (
- "^/favicon.ico$" => "$0",
- "^/robots.txt$" => "$0",
- "^/symphony/(assets|content|lib|template)/.*$" => "$0",
- "^/workspace/([^?]*)" => "$0",
- "^/symphony(\/(.*\/?))?(.*)\?(.*)$" => "/index.php?symphony-page=$1&mode=administration&$4&$5",
- "^/symphony(\/(.*\/?))?$" => "/index.php?symphony-page=$1&mode=administration",
- "^/([^?]*/?)(\?(.*))?$" => "/index.php?symphony-page=$1&$3"
- )
+```
+url.rewrite-once += (
+ "^/favicon.ico$" => "$0",
+ "^/robots.txt$" => "$0",
+ "^/symphony/(assets|content|lib|template)/.*$" => "$0",
+ "^/workspace/([^?]*)" => "$0",
+ "^/symphony(\/(.*\/?))?(.*)\?(.*)$" => "/index.php?symphony-page=$1&mode=administration&$4&$5",
+ "^/symphony(\/(.*\/?))?$" => "/index.php?symphony-page=$1&mode=administration",
+ "^/([^?]*/?)(\?(.*))?$" => "/index.php?symphony-page=$1&$3"
+)
+```
Dieses läuft mit der aktuellsten Symphony Version einwandfrei. Zu finden ist die Konfiguration übrigens mit den restlichen Quellen meines neuen Webseiten-Setups auf [Github](https://github.com/KnairdA/blog.kummerlaender.eu).
diff --git a/articles/2011-10-02_tarsnap_backups_fuer_paranoide.md b/articles/2011-10-02_tarsnap_backups_fuer_paranoide.md
index 7aedf41..d3dca15 100644
--- a/articles/2011-10-02_tarsnap_backups_fuer_paranoide.md
+++ b/articles/2011-10-02_tarsnap_backups_fuer_paranoide.md
@@ -4,23 +4,29 @@ Für meine Backups nutze ich jetzt seit einiger Zeit den Online-Service [Tarsnap
Das ganze ist so aufgebaut, dass immer nur veränderte und neue Dateien übertragen werden müssen. Alle Daten werden schon vom Client verschlüsselt, sodass keine unverschlüsselten Daten übers Netzwerk fließen und weder die Entwickler von Tarsnap noch Amazon den Inhalt der Daten auslesen können.
-Der Service ist nicht kostenlos, aber sehr günstig - der Preis pro Byte Speicher / Datenverkehr beträgt 300 Picodollar, ein Gigabyte kostet also pro Monat nur 0,30$.
+Der Service ist nicht kostenlos, aber sehr günstig - der Preis pro Byte Speicher / Datenverkehr beträgt 300 Picodollar, ein Gigabyte kostet also pro Monat nur 0,30 Dollar.
Der Tarsnap-Client ist im Quellcode verfügbar (aber nicht unter einer Open Source Lizenz) und lässt sich problemlos auch auf ARM Prozessoren kompilieren, sodass ich auch vom N900 und SheevaPlug aus Zugriff auf meine Backups haben kann. Die Authentifizierung mit dem Server funktioniert über einen Schlüssel, der sich nach Eingabe des Passworts mit folgendem Befehl generieren lässt:
- tarsnap-keygen --keyfile [pfad-zum-schlüssel] --user [email] --machine [hostname]
+```sh
+tarsnap-keygen --keyfile [pfad-zum-schlüssel] --user [email] --machine [hostname]
+```
Die resultierende Datei ermöglicht ohne zusätzliche Authentifizierung Zugriff auf die Backups und sollte somit sicher aufbewahrt werden und nicht in falsche Hände geraten, denn ohne sie hat man keinen Zugriff mehr auf seine Daten.
Ein neues Backup lässt sich über diesen Befehl anlegen:
- tarsnap -c -f [name-des-backups] [zu-sichernder-pfad]
+```sh
+tarsnap -c -f [name-des-backups] [zu-sichernder-pfad]
+```
Jedes weitere Backup geht danach um einiges schneller weil Tarsnap nur veränderte Daten überträgt. Standardmäßig wird dieser Cache unter "/usr/local/tarsnap-cache" und der Schlüssel unter "/root/tarsnap.key" erwartet, dies lässt sich jedoch über entsprechende Parameter steuern - näheres dazu findet sich auf der [Manpage](http://www.tarsnap.com/man-tarsnap.1.html).
Sollte man dann einmal in die nicht wünschenswerte Situation kommen Zugriff auf sein Backup zu benötigen, reicht dieser Befehl um die Daten wiederherzustellen:
- tarsnap -x -f [name-des-backups] [wiederherzustellender-pfad]
+```sh
+tarsnap -x -f [name-des-backups] [wiederherzustellender-pfad]
+```
Tarsnap kann ich wirklich empfehlen, es hat mich vom [Konzept](http://www.tarsnap.com/design.html) und der Umsetzung her voll überzeugt und ist auf jeden Fall eine ernst zunehmende Alternative zu anderen Backuplösungen in der _Wolke_.
diff --git a/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md b/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md
index f59b709..4084d69 100644
--- a/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md
+++ b/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md
@@ -7,9 +7,8 @@ Erst sah es so aus, als würde ich nicht darum herum kommen das Betriebsystem ne
Dabei handelt es sich um ein kleines Linux welches mithilfe des normalen [Flashers](http://tablets-dev.nokia.com/maemo-dev-env-downloads.php) direkt in den RAM des N900 kopiert und dort gebootet werden kann. Vom rescueOS aus kann man dann das Root-Dateisystem problemlos einbinden und Probleme beheben. Zum Starten reicht das [initrd Image](http://n900.quitesimple.org/rescueOS/rescueOS-1.0.img) und folgender Befehl:
-~~~
+```sh
flasher-3.5 -k 2.6.37 -n initrd.img -l -b"rootdelay root=/dev/ram0"
-~~~
-{: .language-sh}
+```
Nähere Informationen zur Verwendung und den Funktionen finden sich in der rescueOS [Dokumentation](http://n900.quitesimple.org/rescueOS/documentation.txt).
diff --git a/articles/2011-11-08_informationen_umformen_mit_xsl.md b/articles/2011-11-08_informationen_umformen_mit_xsl.md
index 7785b83..f84f17c 100644
--- a/articles/2011-11-08_informationen_umformen_mit_xsl.md
+++ b/articles/2011-11-08_informationen_umformen_mit_xsl.md
@@ -8,7 +8,7 @@ Schlussendlich habe ich dann eine [XSLT](http://de.wikipedia.org/wiki/XSLT) gesc
Mit XSL lassen sich XML Dateien in andere Formen bringen. Da Mediawiki mehr oder weniger valides XHTML ausgibt, kann man, nachdem das XHTML mit [Tidy](http://tidy.sourceforge.net) ein wenig aufgeräumt wurde, sehr einfach die [Terminliste](http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine) extrahieren und gleichzeitig in RSS umformen:
-~~~
+```xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://www.w3.org/1999/xhtml"
@@ -57,8 +57,7 @@ Mit XSL lassen sich XML Dateien in andere Formen bringen. Da Mediawiki mehr oder
<xsl:template match="text()"/>
</xsl:stylesheet>
-~~~
-{: .language-xsl}
+```
Der Kern dieses XSL ist nicht mehr als ein Template welches auf den [XPATH](http://de.wikipedia.org/wiki/XPATH) zum Finden der Terminliste reagiert. Die For-Each-Schleife iteriert dann durch die Termine und formt diese entsprechend in RSS um.
Der einzige Knackpunkt kommt daher, dass XHTML kein normales XML ist und somit seinen eigenen Namespace hat. Diesen sollte man im Element `xsl:stylesheet` korrekt angeben, sonst funktioniert nichts. Auch muss im XPATH Ausdruck dann vor jedem Element ein `x:` eingefügt werden um dem XSL Prozessor den Namespace für das jeweilige Element mitzuteilen.
@@ -72,17 +71,16 @@ Zum Anpassen des Datums verwende ich - wie auch in diesem Blog - die [date-time.
Mit der eben beschriebenen XSLT lässt sich jetzt in drei Schritten das fertige RSS generieren:
-~~~
+```sh
#!/bin/sh
wget -O termine_wiki.html "http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine"
tidy -asxml -asxhtml -O termine_tidy.html termine_wiki.html
xsltproc --output termine_kvkn.rss --novalid termine_kvkn.xsl termine_tidy.html
-~~~
-{: .language-sh}
+```
In PHP ist das ganze dann zusammen mit sehr einfachem Caching auch direkt auf einem Webserver einsetzbar:
-~~~
+```php
define('CACHE_TIME', 6);
define('CACHE_FILE', 'rss.cache');
@@ -139,5 +137,4 @@ function generate_rss()
return false;
}
}
-~~~
-{: .language-php}
+```
diff --git a/articles/2012-01-25_erfahrungen_mit_openslides.md b/articles/2012-01-25_erfahrungen_mit_openslides.md
index 2804605..b670400 100644
--- a/articles/2012-01-25_erfahrungen_mit_openslides.md
+++ b/articles/2012-01-25_erfahrungen_mit_openslides.md
@@ -6,13 +6,13 @@ OpenSlides ist ein auf dem Python-Webframework [Django](https://www.djangoprojec
Das UI ist dabei in den Administrationsbereich, über den sämtliche Daten eingegeben werden können, und eine Beamer-Ansicht geteilt. Beide dieser Komponenten laufen in einem gewöhnlichen Webbrowser. Das Aussehen lässt sich also einfach durch Modifikation der Templates und der CSS-Formatierungen an die eigenen Wünsche anpassen.
-![KPT OpenSlides](https://static.kummerlaender.eu/media/kpt_it.jpg){: .full}
+![KPT OpenSlides](https://static.kummerlaender.eu/media/kpt_it.jpg){.full}
Nachdem ich anfangs alle Wahlen, bekannten Teilnehmer und Anträge in das Redaktionsystem eingespiesen hatte, ließ sich am Parteitag selbst dann mit wenigen Mausklicks eine ansprechende Präsentation des aktuellen Themas erzeugen.
Wahlergebnisse waren ebenso wie die Annahme oder Ablehnung eines Antrags über entsprechende Formulare schnell eingepflegt und dargestellt.
Sehr gefallen hat mir im Vorfeld auch die Möglichkeit der Generierung von Antragsbüchern als PDF.
-![KPT OpenSlides](https://static.kummerlaender.eu/media/kpt_openslides.png){: .full}
+![KPT OpenSlides](https://static.kummerlaender.eu/media/kpt_openslides.png){.full}
Der Funktionsumfang von OpenSlides geht jedoch über die bloße Darstellung der TO auf einem Beamer hinaus. So kann wenn gewünscht jeder Teilnehmer über sein eigenes Endgerät auf das Webinterface zugreifen und als Deligierter an der Versammlung teilnehmen - also Abstimmen, Wählen und Anträge stellen.
Theoretisch ermöglicht es diese Software also - bei entsprechender Authentifizierung - die Durchführung von dezentralen Versammlungen. Aber auch wenn dies z.B. aufgrund von zur Nachvollziehbarkeit nötiger Klarnamenspflicht nicht in Frage kommt, ergibt sich doch so für die Teilnehmer immerhin die Möglichkeit den Ablauf auf einem eigenen Gerät nachzuverfolgen.
@@ -20,7 +20,7 @@ Theoretisch ermöglicht es diese Software also - bei entsprechender Authentifizi
Der einzige Punkt der mich wirklich störte war die fehlende Anzeige von Wahlergebnissen der Teilnehmer die eine Wahl verloren hatten. Die jeweilige Stimmenzahl war im Frontend erst sichtbar nachdem der entsprechende Kandidat als Sieger markiert worden war.
Doch auch dieses Problem ließ sich - OpenSource sei Dank - schnell über manuelles Eingreifen im Quelltext korrigieren:
-~~~
+```diff
--- /home/adrian/Downloads/original_views.py
+++ /opt/hg.openslides.org/openslides/agenda/views.py
@@ -132,14 +132,11 @@
@@ -42,8 +42,7 @@ Doch auch dieses Problem ließ sich - OpenSource sei Dank - schnell über manuel
else:
tmplist[1].append("-")
votes.append(tmplist)
-~~~
-{: .language-diff}
+```
OpenSlides ist wirklich ein tolles Stück Software und ich kann nur jedem der vor der Aufgabe steht eine Versammlung zu organisieren, sei es die eines Vereins oder wie in meinem Fall die einer Partei, empfehlen sich es einmal näher anzusehen.
Weitere Angaben zur Installation und Konfiguration finden sich auf der [Webpräsenz](http://openslides.org/de/index.html) und im [Quell-Archiv](http://openslides.org/download/openslides-1.1.tar.gz).
diff --git a/articles/2012-04-07_mobile_endgeraete_und_freie_software.md b/articles/2012-04-07_mobile_endgeraete_und_freie_software.md
index 26d6435..8feba56 100644
--- a/articles/2012-04-07_mobile_endgeraete_und_freie_software.md
+++ b/articles/2012-04-07_mobile_endgeraete_und_freie_software.md
@@ -11,7 +11,7 @@ Geräte die auf Android als Betriebssystem setzen bieten natürlich prinzipiell
Glücklicherweise sind wir nicht ganz auf Android-ausführende Hardware beschränkt. Das Mobiltelefon meiner Wahl ist seit etwa 2 Jahren beispielsweise das [N900](http://en.wikipedia.org/wiki/Nokia_N900), das aus meiner Sicht wirklich als **das** offene Gerät auf dem Markt angesehen werden kann. Ich könnte hier jetzt seitenweise Punkte aufzählen was alles mit dem N900 möglich ist aber es geht auch kurz:
-![N900](https://static.kummerlaender.eu/media/n900_teaser.png){: .full width="600px"}
+![N900](https://static.kummerlaender.eu/media/n900_teaser.png){.full width="600px"}
Mit dem N900 lässt sich, ohne das man durch herstellerseitige Einschränkungen belästigt wird, alles machen was mit einem normalen Linux-Rechner geht. Die einzige mir bekannte Einschränkung ist: Teile der Hardware wie z.B. die Grafikkarte erfordern (noch) unfreie, geschlossene Treiber.
diff --git a/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md b/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md
index 7be6d2a..72ce8c0 100644
--- a/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md
+++ b/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md
@@ -21,7 +21,7 @@ nötig sein sollte ist das umso besser. Die 16 GiB SD-Karte des SheevaPlugs läu
Hier meine derzeitige `/etc/fstab`:
-~~~
+```sh
#
# /etc/fstab: static file system information
#
@@ -30,8 +30,7 @@ tmpfs /tmp tmpfs nodev,nosuid 0 0
/dev/sda1 swap swap defaults,noatime,discard 0 0
/dev/sda2 / ext4 defaults,noatime,discard,data=ordered 0 0
-~~~
-{: .language-sh}
+```
## Verschlüsselung?
diff --git a/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md b/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md
index a4b1924..8d3e8db 100644
--- a/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md
+++ b/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md
@@ -25,10 +25,9 @@ des Gast-Systems werden auf die gleiche Weise gesetzt. Aus diesem Grund gehe ich
Hier als Beispiel mein derzeitiger Standardaufruf von KVM, der für alle VMs gleich ist. Dynamisch ist allein das zu verwendende Speicher-Gerät - in meinem Fall verschiedene Image-Dateien.
-~~~
+```sh
qemu-kvm -cpu host -hda $1 -m 1024 -daemonize -vnc none -usb -net nic -net vde
-~~~
-{: .language-sh}
+```
Dieser verwendet das als erster Parameter übergebene Gerät als Festplatte und setzt neben den nötigen Netzwerk-Einstellungen die VM mittels `-daemonize` in den Hintergrund. Falls benötigt, kann
als Wert des Parameters `-vnc` auch eine von einem Doppelpunkt angeführte Zahl übergeben werden um die Grafik-Ausgabe der VM an einen VNC-Server anzubinden (z.B. `-vnc :1` für `127.0.0.1:1`). Diese
@@ -40,7 +39,7 @@ Funktion verwende ich nicht, da ich ausschließlich über das interne Netzwerk d
Meine Konfiguration hält sich dabei im wesentlichen an den [Vorschlag](https://wiki.archlinux.org/index.php/QEMU#Networking_with_VDE2) im englischen Arch-Wiki, welchen ich in ein einfaches Script verpackt habe:
-~~~
+```sh
#!/bin/sh
case "$1" in
start)
@@ -55,8 +54,7 @@ case "$1" in
ip tuntap del tap0 mode tap
;;
esac
-~~~
-{: .language-sh}
+```
Dieses Script erzeugt ein virtuelles Interface `tap0` und verbindet ein neues, als Daemon im Hintergrund laufendes, virtuelles Switch mit diesem. Als nächstes wird dann noch eine statische IP Konfiguration für das virtuelle Interface definiert. Durch diese können alle mit `-net nic -net vde` Parametern gestarteten KVM Gäste über die IP `192.168.100.254` auf den Host zugreifen.
@@ -70,7 +68,7 @@ In den Gast-Systemen selbst muss zusätzlich eine statische IP Konfiguration vor
Um das interne virtuelle LAN bei Bedarf mit der Außenwelt zu verbinden gibt es ebenfalls ein kleines Script welches die nötige Route erzeugt bzw. löscht:
-~~~
+```sh
#!/bin/sh
case "$1" in
start)
@@ -82,8 +80,7 @@ case "$1" in
echo "0" > /proc/sys/net/ipv4/ip_forward
;;
esac
-~~~
-{: .language-sh}
+```
Anpassbar ist hierbei das Interface, um z.B. daheim `eth0` und unterwegs wahlweise `wlan0` oder `usb0` verwenden zu können.
@@ -91,38 +88,39 @@ Anpassbar ist hierbei das Interface, um z.B. daheim `eth0` und unterwegs wahlwei
Nach einer Kernel Aktualisierung im ArchLinux Gast-System, kam es beim Neustart plötzlich zu dieser etwas erschreckenden Meldung:
- KVM: entry failed, hardware error 0x80000021
-
- If you're running a guest on an Intel machine without unrestricted mode
- support, the failure can be most likely due to the guest entering an invalid
- state for Intel VT. For example, the guest maybe running in big real mode
- which is not supported on less recent Intel processors.
-
- EAX=00000000 EBX=0020fa5c ECX=00000000 EDX=fffff000
- ESI=f6d29014 EDI=00000001 EBP=f6461fa0 ESP=f6461f60
- EIP=c0128443 EFL=00010246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
- ES =007b 00000000 ffffffff 00c0f300 DPL=3 DS [-WA]
- CS =0060 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
- SS =0068 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
- DS =007b 00000000 ffffffff 00c0f300 DPL=3 DS [-WA]
- FS =00d8 36648000 ffffffff 00809300 DPL=0 DS16 [-WA]
- GS =00e0 f6d2f540 00000018 00409100 DPL=0 DS [--A]
- LDT=0000 ffff0000 f0000fff 00f0ff00 DPL=3 CS64 [CRA]
- TR =0080 f6d2d3c0 0000206b 00008b00 DPL=0 TSS32-busy
- GDT= f6d28000 000000ff
- IDT= c060b000 000007ff
- CR0=8005003b CR2=ffffffff CR3=006ef000 CR4=000006d0
- DR0=0000000000000000 DR1=0000000000000000 DR2=0000000700000000 DR3=0000000000000000
- DR6=00000000ffff0ff0 DR7=0000000000000400
- EFER=0000000000000000
- Code=00 8b 15 c4 b5 61 c0 55 89 e5 5d 8d 84 10 00 c0 ff ff 8b 00 <c3> 8d b6 00 00 00 00 8d bf 00 00 00 00 8b 15 a0 ae 61 c0 55 89 e5 53 89 c3 b8 30 00 00 00
+```
+KVM: entry failed, hardware error 0x80000021
+
+If you're running a guest on an Intel machine without unrestricted mode
+support, the failure can be most likely due to the guest entering an invalid
+state for Intel VT. For example, the guest maybe running in big real mode
+which is not supported on less recent Intel processors.
+
+EAX=00000000 EBX=0020fa5c ECX=00000000 EDX=fffff000
+ESI=f6d29014 EDI=00000001 EBP=f6461fa0 ESP=f6461f60
+EIP=c0128443 EFL=00010246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
+ES =007b 00000000 ffffffff 00c0f300 DPL=3 DS [-WA]
+CS =0060 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
+SS =0068 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
+DS =007b 00000000 ffffffff 00c0f300 DPL=3 DS [-WA]
+FS =00d8 36648000 ffffffff 00809300 DPL=0 DS16 [-WA]
+GS =00e0 f6d2f540 00000018 00409100 DPL=0 DS [--A]
+LDT=0000 ffff0000 f0000fff 00f0ff00 DPL=3 CS64 [CRA]
+TR =0080 f6d2d3c0 0000206b 00008b00 DPL=0 TSS32-busy
+GDT= f6d28000 000000ff
+IDT= c060b000 000007ff
+CR0=8005003b CR2=ffffffff CR3=006ef000 CR4=000006d0
+DR0=0000000000000000 DR1=0000000000000000 DR2=0000000700000000 DR3=0000000000000000
+DR6=00000000ffff0ff0 DR7=0000000000000400
+EFER=0000000000000000
+Code=00 8b 15 c4 b5 61 c0 55 89 e5 5d 8d 84 10 00 c0 ff ff 8b 00 <c3> 8d b6 00 00 00 00 8d bf 00 00 00 00 8b 15 a0 ae 61 c0 55 89 e5 53 89 c3 b8 30 00 00 00
+```
Dies sah für mich im ersten Moment wie ein klarer Hardware-Fehler aus, alle Informationen die sich über meine bevorzugte Suchmaschine finden ließen, waren jedoch für andere Situationen und ältere Kernel Versionen als `3.6.6-1`. Nach Tests mit verschiedenen Parametern für die zuständigen Kernel-Module, funktionierte es schließlich nach Laden des Moduls mit folgendem Befehl wieder einwandfrei:
-~~~
+```sh
modprobe kvm_intel emulate_invalid_guest_state=0
-~~~
-{: .language-sh}
+```
Um den `emulate_invalid_guest_state` Parameter dauerhaft zu setzen reicht ein Eintrag in `/etc/modprobe.d`.
diff --git a/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md b/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md
index ae04631..be0e41c 100644
--- a/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md
+++ b/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md
@@ -2,27 +2,25 @@
In a current project of mine I defined the following function marked with the inline hint without declaring it in a header file:
-~~~
+```cpp
inline bool checkStorageSection(const void* keyBuffer) {
return (StorageSection::Edge == readNumber<uint8_t>(
reinterpret_cast<const uint8_t*>(keyBuffer)+0
));
}
-~~~
-{: .language-cpp}
+```
This function was not defined in one but in multiple translation units - each instance with the same signature but a slightly different comparison contained in the function body. I expected these functions to be local to their respective translation unit and in the best case to be inlined into their calling member methods.
While debugging another issue that seemed to be unrelated to these functions I noticed a strange behaviour: The calls in the member methods that should have linked to their respective local function definition all linked to the same definition in a different translation unit (the one displayed above). A quick check in GDB using the _x_-command to display the function addresses confirmed this suspicion:
-~~~
+```gdb
// Function address in translation unit A
0x804e718 <GraphDB::checkStorageSection(void const*)>: 0x83e58955
// Function address in translation unit B
0x804e718 <GraphDB::checkStorageSection(void const*)>: 0x83e58955
-~~~
-{: .language-gdb}
+```
The address _0x804e718_ was the address of the function definition in translation unit "A" in both cases. At first I suspected that the cause was probably that both definitions were located in the same namespace, but excluding them from the enclosing namespace declaration did not fix the problem.
diff --git a/articles/2013-10-06_notizen_zu_cpp_und_unicode.md b/articles/2013-10-06_notizen_zu_cpp_und_unicode.md
index e900a66..0238df3 100644
--- a/articles/2013-10-06_notizen_zu_cpp_und_unicode.md
+++ b/articles/2013-10-06_notizen_zu_cpp_und_unicode.md
@@ -11,10 +11,9 @@ Getreu der auf [UTF-8 Everywhere](http://www.utf8everywhere.org/) hervorgebracht
Grundsätzlich stellt es auf der Plattform meiner Wahl - Linux mit Lokalen auf _en\_US.UTF-8_ - kein Problem dar, UTF-8 enkodierte Strings in C++ Programmen zu verarbeiten.
Den Klassen der C++ Standard Library ist es, solange wir nur über das reine Speichern und Bewegen von Strings sprechen, egal ob dieser in UTF-8, ASCII oder einem ganz anderen Zeichensatz kodiert ist. Möchten wir sicher gehen, dass ein in einer Instanz von _std::string_ enthaltener Text tatsächlich in UTF-8 enkodiert wird und dies nicht vom Zeichensatz der Quelldatei abhängig ist, reicht es dies durch voranstellen von _u8_ zu definieren:
-~~~
+```cpp
std::string test(u8"Hellø Uni¢ød€!");
-~~~
-{: .language-cpp}
+```
Der C++ Standard garantiert uns, dass ein solcher String in UTF-8 enkodiert wird. Auch die Ausgabe von in dieser Form enkodierten Strings funktioniert nach meiner Erfahrung - z.T. erst nach setzen der Lokale mittels _std::setlocale_ - einwandfrei. Probleme gibt es dann, wenn wir den Text als solchen näher untersuchen oder sogar verändern wollen bzw. die Ein- und Ausgabe des Textes in anderen Formaten erfolgen soll. Für letzteres gibt es eigentlich die _std::codecvt_ Facetten, welche aber in der aktuellen Version der GNU libstdc++ noch [nicht implementiert](http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2011) sind.
Wir müssen in diesem Fall also auf externe Bibliotheken wie beispielweise [iconv](https://www.gnu.org/software/libiconv/) oder [ICU](http://site.icu-project.org/) zurückgreifen. Auch die in der C++ Standard Library enthaltenen Templates zur String-Verarbeitung helfen uns bei Multibyte-Enkodierungen, zu denen auch UTF-8 zählt, nicht viel, da diese mit dem _char_ Datentyp und nicht mit Code-Points arbeiten. So liefert _std::string_ beispielsweise für einen UTF-8 enkodierten String, welcher nicht nur von dem in einer Code-Unit abbildbaren ASCII-Subset Gebrauch macht, nicht die korrekte Zeichenanzahl. Auch eine String-Iteration ist mit den Standard-Klassen nur Byte- und nicht Code-Point-Weise umsetzbar. Wir stehen also vor der Entscheidung eine weitere externe Bibliothek zu verwenden oder Programm-Intern vollständig auf UTF-32 zu setzen.
@@ -26,11 +25,12 @@ Um zumindest für rein lesende Zugriffe auf UTF-8 Strings nicht gleich eine Bibl
UTF-8 enkodiert die aktuell maximal 21 Bit eines Unicode Code-Points in bis zu vier Code-Units mit einer Länge von je einem Byte. Die verbleibenden
maximal 11 Bit werden dazu verwendet, Anfangs- und Fortsetzungs-Bytes eines Code-Points zu kennzeichnen und schon in der ersten Code-Unit zu definieren, in wie vielen Code-Units das aktuelle Symbol enkodiert ist.
-| Payload | Struktur |
-| 7 | `0xxxxxxx` |
-| 11 | `110xxxxx 10xxxxxx` |
-| 17 | `1110xxxx 10xxxxxx 10xxxxxx` |
-| 21 | `11110xxx 10xxxxxx 10xxxxxx 10xxxxxx` |
+Payload Struktur
+------- -------------------------------------
+7 `0xxxxxxx`
+11 `110xxxxx 10xxxxxx`
+17 `1110xxxx 10xxxxxx 10xxxxxx`
+21 `11110xxx 10xxxxxx 10xxxxxx 10xxxxxx`
In obenstehender Tabelle ist die in [RFC3629](http://tools.ietf.org/html/rfc3629) definierte Struktur der einzelnen Code-Units zusammen mit der jeweiligen Anzahl der Payload-Bits dargestellt.
Anhand der Tabelle können wir erkennen, dass die Rückwärtskompatibilität zu ASCII dadurch gewährleistet wird, dass alle Code-Points bis
@@ -38,7 +38,7 @@ einschließlich 127 im ersten Byte dargestellt werden können. Sobald in der ers
Zur Erkennung und Umformung der UTF-8 Code-Units verwenden wir in der _UTF8::CodepointIterator_-Klasse die folgenden, in stark typisierten Enums definierten, Bitmasken:
-~~~
+```cpp
enum class CodeUnitType : uint8_t {
CONTINUATION = 128, // 10000000
LEADING = 64, // 01000000
@@ -52,13 +52,12 @@ enum class CodePoint : uint8_t {
THREE = 15, // 00001111
FOUR = 7, // 00000111
};
-~~~
-{: .language-cpp}
+```
Bei tieferem Interesse lässt sich die Implementierung der UTF-8 Logik in der Quelldatei [codepoint_iterator.cc](https://github.com/KnairdA/CodepointIterator/blob/master/src/codepoint_iterator.cc) nachlesen.
Zusätzlich zu den in GoogleTest geschriebenen [Unit-Tests](https://github.com/KnairdA/CodepointIterator/blob/master/test.cc) sehen wir im folgenden noch ein einfaches Beispiel zur Verwendung des `UTF8::CodepointIterator` mit einem [Beispieltext](http://www.columbia.edu/~fdc/utf8/) in altnordischen Runen:
-~~~
+```cpp
std::string test(u8"ᛖᚴ ᚷᛖᛏ ᛖᛏᛁ ᚧ ᚷᛚᛖᚱ ᛘᚾ ᚦᛖᛋᛋ ᚨᚧ ᚡᛖ ᚱᚧᚨ ᛋᚨᚱ");
for ( UTF8::CodepointIterator iter(test.cbegin());
@@ -66,8 +65,7 @@ for ( UTF8::CodepointIterator iter(test.cbegin());
++iter ) {
std::wcout << static_cast<wchar_t>(*iter);
}
-~~~
-{: .language-cpp}
+```
Die Dereferenzierung einer Instanz des Iterators produziert den aktuellen Code-Point als _char32\_t_, da dieser Datentyp garantiert vier Byte lang ist. Die Ausgabe eines solchen UTF-32 enkodierten Code-Points ist mir allerdings leider nur nach dem Cast in _wchar\_t_ gelungen. Dieser wird trotzdem nicht als Dereferenzierungs-Typ verwendet, da die Länge nicht fest definiert ist, sondern abhängig von der jeweiligen C++ Implementierung unterschiedlich sein kann. Dies stellt jedoch kein größeres Problem dar, da der Iterator für die interne Betrachtung von Strings und nicht zur Konvertierung für die Ausgabe gedacht ist.
diff --git a/articles/2013-11-03_mapping_binary_structures_as_tuples_using_template_metaprogramming.md b/articles/2013-11-03_mapping_binary_structures_as_tuples_using_template_metaprogramming.md
index 5c82f05..e2b4784 100644
--- a/articles/2013-11-03_mapping_binary_structures_as_tuples_using_template_metaprogramming.md
+++ b/articles/2013-11-03_mapping_binary_structures_as_tuples_using_template_metaprogramming.md
@@ -17,7 +17,7 @@ differences in endianness and In-place modification of the structure fields.
To be able to easily work with structure definitions using template metaprogramming I am relying on the standard library's [_std::tuple_](http://en.cppreference.com/w/cpp/utility/tuple)
template.
-~~~
+```cpp
template<typename Tuple>
class BinaryMapping {
public:
@@ -42,8 +42,7 @@ class BinaryMapping {
Tuple tuple_;
};
-~~~
-{: .language-cpp}
+```
This implementation of a template class _BinaryMapping_ provides _get_ and _set_ template methods for accessing values in a given binary buffer using the mapping provided by a given
Tuple template argument. The most notable element of this class is the usage of the _decltype_ keyword which was introduced in C++11. This keyword makes it easier to declare types
@@ -55,7 +54,7 @@ as its return type is also dependent on the template arguments.
As you may have noticed the above template class is not complete as I have not included a implementation of the _TupleReader::read_ method which does the actual work of mapping the binary
buffer as a tuple. This mapping is achieved by the following recursive template methods:
-~~~
+```cpp
struct TupleReader {
template <typename Tuple, size_t Index = 0, off_t Offset = 0>
static inline typename std::enable_if<
@@ -77,8 +76,7 @@ struct TupleReader {
);
}
};
-~~~
-{: .language-cpp}
+```
Template metaprogramming in C++ offers a Turing-complete language which is fully executed during compilation. This means that any problem we may solve during the runtime of a _normal_ program
may also be solved during compilation using template metaprogramming techniques. This kind of programming is comparable to functional programming as we have to rely on recursion and pattern
@@ -106,7 +104,7 @@ is always available as a template argument.
The classes _TupleReader_ and _BinaryMapping_ are enough to map a binary structure as a _std::tuple_ instantiation like in the following example where I define a _TestRecord_ tuple containing
a pointer to _uint64\_t_ and _uint16\_t_ integers:
-~~~
+```cpp
typedef std::tuple<uint64_t*, uint16_t*> TestRecord;
uint8_t* buffer = reinterpret_cast<uint8_t*>(
@@ -120,8 +118,7 @@ mapping.set<1>(1337);
std::cout << mapping.get<0>() << std::endl;
std::cout << mapping.get<1>() << std::endl;
-~~~
-{: .language-cpp}
+```
## Endianness
@@ -129,7 +126,7 @@ As you may remember this does not take endianness into account as I defined as a
_BinaryMapping_ template class which worked, but led to problems as soon as I mixed calls to _get_ and _set_. The resulting problems could of course have been fixed but this would probably
have conflicted with In-place modifications of the buffer. Because of that I chose to implement endianness support in a separate set of templates.
-~~~
+```cpp
struct BigEndianSorter {
template <class Key>
static void write(uint8_t*, const Key&);
@@ -137,25 +134,23 @@ struct BigEndianSorter {
template <typename Key>
static Key read(uint8_t* buffer);
};
-~~~
-{: .language-cpp}
+```
To be able to work with different byte orderings I abstracted the basic operations down to _read_ and _write_ template methods contained in a _struct_ so I would be able to provide separate
implementations of these methods for each type of endianness. The following template specialization of the _write_ method which does an In-place reordering of a _uint64\_t_ should be enough
to understand the basic principle:
-~~~
+```cpp
template <>
void BigEndianSorter::write<uint64_t>(uint8_t* buffer, const uint64_t& number) {
*reinterpret_cast<uint64_t*>(buffer) = htobe64(number);
}
-~~~
-{: .language-cpp}
+```
As soon as I had the basic endianness conversion methods implemented in a manner which could be used to specialize other template classes I was able to build a generic implementation of a
serializer which respects the structure defined by a given _std::tuple_ instantiation:
-~~~
+```cpp
template <class ByteSorter>
struct Serializer {
template <typename Tuple, size_t Index = 0, off_t Offset = 0>
@@ -205,8 +200,7 @@ struct Serializer {
);
}
};
-~~~
-{: .language-cpp}
+```
It should be evident that the way both the _serialize_ and _deserialize_ template methods are implemented is very similar to the _TupleReader_ implementation. In fact the only difference
is that no actual _std::tuple_ instantiation instance is touched and instead of setting pointers to the buffer we are only reordering the bytes of each section of the buffer corresponding to
@@ -216,7 +210,7 @@ a tuple element. This results in a complete In-place conversion between differen
At last I am now able to do everything I planned in the beginning in a very compact way using the _Serializer_, _TupleReader_ and _BinaryMapping_ templates. In practice this now looks like this:
-~~~
+```cpp
typedef std::tuple<uint64_t*, uint16_t*> TestRecord;
uint8_t* buffer = reinterpret_cast<uint8_t*>(
@@ -245,8 +239,7 @@ std::cout << testMapping.get<1>() << std::endl;
std::free(buffer);
std::free(testBuffer);
-~~~
-{: .language-cpp}
+```
The above coding makes use of all features provided by the described templates by first setting two values using _BinaryMapping_ specialized on the _TestRecord_ tuple, serializing them using
_Serializer_ specialized on the _BigEndianSorter_, deserializing the buffer back to the host byte ordering and reading the values using another _BinaryMapping_.
diff --git a/articles/2013-12-21_musikalischer_jahresruekblick_2013.md b/articles/2013-12-21_musikalischer_jahresruekblick_2013.md
index 59f8afe..24a7286 100644
--- a/articles/2013-12-21_musikalischer_jahresruekblick_2013.md
+++ b/articles/2013-12-21_musikalischer_jahresruekblick_2013.md
@@ -12,7 +12,7 @@ auch unter diesem Namen als Album veröffentlicht wurde. Somit war für mich ab
lassen konnte. Und ich wurde nicht enttäuscht, das drei Stunden andauernde Konzert war fantastisch und bewegt sich für mich außerhalb jeder Skala, die man errichten könnte. Im Folgenden werde
ich deshalb einfach einen Ausschnitt des, auch auf DVD aufgenommenen, Konzertes für sich sprechen lassen:
-[![Epica Retrospect Unleashed](https://static.kummerlaender.eu/media/retrospect_unleashed.jpg){: .full}](https://www.youtube.com/watch?v=rxd6sxLxdys)
+[![Epica Retrospect Unleashed](https://static.kummerlaender.eu/media/retrospect_unleashed.jpg){.full}](https://www.youtube.com/watch?v=rxd6sxLxdys)
Neben Epica-eigenen Liedern, wie dem obigen Titel _Unleashed_ des 2009 erschienenen Albums _Design Your Universe_, spielte das Ensemble auch Cover von klassischen Stücken wie _Stabat Mater Dolorosa_ im Duett mit der aktuellen
Nightwish-Sängerin Floor Jansen, den _Imperial March_ des Starwars-Soundtracks sowie ein Medley der orchestralen Fassungen einiger Epica-Lieder. Das Orchester und der Chor waren also optimal
@@ -34,7 +34,7 @@ nachvollziehen. Werbung war nicht übermäßig und wenn dann hauptsächlich auf
Open-Air Veranstaltung so gut erlebt habe, Kritik üben.
Die diesjährige Band-Aufstellung des Festivals war aus meiner Sicht sehr gut, besonders zugesagt haben mir in zufälliger Reihenfolge Nightwish, Powerwolf, Sabaton, Trivium, das Lingua Mortis Orchestra und Alestorm. Als Ausschnitt hier Nightwish's _Ghost Love Score_:
-[![Nightwish Showtime, Storytime Ghost Love Score](https://static.kummerlaender.eu/media/nightwish_ghost_love_score.jpg){: .full}](https://www.youtube.com/watch?v=JYjIlHWBAVo)
+[![Nightwish Showtime, Storytime Ghost Love Score](https://static.kummerlaender.eu/media/nightwish_ghost_love_score.jpg){.full}](https://www.youtube.com/watch?v=JYjIlHWBAVo)
Neben Metal-Konzerten besuche ich auch gerne Konzerte der in meiner Gegend angesiedelten sinfonischen Blasorchester. Besonders hervorheben möchte ich dieses Jahr das in Kooperation mit einer eigens gegründeten Rock-Band durchgeführte Konzert der [Stadtmusik Stockach](http://www.musikverein-stockach.de/). Bei diesem im Oktober stattgefundenen mit [_Symphonic meets Rock_](http://www.wochenblatt.net/heute/nachrichten/article/wenn-die-grenzen-fallen.html) betitelten Konzert spielte die Stadtmusik meines Heimatortes u.a. das _Concerto for Group and Orchestra_ von Jon Lord.
diff --git a/articles/2014-01-05_disabling_methods_in_implicitly_instantiated_class_template_specializations_in_cpp.md b/articles/2014-01-05_disabling_methods_in_implicitly_instantiated_class_template_specializations_in_cpp.md
index 98740c9..61983f3 100644
--- a/articles/2014-01-05_disabling_methods_in_implicitly_instantiated_class_template_specializations_in_cpp.md
+++ b/articles/2014-01-05_disabling_methods_in_implicitly_instantiated_class_template_specializations_in_cpp.md
@@ -5,7 +5,7 @@ During my current undertaking of developing a [template based library](https://g
The specific scenario I am talking about is disabling the _serialize_ and _deserialize_ template methods in all specializations of the
_[Tuple](https://github.com/KnairdA/BinaryMapping/blob/master/src/tuple/tuple.h)_ class template whose _Endianess_ argument is not of the type _UndefinedEndian_. My first working implementation of this requirement looks as follows:
-~~~
+```cpp
template <
typename CustomOrder,
typename Helper = Endianess
@@ -16,8 +16,7 @@ inline typename std::enable_if<
>::type serialize() {
Serializer<InPlaceSorter<CustomOrder>>::serialize(this->tuple_);
}
-~~~
-{: .language-cpp}
+```
As we can see I am relying on the standard library's `std::enable_if` template to enable the method only if the _Helper_ template argument equals the type _UndefinedEndian_. One may wonder why I am supplying the `std::enable_if` template with the argument _Helper_ instead of directly specifying the class template argument _Endianess_. This was needed because of the following paragraph of the ISO C++ standard:
@@ -30,7 +29,7 @@ I defined a additional _Helper_ argument which defaults to the class template's
The code supplied above works as expected but has at least two flaws: There is an additonal template argument whose sole purpose is to work around the C++ standard to make _[SFINAE](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error)_ possible and the return type of the method is obfuscated by the use of the `std::enable_if` template.
Luckily it is not the only way of achieving our goal:
-~~~
+```cpp
template <
typename CustomOrder,
typename = typename std::enable_if<
@@ -41,8 +40,7 @@ template <
inline void serialize() {
Serializer<InPlaceSorter<CustomOrder>>::serialize(this->tuple_);
}
-~~~
-{: .language-cpp}
+```
In this second example implementation we are moving the `std::enable_if` template from the return type into a unnamed default template argument of the method. This unnamed default
template argument which was not possible prior to the C++11 standard reduces the purpose of the `std::enable_if` template to selectively disabling method specializations. Additionally
@@ -50,7 +48,7 @@ the return type can be straight forwardly declared and the _Helper_ template arg
But during my research concerning this problem I came up with one additional way of achieving our goal which one could argue is even better than the second example:
-~~~
+```cpp
template <typename CustomOrder>
inline void serialize() {
static_assert(
@@ -60,8 +58,7 @@ inline void serialize() {
Serializer<InPlaceSorter<CustomOrder>>::serialize(this->tuple_);
}
-~~~
-{: .language-cpp}
+```
This implementation of the _serialize_ method renounces any additonal template arguments and instead uses a declaration called `static_assert` which makes any specializations where
the statement `std::is_same<Endianess, UndefinedEndian>::value` resolves to false ill-formed. Additionally it also returns a helpful message to the compiler log during such a situation.
diff --git a/articles/2014-07-11_mapping_arrays_using_tuples_in_cpp11.md b/articles/2014-07-11_mapping_arrays_using_tuples_in_cpp11.md
index 6a98630..19bc030 100644
--- a/articles/2014-07-11_mapping_arrays_using_tuples_in_cpp11.md
+++ b/articles/2014-07-11_mapping_arrays_using_tuples_in_cpp11.md
@@ -2,11 +2,11 @@
During my proof-of-concept implementation of external functions enabling [XSLT based static site generation](https://github.com/KnairdA/InputXSLT) I came upon the problem of calling a template method specialized on the Nth type of a `std::tuple` specialization using the Nth element of a array-like type instance as input. This was needed to implement a generic template-based interface for implementing [Apache Xalan](http://xalan.apache.org/xalan-c/index.html) external functions. This article aims to explain the particular approach taken to solve this problem.
-While it is possible to unpack a `std::tuple` instance into individual predefined objects using `std::tie` the standard library offers no such helper template for unpacking an array into individual objects and calling appropriate casting methods defined by a `std::tuple` mapping type. Sadly exactly this functionality is needed so that we are able to call a `constructDocument` member method of a class derived from the [`FunctionBase`](https://github.com/KnairdA/InputXSLT/blob/master/src/function/base.h) external function interface template class using static polymorphism provided through the [curiously recurring template pattern](https://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern). This interface template accepts the desired external function arguments as variadic template types and aims to provide the required validation and conversion boilerplate implementation. While we could recursively generate a `std::tuple` specialization instance from an array-like type using a approach simmilar to the one detailed in my article on [mapping binary structures as tuples using template metaprogramming](/article/mapping_binary_structures_as_tuples_using_template_metaprogramming) this wouldn't solve the problem of passing on the resulting values as individual objects. This is why I had to take the new approach of directly calling a template method on individual array elements using a `std::tuple` specialization as a kind of blueprint and passing the result values of this method to the `constructDocument` method as separate arguments.
+While it is possible to unpack a `std::tuple` instance into individual predefined objects using `std::tie` the standard library offers no such helper template for unpacking an array into individual objects and calling appropriate casting methods defined by a `std::tuple` mapping type. Sadly exactly this functionality is needed so that we are able to call a `constructDocument` member method of a class derived from the [FunctionBase](https://github.com/KnairdA/InputXSLT/blob/master/src/function/base.h) external function interface template class using static polymorphism provided through the [curiously recurring template pattern](https://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern). This interface template accepts the desired external function arguments as variadic template types and aims to provide the required validation and conversion boilerplate implementation. While we could recursively generate a `std::tuple` specialization instance from an array-like type using a approach simmilar to the one detailed in my article on [mapping binary structures as tuples using template metaprogramming](/article/mapping_binary_structures_as_tuples_using_template_metaprogramming) this wouldn't solve the problem of passing on the resulting values as individual objects. This is why I had to take the new approach of directly calling a template method on individual array elements using a `std::tuple` specialization as a kind of blueprint and passing the result values of this method to the `constructDocument` method as separate arguments.
Extracting array elements obviously requires some way of defining the appropriate indexes and mapping the elements using a tuple blueprint additionally requires this way to be statically resolvable as one can not pass a dynamic index value to `std::tuple_element`. So the first step to fullfilling the defined requirements involved the implementation of a template based index or sequence type.
-~~~
+```cpp
template <std::size_t...>
struct Sequence {
typedef Sequence type;
@@ -24,14 +24,13 @@ struct IndexSequence {
Sequence<Current...>
>::type::type type;
};
-~~~
-{: .language-cpp}
+```
This is achieved by the [`IndexSequence`](https://github.com/KnairdA/InputXSLT/blob/49e2010b489ab6d5516a9abd896c67738e0dc1cc/src/support/type/sequence.h) template above by recursively specializing the `Sequence` template using static recursion controlled by the standard library's template metaprogramming utility template `std::conditional`. This means that e.g. the type `Sequence<0, 1, 2, 3>` can also be defined as `IndexSequence<4>::type`.
Now all that is required to accomplish the goal is instantiating the sequence type and passing it to a variadic member template as [follows](https://github.com/KnairdA/InputXSLT/blob/master/src/function/base.h):
-~~~
+```cpp
[...]
this->callConstructDocument(
parameters,
@@ -55,11 +54,10 @@ inline xalan::XalanDocument* callConstructDocument(
)
);
}
-~~~
-{: .language-cpp}
+```
As we can see a `IndexSequence` template specialization instance is passed to the variadic `callConstructDocument` method to expose the actual sequence values as `Index`. This method then resolves the `Index` parameter pack as both the array and `std::tuple` index inside the calls to the `valueGetter.get` template method which is called for every sequence element because of this. What this means is that we are now able to implement non-template `constructDocument` methods inside XSLT external function implementations such as [FunctionTransform](https://github.com/KnairdA/InputXSLT/blob/master/src/function/transform.h). The values passed to these methods are automatically extracted from the argument array and converted into their respective types as required.
While this article only provided a short overview of mapping arrays using tuples in C++11 one may view the full implementation on [Github](https://github.com/KnairdA/InputXSLT/blob/master/src/function/base.h) or [cgit](http://code.kummerlaender.eu/InputXSLT/tree/src/function/base.h).
-**Update:** The recently passed C++14 standard adds a [`std::integer_sequence`](http://en.cppreference.com/w/cpp/utility/integer_sequence) template to the standard library which covers the same use case as the custom `Sequence` and `IndexSequence` templates detailed in this article. `FunctionBase` was already [modified](https://github.com/KnairdA/InputXSLT/commit/b9d62d5ce1e3f92a8ab34239c6e4044ad57180df) accordingly as one should obviously rely on the standard's version of a integer sequence in the future.
+**Update:** The recently passed C++14 standard adds a [std::integer_sequence](http://en.cppreference.com/w/cpp/utility/integer_sequence) template to the standard library which covers the same use case as the custom `Sequence` and `IndexSequence` templates detailed in this article. `FunctionBase` was already [modified](https://github.com/KnairdA/InputXSLT/commit/b9d62d5ce1e3f92a8ab34239c6e4044ad57180df) accordingly as one should obviously rely on the standard's version of a integer sequence in the future.
diff --git a/articles/2014-10-30_expanding_xslt_using_xalan_and_cpp.md b/articles/2014-10-30_expanding_xslt_using_xalan_and_cpp.md
index b0a53c4..07c12de 100644
--- a/articles/2014-10-30_expanding_xslt_using_xalan_and_cpp.md
+++ b/articles/2014-10-30_expanding_xslt_using_xalan_and_cpp.md
@@ -14,7 +14,7 @@ As Xalan itself offers no easy way of creating node trees from scratch I had to
Because Xerces doesn't fully adhere to the principles of [RAII] I suggest wrapping [`xercesc::DOMDocument`] inside a `std::unique_ptr` specialized on a corresponding custom deleter as follows:
-~~~
+```cpp
class document_deleter {
friend std::unique_ptr<xercesc::DOMDocument, document_deleter>;
@@ -35,14 +35,13 @@ document_ptr document(
nullptr
)
);
-~~~
-{: .language-cpp}
+```
Notable in the example above is the usage of a special [`XercesStringGuard`] class template I implemented to simplify the conversion between `char` based strings and the custom `XMLCh` type used by Xerces. After one has constructed the desired document tree using the standard DOM manipulations provided by [`xercesc::DOMDocument`] the next step is the conversion of this Xerces specific document into a [`xalan::XalanDocument`] instance usable by Xalan.
As Xalan is based on Xerces it offers a class especially for this task called [`xalan::XercesDOMWrapperParsedSource`] that may be used as follows:
-~~~
+```cpp
xalan::XercesParserLiaison parser;
xalan::XercesDOMSupport domSupport(parser);
xalan::XercesDOMWrapperParsedSource parsedSource(
@@ -52,12 +51,11 @@ xalan::XercesDOMWrapperParsedSource parsedSource(
);
xalan::XalanDocument* const xalanDocument = parsedSource.getDocument();
-~~~
-{: .language-cpp}
+```
After one has converted the Xerces document into a Xalan document its parent nodes have to be included into a [`xalan::XPathExecutionContext::BorrowReturnMutableNodeRefList`] which then may finally be passed into `xalan::XObjectFactory::createNodeSet`.
-~~~
+```cpp
xalan::XPathExecutionContext::BorrowReturnMutableNodeRefList nodes(
executionContext
);
@@ -67,8 +65,7 @@ nodes->addNodes(
);
return executionContext.getXObjectFactory().createNodeSet(nodes);
-~~~
-{: .language-cpp}
+```
Note that while the listings above should be enough to get you started on implementing external functions which are able to return node trees, they do not contain the logic necessary to keep the [`xalan::XercesDOMWrapperParsedSource`] instance including its helper classes alive through the whole duration of processing a XSL transformation and do not showcase the additional method implementations required to satisfy the [`xalan::Function`] interface.
diff --git a/articles/2015-01-14_a_look_at_compile_time_computation_in_cpp.md b/articles/2015-01-14_a_look_at_compile_time_computation_in_cpp.md
index 18de33f..7a5ce3a 100644
--- a/articles/2015-01-14_a_look_at_compile_time_computation_in_cpp.md
+++ b/articles/2015-01-14_a_look_at_compile_time_computation_in_cpp.md
@@ -8,7 +8,7 @@ Besides C-style macros C++ templates present one additional language element tha
My first attempt at facilitating compile time computation is a _functional-style_ list library based on template metaprogramming: [ConstList]. This library handles lists in a fashion simmilar to how it is done in languages such as Scheme or Haskell, i.e. by providing functions such as `fold` and `map` which manipulate a basic list type based on _Cons_ expressions. As an example one may consider how [ConstList]'s [`map`] function is expressed in terms of [`foldr`]:
-~~~
+```cpp
template <
typename Cons,
typename Function
@@ -22,14 +22,13 @@ constexpr auto map(const Cons& cons, const Function& function) {
make()
);
}
-~~~
-{: .language-cpp}
+```
The [`foldr`] implementation is also quite straightforward and simply applies a given function to each pair of the _Cons_ structure using static recursion. Note that this approach of _lambda expression based_ template metaprogramming would have been much more verbose in C++11 as many list manipulators such as [`map`] and [`foldr`] make use of C++14's _generic lambda expressions_. While the [test cases] provide a set of - in my opinion - reasonably nice list transformations and queries they also present the core problem of the particular approach taken in [ConstList], as it is impossible to return lists of varying lengths depending on their contents. This pervasive limitation exists because the only way to vary types at compile time depending on values is to use these values as template parameters. That is the _Cons_ list type tree would have to be both list declaration and definition, analogously to e.g. [`std::integral_constant`]. Obviously this is quite different from how types and values were separated into templates and member constants in [ConstList]. One would have to think of types as values and templates as functions that modify those values instead.
Furthermore the compilation performance degrades noticeably when manipulating lists with more than a couple of dozen items or plainly fails to execute at compile time at all. What works in a reasonably consistent fashion are list manipulations such as this one, which evaluates down to a hard coded `1056` in GCC's Assembler output:
-~~~
+```cpp
#include "list.h"
int main(int, char**) {
@@ -48,8 +47,7 @@ int main(int, char**) {
0
);
}
-~~~
-{: .language-cpp}
+```
To summarize: The approach taken in my implementation of [ConstList] may be a nice exercise in template metaprogramming and writing _functional-style_ C++ code but its practical applications in compile time computation are unreasonably narrow.
@@ -57,7 +55,7 @@ To summarize: The approach taken in my implementation of [ConstList] may be a ni
As was already mentioned, prior to the C++11 standard the only way to perform compile time computations was to rely on macros and template metaprogramming. While both of those can be thought of as separate _functional-style_ languages inside C++, the `constexpr` keyword allows one to declare a normal function as _potentially executable_ at compile time. So contrary to template metaprogramming based solutions we don't have a strong guarantee that our _compile time program_ is actually evaluated at compile time and would have to look at the generated Assembler output when in doubt. Sadly this is actually not much more than what is possible in _normal_ C++ compiled by a _sufficiently smart compiler_, e.g. the listing below is evaluated at compile time by GCC without any usage of `constexpr` or template metaprogramming:
-~~~
+```cpp
int example(int x) {
return 2 * x;
}
@@ -75,17 +73,15 @@ int main(int, char**) {
recursive_example(21)
);
}
-~~~
-{: .language-cpp}
+```
Where the verbose Assembler output is acquired as follows (note that the same command also works for Clang):
-~~~
+```sh
> g++ -S -fverbose-asm -O2 example.cc -o example.asm
> grep example.asm -n -e 42
95: movl $42, %eax #,
-~~~
-{: .language-sh}
+```
One area where the example above would not work and one would thus require the `constexpr` keyword, is when one wants to use the result of a function as e.g. a template parameter or any other value that is required by the standard to be defined at compile time. While this is certainly useful it - contrary to what one could think after first hearing about `constexpr` - doesn't quite enable one to explicitly write _compile time programs_ in the same way as _normal_ programs.
diff --git a/articles/2015-03-06_using_scheme_as_a_metaphor_for_template_metaprogramming.md b/articles/2015-03-06_using_scheme_as_a_metaphor_for_template_metaprogramming.md
index 8bd8f79..e1c9769 100644
--- a/articles/2015-03-06_using_scheme_as_a_metaphor_for_template_metaprogramming.md
+++ b/articles/2015-03-06_using_scheme_as_a_metaphor_for_template_metaprogramming.md
@@ -5,7 +5,7 @@ Back in January I looked at compile time computation in C++ based on handling li
While [ConstList] turned out to be of limited use in actually performing compile time computations, its list manipulation and query functionality was already inspired by how lists are handled in _LISP_ respectively its more minimalistic dialect _Scheme_, especially by the functionality described in the latter's [SRFI-1].
When I started developing a new library porting this basic concept to the _type as value and templates as functions_ approach called [TypeAsValue] it quickly turned out that a _Scheme_ like paradigm maps quite well to template metaprogramming. This was initially very surprising as I did not expect that C++ templates would actually feel like a - admittedly rather verbose - functional programming language if used in a certain way.
-~~~
+```cpp
// (define sum
// (fold +
// 0
@@ -19,8 +19,7 @@ using sum = tav::Fold<
tav::Int<2>
>
>;
-~~~
-{:.language-cpp}
+```
As we can see compile time computations expressed using this approach are more or less direct mappings of their _Scheme_ equivalent if we overlook the need to explicitly declare types, the different syntax used for defining bindings as well as its immutability.
@@ -30,18 +29,17 @@ While [TypeAsValue] started out as a direct reimplementation of my previous atte
The desire to express values in terms of types restricts the set of usable types to _integral types_ as only those types may be used as template parameters. According to the standard[^0] this includes all _integer types_ i.e. all non-floating-point types such as `bool`, `char` and `int`. In case of [TypeAsValue] all values are expressed as specializations of [`std::integral_constant`] wrapped in template aliases to simplify their declaration.
-~~~
+```cpp
using answer = tav::Int<42>; // std::integral_constant<int, 42>
using letter = tav::Char<'A'>; // std::integral_constant<char, 'A'>
using truth = tav::Boolean<true>; // std::integral_constant<bool, true>
-~~~
-{:.language-cpp}
+```
This need to explicitly declare all types because deduction during template resolution is not feasible marks one of the instances where the _Scheme metaphor_ does not hold true. Luckily this is not a bad thing as the goal is after all not to develop a exact replica of _Scheme_ in terms of template metaprogramming but to enable compile time computations in a _Scheme like_ fashion. In this context not disregarding the C++ type system is an advantage, especially since it should be possible to enable type deduction where required using a [`tav::Any`] like [`std::integral_constant`] constructor.
Obviously expressing single values as types is not enough, we also require at least an equivalent for _Scheme_'s fundamental pair type, on top of which more complex structures such as lists and trees may be built.
-~~~
+```cpp
template <
typename CAR,
typename CDR
@@ -52,8 +50,7 @@ struct Pair : detail::pair_tag {
typedef Pair<CAR, CDR> type;
};
-~~~
-{:.language-cpp}
+```
As we can see expressing a pair type in terms of a type template is very straight forward. Note that the recursive `type` definition will be discussed further in the next section on _templates as functions_. Each [`tav::Pair`] specialization derives from `detail::pair_tag` to simplify verification of values as pairs in `tav::IsPair`. The naming of the parameters as `CAR` and `CDR` is a reference to pair types being constructed using [`tav::Cons`] analogously to _Scheme_, where the pair `(1 . 2)` may be constructed using `(cons 1 2)`.
@@ -61,7 +58,7 @@ To summarize the type concept employed in [TypeAsValue] we can say that all actu
## Templates as functions
-~~~
+```cpp
template <
typename X,
typename Y
@@ -70,12 +67,11 @@ using Multiply = std::integral_constant<
decltype(X::value * Y::value),
X::value * Y::value
>;
-~~~
-{:.language-cpp}
+```
As we can see basic functionality such as a function respectively template to multiply a number by another is easily implemented in terms of an alias for a value type specialization, including automatic result type deduction using `decltype`. This also applies to higher order functionality which can be expressed only using other templates provided by the library such as the [`tav::Every`] list query.
-~~~
+```cpp
// (define (every predicate list)
// (fold (lambda (x y) (and x y))
// #t
@@ -89,14 +85,13 @@ using Every = Fold<
Boolean<true>,
Map<Predicate, List>
>;
-~~~
-{:.language-cpp}
+```
If we ignore the need to explicitly declare the predicate as a _template template parameter_ i.e. as a function this example is very simmilar to its _Scheme_ equivalent. Concerning the function used to fold the list it is actually less verbose than the _Scheme_ version of [`tav::Every`] as we can directly pass [`tav::And`] instead of wrapping it in a lambda expression as is required in _Scheme_ [^1].
Sadly the actual implementations of e.g. [`tav::Fold`] are not as easily expressed. The recursive nature of folding a list or even constructing its underlying pair based structure using the variadic [`tav::List`] requires partial template specializations which are not allowed for template aliases[^2].
-~~~
+```cpp
template <
template<typename, typename> class Function,
typename Initial,
@@ -116,20 +111,18 @@ template <
struct fold_pair<Function, Initial, void> {
typedef Initial type;
};
-~~~
-{:.language-cpp}
+```
While the listing of `tav::detail::fold_pair` shows how the partial specialization of its [`tav::Pair`] parameter allows recursion until the list ends[^3], it also forces us to define its actual type in terms of a public `type` member `typedef`. Such a member type definition can lead to cluttering the code with `typename` keywords which is why [TypeAsValue] employs a simple [`tav::Eval`] template alias to hide all `typename *::type` constructs.
-~~~
+```cpp
template <
template<typename, typename> class Function,
typename Initial,
typename List
>
using Fold = Eval<detail::fold_pair<Function, Initial, List>>;
-~~~
-{:.language-cpp}
+```
Hiding member type defintions behind template aliases enables most _higher_ functionality and applications built using its functions to be written in a reasonably minimalistic - _Scheme_ like - fashion as we can see in e.g. the listing of [`tav::Every`]. This also explains why [`tav::Pair`] recursively defines its own type, as we would otherwise have to be quite careful where to resolve it.
@@ -137,7 +130,7 @@ Hiding member type defintions behind template aliases enables most _higher_ func
Not all programs are sensibly expressed as a nested chain of function calls if we want to reuse some values, separate functionality into appropriately named functions or hide complexity via private bindings. While in _Scheme_ one would use `let` and the like for this purpose, such functionality is not easily replicated in the context of template metaprogramming. This is why [TypeAsValue] uses an alternate and more _C++ like_ solution to this problem by simply making use of the standard object oriented aspects of the language.
-~~~
+```cpp
// (define (quick_sort comparator sequence)
// (if (null-list? sequence)
// (list)
@@ -179,8 +172,7 @@ template <template<typename, typename> class Comparator>
struct quick_sort<Comparator, void> {
typedef void type;
};
-~~~
-{:.language-cpp}
+```
Above we can see the complete listing of the _Quick Sort_ implementation employed by the [`tav::Sort`] template alias. At first glance this looks rather different from the corresponding _Scheme_ program but if we look closer one could argue that it is a equivalent of a `let` binding where the _private_ section of `tav::detail::quick_sort` contains the bound constants and the _public_ section contains the body.
@@ -190,7 +182,7 @@ While partial application of the `comparator` function in the _Scheme_ _Quick So
To put it simply [`tav::Apply`] implements a [`std::bind`] analog for usage in a template metaprogramming context. This means that it _returns_ a new template for a given template including all its arguments where some or all of those arguments may be placeholders. In this context a placeholder is a specialization of the [`tav::detail::placeholder`] template on an arbitrary integer value that represents the index of the argument to the _returned_ template the placeholder should resolve to.
-~~~
+```cpp
// (define result
// (map (lambda (x) (+ 2 x))
// (list 1 2 3)))
@@ -199,8 +191,7 @@ using result = tav::Map<
tav::Apply<tav::Add, tav::Int<2>, tav::_0>::template function,
tav::List<tav::Int<1>, tav::Int<2>, tav::Int<3>>
>;
-~~~
-{:.language-cpp}
+```
Note that `tav::_0` is just an alias to `tav::detail::placeholder<0>`. The [`tav::Apply`] template automatically selects a matching implementation as its base class depending on the count of placeholder arguments using [`tav::Cond`]. If there are more than two placeholder arguments it _returns_ a generic variadic template as its `function` alias whereas there is a explicit version for one, two or zero placeholders. The zero placeholder variant of [`tav::Apply`] is useful if function application has to be deferred as is required for e.g. the handling of invalid values.
@@ -216,7 +207,7 @@ Both of these examples are certainly not what [TypeAsValue] might be used for in
## Summary
-While the _Scheme_ metaphor for template metaprogramming in C++ certainly has its limits, especially in the area of anonymous functions, I think that this article as well as the actual implementation of [TypeAsValue] are proof that it holds up quite well in many circumstances. As stated in the introduction to this article I was very surprised how close template metaprogramming can feel to a _real_ functional programming language.
+While the _Scheme_ metaphor for template metaprogramming in C++ certainly has its limits, especially in the area of anonymous functions, I think that this article as well as the actual implementation of [TypeAsValue] are proof that it holds up quite well in many circumstances. As stated in the introduction to this article I was very surprised how close template metaprogramming can feel to a _real_ functional programming language.
All listings in this article as well as the [TypeAsValue] library itself are freely available under the terms of the MIT license on [Github] and [cgit]. Feel free to check them out and contribute - I am especially interested in practical solutions to providing better partial function application support or even full compile time lambda expressions that do not require the whole library to be designed around this concept.
diff --git a/articles/2015-09-18_nokia_heir_and_hardware_keyboards.md b/articles/2015-09-18_nokia_heir_and_hardware_keyboards.md
index 93e77bd..6f318c7 100644
--- a/articles/2015-09-18_nokia_heir_and_hardware_keyboards.md
+++ b/articles/2015-09-18_nokia_heir_and_hardware_keyboards.md
@@ -13,7 +13,7 @@ But sadly this does not change the reality that at least my other half keyboard
![Jolla with TOHKBDv2](https://static.kummerlaender.eu/media/jolla.png)
-Of course the _Jolla_ has its strengths: _SailfishOS_ is a pleasure to use[^0] and the faster internals are essential to using it without having to wait on the device every other interaction. Also the replacement of _GTK_ with _Qt's QML_ as the primary _UI_ framework was definitly the right step and being able to execute _Android_ applications is useful for when there is no _SailfishOS_ counterpart.
+Of course the _Jolla_ has its strengths: _SailfishOS_ is a pleasure to use[^0] and the faster internals are essential to using it without having to wait on the device every other interaction. Also the replacement of _GTK_ with _Qt's QML_ as the primary _UI_ framework was definitely the right step and being able to execute _Android_ applications is useful for when there is no _SailfishOS_ counterpart.
But while slow the _N900_ is superior in other situations such as direct sunlight and precision usage using a stylus. The transreflective background of the display means that one can turn off the backlight completly if the sun is shining bright enough and use it as a source of light whereas the _Jolla_ display is often not readable in bright sunlight.
While _SailfishOS_ is more fluid and looks nice, _Hildon_ with all transitions turned off feels quick in a way that an animated UI simply does not. Add to that the various unlock methods such as sliding out the keyboard, sliding back the camera protector or sliding the unlock button and the daily usage of the _N900_ feels more intutive and quicker than any touch based interface I've tried. This problem is increased by the recent _SailfishOS_ UI overhaul that replaces gestures with buttons in various parts of the interface. Many of the nice properties of _Jolla's_ interface such as sliding from the top of the display to lock and sliding up to access the application menu from the lockscreen now have to be patched back into the UI using custom repositories. Admittedly it is great that this is even possible without requiring deep changes to the system such as _jailbreaks_ as in other mobile systems. Furthermore with the right set of patches from the _Warehouse_ it is possible to e.g. enable nearly system wide landscape mode support which is very nice.
diff --git a/articles/2015-09-24_the_joys_of_ipv6.md b/articles/2015-09-24_the_joys_of_ipv6.md
index eb7c8ee..c913723 100644
--- a/articles/2015-09-24_the_joys_of_ipv6.md
+++ b/articles/2015-09-24_the_joys_of_ipv6.md
@@ -16,14 +16,16 @@ This brings me to the main point of this article: _IPv6_ instantly enables all m
## The vision
- 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
- link/ether 00:50:##:##:##:## brd ff:ff:ff:ff:ff:ff
- inet 192.168.178.2/24 brd 192.168.178.255 scope global eth0
- valid_lft forever preferred_lft forever
- inet6 2a02:8071:####:####:###:####:####:####/64 scope global mngtmpaddr dynamic
- valid_lft 604799sec preferred_lft 302399sec
- inet6 fe80::250:43ff:fe01:6d36/64 scope link
- valid_lft forever preferred_lft forever
+```
+2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
+ link/ether 00:50:##:##:##:## brd ff:ff:ff:ff:ff:ff
+ inet 192.168.178.2/24 brd 192.168.178.255 scope global eth0
+ valid_lft forever preferred_lft forever
+ inet6 2a02:8071:####:####:###:####:####:####/64 scope global mngtmpaddr dynamic
+ valid_lft 604799sec preferred_lft 302399sec
+ inet6 fe80::250:43ff:fe01:6d36/64 scope link
+ valid_lft forever preferred_lft forever
+```
As we can see my examplary device connected to my new provider's router not only gets the normal _IPv4_ and _IPv6_ subnet addresses but also a `scope global` _IPv6_ address which is accessible from any _IPv6_ enabled host on the Internet using e.g. `ping6`.
@@ -37,34 +39,38 @@ The only challenge standing in the way of actually being able to do all the nice
While I already had various _OpenVPN_ instances set up on both my virtual server hosting this website as well as the _SheevaPlug_, neither of them were _IPv6_ enabled. This required some trickery to change - especially in combination with my chosen _iptable_ manager _[UFW]_ and some _systemd_ details previously unknown to me.
- proto udp
- proto udp6
-
- dev tun
- tun-ipv6
-
- # [...] certificates
-
- server 10.8.0.0 255.255.255.0
- server-ipv6 2a01:4f8:c17:77a:4000::/66
-
- # [...] further unrelated settings
-
- push "redirect-gateway def1"
- push "redirect-gateway-ipv6 def1"
- push "route-ipv6 ::/0 fe80::1 100"
+```
+proto udp
+proto udp6
+
+dev tun
+tun-ipv6
+
+# [...] certificates
+
+server 10.8.0.0 255.255.255.0
+server-ipv6 2a01:4f8:c17:77a:4000::/66
+
+# [...] further unrelated settings
+
+push "redirect-gateway def1"
+push "redirect-gateway-ipv6 def1"
+push "route-ipv6 ::/0 fe80::1 100"
+```
These are the relevant sections of the server configuration of my _IPv6_ proxy VPN. The `proto udp6` flag enables access to the VPN via _IPv6_. `tun-ipv6` enables _IPv6_ support on the _TUN_ interface created by _OpenVPN_ while the `server-ipv6` statement declares the global _IPv6_ subnet designated for clients of the VPN[^3]. Finally the `push` directives tell the clients that they should route all their _IPv6_ traffic through the VPN.
To make this configuration work one also has to add the following statements to the head of `/etc/ufw/before.rules`[^4]:
- # nat Table rules
- *nat
- :POSTROUTING ACCEPT [0:0]
+```
+# nat Table rules
+*nat
+:POSTROUTING ACCEPT [0:0]
- # Allow traffic from clients to ens3
- -F
- -A POSTROUTING -s 10.8.0.0/24 -o ens3 -j MASQUERADE
+# Allow traffic from clients to ens3
+-F
+-A POSTROUTING -s 10.8.0.0/24 -o ens3 -j MASQUERADE
+```
Additionally the `net.ipv6.conf.all.forwarding` parameter has to be set to `1` using e.g. `sysctl`. If you also use _systemd-networkd_ as your network manager, make sure that the parameter `IPv6Forward` is set to `yes` for your external interface.
Note that these are all the settings I changed while playing around in order to make the VPN work - it very well may be that not all of them are strictly required.
diff --git a/articles/2016-02-21_notes_on_function_interposition_in_cpp.md b/articles/2016-02-21_notes_on_function_interposition_in_cpp.md
index 27fb967..123af85 100644
--- a/articles/2016-02-21_notes_on_function_interposition_in_cpp.md
+++ b/articles/2016-02-21_notes_on_function_interposition_in_cpp.md
@@ -6,7 +6,7 @@ To counterbalance the vastly increased amount of time I am spending on purely th
Most if not all of the applications and services one commonly uses are not monolithic executables that one could execute on the _bare metal_ but depend on a number of separate libraries that provide useful abstractions the actual application is built upon. As most application share a common set of library dependencies it would be quite wasteful to package each application with its own separate copy of a given library. This is why most libraries are commonly _linked dynamically_ which means that e.g. a call to _random library function_ `f` is not resolved during compilation by replacing it with the library provided source code or a fixed reference to the implementation of `f` but resolved respectively linked at runtime. For Linux applications this dynamic resolution is commonly performed by _the dynamic linker_ `ld.so`.
-Instance specific configuration of this library is possible via a set of environment variables. One of these variables is `LD_PRELOAD` which enables us to provide "[...] a list of additional, user-specified, ELF shared objects to be loaded before all others [that] can be used to selectively override functions in other shared objects." (`ld.so` manpage, section on `LD_PRELOAD`).
+Instance specific configuration of this library is possible via a set of environment variables. One of these variables is `LD_PRELOAD` which enables us to provide "[...] a list of additional, user-specified, ELF shared objects to be loaded before all others that can be used to selectively override functions in other shared objects." (`ld.so` manpage, section on `LD_PRELOAD`).
This feature is what is commonly referred to as function interposition and is what will be discussed in the following sections. Other options for intercepting function calls such as `ptrace` are not covered by this particular article.
@@ -26,13 +26,15 @@ Note that this only applies if we want to specifically interpose C functions fro
To check if the symbols are exported correctly we can use `nm` which ĺists the symbols in ELF object files.
- > nm libChangeLog.so | grep "open\|write"
- 000000000009e866 T open
- 000000000009e99b T write
- 000000000009ea5d T writev
- 000000000009f61a W _Z11track_writei
- 000000000009f6ec W _Z11track_writeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
- [...]
+```sh
+> nm libChangeLog.so | grep "open\|write"
+000000000009e866 T open
+000000000009e99b T write
+000000000009ea5d T writev
+000000000009f61a W _Z11track_writei
+000000000009f6ec W _Z11track_writeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
+[...]
+```
As we can see interposing this library would lead to the application calling the library's `open`, `write` and `writev` functions instead of the standard C library's. Note that the C++ source additionally needs to be compiled as position-independent code to be usable as a shared library at all. If one uses _clang_ or _g++_ this is easily achieved by adding the `-fPIC` option.
@@ -42,10 +44,9 @@ As we can see interposing this library would lead to the application calling the
Although we can now replace functions in a target application with our own logic the goal remains to merely interpose a function which means that we have to call the actual function at some point. The dynamic linker library offers a function to acquire the address of the next symbol with a given name in the resolution stack in the form of `dlsym`. This function is defined in the `dlfcn.h` header and requires the interposed library to be linked to `ld.so`.
-~~~
+```c
void* dlsym(void* handle, const char* symbol);
-~~~
-{:.language-c}
+```
While `handle` can be used to restrict the resolution to a specific shared library we pass a special pseudo-handle `RTLD_NEXT` which instructs the function to return the address of the next symbol whose name equals the null-terminated `symbol` parameter.
@@ -53,17 +54,16 @@ Note that `RTLD_NEXT` is only defined by `dlfcn.h` if `_GNU_SOURCE` is defined d
If we were working in C we could directly assign the returned pointer of type `void*` to a function pointer of the function's signature. However this sort of cast is not allowed in C++ which is why we need to manually copy the address of the symbol into a function pointer. This may be achieved using `std::memcpy`.
-~~~
+```cpp
const void* symbol_address{ dlsym(RTLD_NEXT, "write") };
ssize_t (actual_function*)(int, const void*, size_t){};
std::memcpy(&actual_function, &symbol_address, sizeof(symbol_address));
-~~~
-{:.language-cpp}
+```
To prevent `dlsym` from being unneccessarily called more than once for a given symbol name one probably wants to persist the function pointer to e.g. a static variable local to the function body.
-~~~
+```cpp
static ssize_t (actual_function*)(int, const void*, size_t){};
if ( !actual_function ) {
@@ -71,8 +71,7 @@ if ( !actual_function ) {
std::memcpy(&actual_function, &symbol_address, sizeof(symbol_address));
}
-~~~
-{:.language-cpp}
+```
This logic should be placed in the function body and not for instance in a global initialization function as it is not guaranteed that such a function will be executed prior to any calls to interposed functions. The next section will describe an approach to reduce unneccessary code duplication in this context.
@@ -80,15 +79,14 @@ This logic should be placed in the function body and not for instance in a globa
The most straight forward approach to abstracting the usage of `dlsym` is to wrap it in a more C++-like function template. To prevent unneccessary duplication of the functions return and parameter types as well as to hide the _strange_ syntax of function pointer declaration we first define a template alias as follows:
-~~~
+```cpp
template <class Result, typename... Arguments>
using ptr = Result(*)(Arguments...);
-~~~
-{:.language-cpp}
+```
This allows us to define function pointers in a fashion simmilar to `std::function` and can be used as the template parameter of our actual `dlsym` abstraction.
-~~~
+```cpp
template <typename FunctionPtr>
FunctionPtr get_ptr(const std::string& symbol_name) {
const void* symbol_address{ dlsym(RTLD_NEXT, symbol_name.c_str()) };
@@ -98,12 +96,11 @@ FunctionPtr get_ptr(const std::string& symbol_name) {
return actual_function;
}
-~~~
-{:.language-cpp}
+```
This extraction of all `dlsym` calls into a single function template will come in handy during the section on _problems in practice_. Furthermore it allows us to write the exemplary interposition of the `write` library function in the following way which I for one find to be more maintainable and overall nicer looking than its c-style equivalent.
-~~~
+```cpp
ssize_t write(int fd, const void* buffer, size_t count) {
static actual::ptr<ssize_t, int, const void*, size_t> actual_write{};
@@ -115,8 +112,7 @@ ssize_t write(int fd, const void* buffer, size_t count) {
return actual_write(fd, buffer, count);
}
-~~~
-{:.language-cpp}
+```
## Problems in practice
diff --git a/articles/2016-05-22_visualisierung_von_metriken_in_voronoi_diagrammen.md b/articles/2016-05-22_visualisierung_von_metriken_in_voronoi_diagrammen.md
index 2b05dc9..accb083 100644
--- a/articles/2016-05-22_visualisierung_von_metriken_in_voronoi_diagrammen.md
+++ b/articles/2016-05-22_visualisierung_von_metriken_in_voronoi_diagrammen.md
@@ -4,16 +4,18 @@ In der Analysis 2 Vorlesung meines Mathematik Studiums beschäftigen wir uns der
## Normen und Metriken in endlichdimensionalen Vektorräumen
-In der herkömmlichen Schulmathematik sowie alltäglichen Rechnungen definieren wir Begriffe wie die Größe einer Zahl und den Abstand zwischen zwei Zahlen implizit über deren Betrag beziehungsweise die Differenz $$\vert a-b \vert$$ mit $$a, b \in \mathbb{R}$$ [^1]. Diese implizite, ja _intuitive_ Definition der genannten Begriffe reicht für vieles aus, gelangt aber schnell an ihre Grenzen, wenn wir das Ganze, im Rahmen der mathematischen Arbeit des Beweisens, auf formale Grundlagen stellen und als Fundament für Aussagen in anderen Mengen als den herkömmlichen Zahlen nutzen wollen.
+In der herkömmlichen Schulmathematik sowie alltäglichen Rechnungen definieren wir Begriffe wie die Größe einer Zahl und den Abstand zwischen zwei Zahlen implizit über deren Betrag beziehungsweise die Differenz $\vert a-b \vert$ mit $a, b \in \mathbb{R}$ [^1]. Diese implizite, ja _intuitive_ Definition der genannten Begriffe reicht für vieles aus, gelangt aber schnell an ihre Grenzen, wenn wir das Ganze, im Rahmen der mathematischen Arbeit des Beweisens, auf formale Grundlagen stellen und als Fundament für Aussagen in anderen Mengen als den herkömmlichen Zahlen nutzen wollen.
-Mit nicht herkömmlichen Zahlen meine ich dabei Elemente aus Vektorräumen[^2] wie $$\mathbb{R}^2$$. Zumindest für diesen, mittels eines Kartesischen Koordinatensystems als zweidimensionale Ebene darstellbaren, Vektorraum, haben wir in der Schule eine Vorstellung bekommen. Dies trifft sich gut, da sich auch die Visualisierung von Metriken mittels Voronoi-Diagrammen in diesem Raum abspielen wird.
+Mit nicht herkömmlichen Zahlen meine ich dabei Elemente aus Vektorräumen[^2] wie $\mathbb{R}^2$. Zumindest für diesen, mittels eines Kartesischen Koordinatensystems als zweidimensionale Ebene darstellbaren, Vektorraum, haben wir in der Schule eine Vorstellung bekommen. Dies trifft sich gut, da sich auch die Visualisierung von Metriken mittels Voronoi-Diagrammen in diesem Raum abspielen wird.
-Betrachten wir zunächst den Begriff der Größe oder auch des Betrags einer Zahl. Dieser wird für Elemente eines Vektorraums, also Vektoren, über Normen beschrieben. Eine Norm ist dabei formal eine Abbildung $$\| \cdot \| : V \rightarrow \mathbb{R}_{\geq0}$$, also eine Funktion, die Elementen aus einem $$\mathbb{K}$$-Vektorraum $$V$$[^3] einen reellen Wert größer oder gleich Null zuordnet.
-Diese Funktion darf dabei nicht vollkommen beliebig definiert sein, sondern muss für $$x, y \in V$$ sowie $$\alpha \in \mathbb{K}$$ die folgenden Bedingungen erfüllen:
+Betrachten wir zunächst den Begriff der Größe oder auch des Betrags einer Zahl. Dieser wird für Elemente eines Vektorraums, also Vektoren, über Normen beschrieben. Eine Norm ist dabei formal eine Abbildung $\| \cdot \| : V \rightarrow \mathbb{R}_{\geq0}$, also eine Funktion, die Elementen aus einem $\mathbb{K}$-Vektorraum $V$[^3] einen reellen Wert größer oder gleich Null zuordnet.
+Diese Funktion darf dabei nicht vollkommen beliebig definiert sein, sondern muss für $x, y \in V$ sowie $\alpha \in \mathbb{K}$ die folgenden Bedingungen erfüllen:
-|Definitheit |$$\|x\|=0 \Leftrightarrow x=0$$ |
-|Homogenität |$$\|\alpha * x\|=\alpha * \|x\|$$|
-|Dreiecksungleichung|$$\|x+y\| \leq \|x\| + \|y\|$$ |
+------------------- -------------------------------
+Definitheit $\|x\|=0 \Leftrightarrow x=0$
+Homogenität $\|\alpha * x\|=\alpha * \|x\|$
+Dreiecksungleichung $\|x+y\| \leq \|x\| + \|y\|$
+------------------- -------------------------------
Diese Anforderungen bedeuten, dass eine Funktion genau dann als Norm gesehen werden kann, wenn sie nur den Nullvektor auf die reelle Null abbildet, Skalare analog zu linearen Ausrücken _herausgezogen_ werden können und ein Umweg zwischen zwei Punkten nie kürzer ist, als der direkte Verbindungsweg.
@@ -21,48 +23,50 @@ Betrachten wir an dieser Stelle die Defintion der häufig verwendeten Klasse der
$$\|x\|_p := \left(\displaystyle\sum_{i=1}^{n} \vert x_i \vert ^p\right)^\frac{1}{p} \; \text{mit} \; x \in \mathbb{R}^n ,\; p \in \mathbb{R_{\geq1}}$$
-Beachtenswerter Weise geht aus dieser Norm für $$p=1$$ die Betragsnorm, also die Aufsummierung aller Komponentenbeträge des gegebenen Vektors, sowie für $$p=2$$ die sogenannte Euklidische Norm hervor. Durch Verschieben von $$p$$ im Intervall $$[1, \infty]$$ lässt sich dabei die charakteristische Rautenform der Einheitskugel[^4] der Betragsnorm über die tatsächlich kugelförmige Einheitskugel der Euklidischen Norm in die quadratische Form der Maximumsnorm überführen ($$p \rightarrow \infty$$).
+Beachtenswerter Weise geht aus dieser Norm für $p=1$ die Betragsnorm, also die Aufsummierung aller Komponentenbeträge des gegebenen Vektors, sowie für $p=2$ die sogenannte Euklidische Norm hervor. Durch Verschieben von $p$ im Intervall $[1, \infty]$ lässt sich dabei die charakteristische Rautenform der Einheitskugel[^4] der Betragsnorm über die tatsächlich kugelförmige Einheitskugel der Euklidischen Norm in die quadratische Form der Maximumsnorm überführen ($p \rightarrow \infty$).
![Veränderung der abgeschlossenen Einheitskugel unter der p-Norm für p zwischen 1 und 3](https://static.kummerlaender.eu/media/unit_circle_cycle.gif)
-Kommen wir nun zum Begriff des Abstands zwischen zwei Zahlen, welcher in Form von Metriken auf algebraische Strukturen wie Vektorräume übertragen wird. Wie in der Einführung dieses Abschnits beschrieben, haben wir den Abstand zwischen Zahlen schon in der Schule über den Betrag der Differenz beschrieben. Wir kennen an dieser Stelle in Form des Satz des Pythagoras auch schon eine sinnvolle Definition für den Abstand zwischen Punkten in $$\mathbb{R}^2$$:
+Kommen wir nun zum Begriff des Abstands zwischen zwei Zahlen, welcher in Form von Metriken auf algebraische Strukturen wie Vektorräume übertragen wird. Wie in der Einführung dieses Abschnits beschrieben, haben wir den Abstand zwischen Zahlen schon in der Schule über den Betrag der Differenz beschrieben. Wir kennen an dieser Stelle in Form des Satz des Pythagoras auch schon eine sinnvolle Definition für den Abstand zwischen Punkten in $\mathbb{R}^2$:
$$d(x,y) := \sqrt{\vert x_1-x_2 \vert ^2 - \vert y_1-y_2 \vert ^2} \; \text{mit} \; x, y \in \mathbb{R}^2$$
-Diese Metrik über dem zweidimensionalen reellen Vektorraum lässt sich, auf folgende naheliegende Art und Weise, in eine Metrik für alle endlich dimensionalen $$\mathbb{R}$$-Vektorräume erweitern:
+Diese Metrik über dem zweidimensionalen reellen Vektorraum lässt sich, auf folgende naheliegende Art und Weise, in eine Metrik für alle endlich dimensionalen $\mathbb{R}$-Vektorräume erweitern:
$$d(x,y) := \sqrt{\displaystyle\sum_{i=1}^{n} \vert x_i - y_i \vert ^2} \; \text{mit} \; x, y \in \mathbb{R}^n$$
Diese Metrik auf Grundlage des Satz des Pythagoras wird als Euklidische Metrik bezeichnet. Sie ist eine der Metriken, welche wir im weiteren Verlauf dieses Artikels in Voronoi-Diagrammen visualisieren werden.
-Die Definition solcher Metriken als Abbildungen der Form $$d(x,y) : V \times V \rightarrow \mathbb{R}_{\geq0}$$ beinhaltet eine Menge von Axiomen, welche von der Metrik-Abbildung erfüllt sein müssen.
+Die Definition solcher Metriken als Abbildungen der Form $d(x,y) : V \times V \rightarrow \mathbb{R}_{\geq0}$ beinhaltet eine Menge von Axiomen, welche von der Metrik-Abbildung erfüllt sein müssen.
-|Positive Definitheit|$$d(x,y) \geq 0 \land d(x,y)=0 \Leftrightarrow x=y$$|
-|Symmetrie |$$d(x,y) = d(y,x)$$|
-|Dreiecksungleichung |$$d(x,z) \leq d(x,y) + d(y,z)$$|
+-------------------- --------------------------------------------------
+Positive Definitheit $d(x,y) \geq 0 \land d(x,y)=0 \Leftrightarrow x=y$
+Symmetrie $d(x,y) = d(y,x)$
+Dreiecksungleichung $d(x,z) \leq d(x,y) + d(y,z)$
+-------------------- --------------------------------------------------
Wir fordern also, dass der Abstand zwischen beliebigen Punkten immer größer gleich Null sein muss, ein Nullabstand äquivalent zur Gleichheit der Punkte ist, die Reihenfolge der Punkte für den Abstand irrelevant ist und das der direkte Abstand zwischen zwei Punkten kleiner gleich einem Umweg über weitere Punkte ist.
-Bei der Betrachtung der Definitionen von p-Norm und Euklidischer Metrik fällt auf, dass diese sich zu ähneln scheinen. Dies ist kein Zufall, denn Metriken können aus Normen _induziert_ werden. So folgt die Euklidische Metrik mit $$d(x,y) := \|x-y\|_2$$ direkt aus der 2-Norm.
+Bei der Betrachtung der Definitionen von p-Norm und Euklidischer Metrik fällt auf, dass diese sich zu ähneln scheinen. Dies ist kein Zufall, denn Metriken können aus Normen _induziert_ werden. So folgt die Euklidische Metrik mit $d(x,y) := \|x-y\|_2$ direkt aus der 2-Norm.
-Es liegt also Nahe, dass auch aus die Betragsnorm mit $$p=1$$ eine Metrik induziert - die sogenannte Mannheimer-Metrik:
+Es liegt also Nahe, dass auch aus die Betragsnorm mit $p=1$ eine Metrik induziert - die sogenannte Mannheimer-Metrik:
$$d(x,y) := \displaystyle\sum_{i=1}^{n} \vert x_i - y_i \vert \; \text{mit} \; x, y \in \mathbb{R}^n$$
Die Bezeichnung dieser Metrik als Mannheimer-, Manhattan oder auch Taxi-Metrik wird nachvollziehbar, wenn wir uns bewusst machen, dass sie die Betragsdifferenzen der Punkte aufsummiert und somit den Weg beschreibt, den ein Taxi in einem Straßenraster nachvollziehen müsste, wie es in Mannheim und zahlreichen nordamerikanischen Städten üblich ist, um von A nach B zu gelangen.
-Wir haben also nun zwei Metriken kennengelernt, die beide für verschiedene $$p$$ aus der gleichen p-Norm hervorgehen. Die Mathematik charakterisierende Suche nach gemeinsamen Mustern in abstrakten Strukturen legt nahe, dass so, wie die Betragsnorm und die Euklidische Norm Varianten der allgemeineren Klasse der p-Normen sind, auch die Mannheimer und Euklidische Metrik Varianten einer allgemeineren Klasse von Metriken sind. Diese allgemeinere Klasse beschreiben wir in Form der Minkowski-Metrik:
+Wir haben also nun zwei Metriken kennengelernt, die beide für verschiedene $p$ aus der gleichen p-Norm hervorgehen. Die Mathematik charakterisierende Suche nach gemeinsamen Mustern in abstrakten Strukturen legt nahe, dass so, wie die Betragsnorm und die Euklidische Norm Varianten der allgemeineren Klasse der p-Normen sind, auch die Mannheimer und Euklidische Metrik Varianten einer allgemeineren Klasse von Metriken sind. Diese allgemeinere Klasse beschreiben wir in Form der Minkowski-Metrik:
$$d(x,y) := \left(\displaystyle\sum_{i=1}^{n} \vert x_i - y_i \vert ^p\right)^\frac{1}{p} \; \text{mit} \; x, y \in \mathbb{R}^n ,\; p \in \mathbb{R_+}$$
-Die Beschreibung der Euklidischen und Mannheimer-Metrik als Varianten der Minkowski-Metrik ist damit gerechtfertigt, dass diese für $$p=1$$ beziehungsweise $$p=2$$ aus ihr hervorgehen.
+Die Beschreibung der Euklidischen und Mannheimer-Metrik als Varianten der Minkowski-Metrik ist damit gerechtfertigt, dass diese für $p=1$ beziehungsweise $p=2$ aus ihr hervorgehen.
-Besonders interessant ist im Kontext der Visualisierung von Metriken, dass die Minkowski-Metrik für $$p \in [1, 2]$$ einen stetigen Übergang von der Mannheimer in die Euklidische Metrik ermöglicht. Dies ergibt schöne, _flüssige_ Voronoi-Diagramme, wie wir im Abschnitt zu bewegten Bildern sehen werden.
+Besonders interessant ist im Kontext der Visualisierung von Metriken, dass die Minkowski-Metrik für $p \in [1, 2]$ einen stetigen Übergang von der Mannheimer in die Euklidische Metrik ermöglicht. Dies ergibt schöne, _flüssige_ Voronoi-Diagramme, wie wir im Abschnitt zu bewegten Bildern sehen werden.
-[^1]: $$\mathbb{R}$$ könnte an dieser Stelle auch die Menge $$\mathbb{N}$$ der natürlichen Zahlen, die Menge $$\mathbb{C}$$ der komplexen Zahlen oder ein beliebiger anderer Körper sein, für den der Betrag definiert ist.
-[^2]: Ein Vektorraum ist eine Menge von Vektoren gleicher Dimension, für welche die Operationen der Vektoraddition und Skalarmultiplikation sinnvoll definiert sind. Eine sinnvolle Definition dieser Operationen schließt neben einigen Rechenregeln mit ein, dass ein unter der Addition neutrales Element, der Nullvektor, sowie ein unter der Skalarmultiplikation neutraler Skalar, das Einselement, existieren. Zusätzlich muss zu jedem Vektor ein bezüglich der Addition inverses Element existieren, d.h. ein $$v \in V$$ mit $$v + -v = 0$$. Zusammenfassend führen diese Anforderungen dazu, dass innerhalb eines Vektorraums in weitgehend gewohnter Art und Weise gerechnet werden kann.
-[^3]: Der Begriff $$\mathbb{K}$$-Vektorraum sagt aus, dass alle Komponenten der enthaltenen Vektoren Elemente aus dem Körper $$\mathbb{K}$$ sind. Im Falle eines $$\mathbb{R}$$-Vektorraums sind also beispielsweise alle Komponenten aller Vektoren reelle Zahlen. Der Körper ist dabei auch die Menge, aus der die Skalare für die Skalarmultiplikation gegriffen werden.
-[^4]: Die abgeschlossene Einheitskugel ist die Menge $$\overline{B}(1,0) := \{x \in V \vert \|x\| \leq 1 \}$$ - also die Menge aller Vektoren mit Länge kleiner gleich Eins. Die Visualisierung dieser Kugel kann zur Charakterisierung von Normen herangezogen werden.
+[^1]: $\mathbb{R}$ könnte an dieser Stelle auch die Menge $\mathbb{N}$ der natürlichen Zahlen, die Menge $\mathbb{C}$ der komplexen Zahlen oder ein beliebiger anderer Körper sein, für den der Betrag definiert ist.
+[^2]: Ein Vektorraum ist eine Menge von Vektoren gleicher Dimension, für welche die Operationen der Vektoraddition und Skalarmultiplikation sinnvoll definiert sind. Eine sinnvolle Definition dieser Operationen schließt neben einigen Rechenregeln mit ein, dass ein unter der Addition neutrales Element, der Nullvektor, sowie ein unter der Skalarmultiplikation neutraler Skalar, das Einselement, existieren. Zusätzlich muss zu jedem Vektor ein bezüglich der Addition inverses Element existieren, d.h. ein $v \in V$ mit $v + -v = 0$. Zusammenfassend führen diese Anforderungen dazu, dass innerhalb eines Vektorraums in weitgehend gewohnter Art und Weise gerechnet werden kann.
+[^3]: Der Begriff $\mathbb{K}$-Vektorraum sagt aus, dass alle Komponenten der enthaltenen Vektoren Elemente aus dem Körper $\mathbb{K}$ sind. Im Falle eines $\mathbb{R}$-Vektorraums sind also beispielsweise alle Komponenten aller Vektoren reelle Zahlen. Der Körper ist dabei auch die Menge, aus der die Skalare für die Skalarmultiplikation gegriffen werden.
+[^4]: Die abgeschlossene Einheitskugel ist die Menge $\overline{B}(1,0) := \{x \in V \vert \|x\| \leq 1 \}$ - also die Menge aller Vektoren mit Länge kleiner gleich Eins. Die Visualisierung dieser Kugel kann zur Charakterisierung von Normen herangezogen werden.
## Voronoi-Diagramme
@@ -70,17 +74,17 @@ Nachdem wir uns im vorangehenden Abschnitt einen groben Überblick über Normen
Unter Voronoi-Diagrammen verstehen wir die Aufteilung der Euklidischen Ebene in disjunkte Teilflächen abhängig der Distanz zu einer gegebenen Menge von Punkten und gekennzeichnet durch entsprechende Einfärbung entsprechend des jeweils nächsten Punktes.
-Im Falle der Euklidischen Metrik, d.h. der Minkowski-Metrik mit $$p=2$$, ergeben sich somit Grafiken wie die folgende:
+Im Falle der Euklidischen Metrik, d.h. der Minkowski-Metrik mit $p=2$, ergeben sich somit Grafiken wie die folgende:
![Voronoi-Diagramm der Minkowski-Metrik mit p=2](https://static.kummerlaender.eu/media/voronoi_minkowski_2.png)
-Während wir die Definitionen der Metriken bisher im Speziellen für $$\mathbb{R}^2$$ betrachtet haben, gerät der zugrundeliegende Körper $$\mathbb{R}$$ mit der konkreten Generierung von Voronoi-Diagrammen als Pixelgrafiken in Konflikt, da wir offensichtlich nicht alle Punkte der Teilflächen bzw. Mengen darstellen können. Die naheliegendste Lösung für dieses Problem ist, die Metriken nur auf $$\mathbb{Z}^2$$ zu betrachten. Dies ist einfach möglich, da $$\mathbb{Z}^2$$ eine echte Teilmenge von $$\mathbb{R}^2$$ ist und eine triviale Bijektion zwischen Punkten in $$\mathbb{Z}^2$$ und Pixeln auf einem Bildschirm existiert.
+Während wir die Definitionen der Metriken bisher im Speziellen für $\mathbb{R}^2$ betrachtet haben, gerät der zugrundeliegende Körper $\mathbb{R}$ mit der konkreten Generierung von Voronoi-Diagrammen als Pixelgrafiken in Konflikt, da wir offensichtlich nicht alle Punkte der Teilflächen bzw. Mengen darstellen können. Die naheliegendste Lösung für dieses Problem ist, die Metriken nur auf $\mathbb{Z}^2$ zu betrachten. Dies ist einfach möglich, da $\mathbb{Z}^2$ eine echte Teilmenge von $\mathbb{R}^2$ ist und eine triviale Bijektion zwischen Punkten in $\mathbb{Z}^2$ und Pixeln auf einem Bildschirm existiert.
![Voronoi-Diagramm der Minkowski-Metrik mit p=1](https://static.kummerlaender.eu/media/voronoi_minkowski_1.png)
-Die konkrete Generierung von Voronoi-Diagrammen ist dann einfach möglich - es müssen nur die Punkte der, dem gewünschten Sichtbereich entsprechenden, Teilmenge von $$\mathbb{Z}^2$$ durchlaufen und abhängig ihrer Distanz zu den Referenzpunkten unter der gewünschten Metrik eingefärbt werden.
+Die konkrete Generierung von Voronoi-Diagrammen ist dann einfach möglich - es müssen nur die Punkte der, dem gewünschten Sichtbereich entsprechenden, Teilmenge von $\mathbb{Z}^2$ durchlaufen und abhängig ihrer Distanz zu den Referenzpunkten unter der gewünschten Metrik eingefärbt werden.
-~~~
+```cpp
double minkowski_metric(
const double p,
const imgen::vector& a,
@@ -92,14 +96,13 @@ double minkowski_metric(
1.0 / p
);
}
-~~~
-{:.language-cpp}
+```
-Zur Approximation der Bildmenge $$\mathbb{R}_{\geq 0}$$ der Metrik-Funktionen verwenden wir `double` Werte, während die Ursprungsmenge $$\mathbb{R}^2 \times \mathbb{R}^2$$ über zwei Tupel des Typs `std::tuple<std::ptrdiff_t, std::ptrdiff_t>` in unserer Implementierung abgebildet wird.
+Zur Approximation der Bildmenge $\mathbb{R}_{\geq 0}$ der Metrik-Funktionen verwenden wir `double` Werte, während die Ursprungsmenge $\mathbb{R}^2 \times \mathbb{R}^2$ über zwei Tupel des Typs `std::tuple<std::ptrdiff_t, std::ptrdiff_t>` in unserer Implementierung abgebildet wird.
-Die obige Implementierung der Minkowski Metrik in C++ genügt zusammen mit folgendem, auf einer kleinen PPM _Grafikbibliothek_ basierendem, Listing zur Generierung von Voronoi-Diagrammen über einer fixen `reference_vectors` Punktmenge für beliebige $$p$$.
+Die obige Implementierung der Minkowski Metrik in C++ genügt zusammen mit folgendem, auf einer kleinen PPM _Grafikbibliothek_ basierendem, Listing zur Generierung von Voronoi-Diagrammen über einer fixen `reference_vectors` Punktmenge für beliebige $p$.
-~~~
+```cpp
std::pair<double, imgen::colored_vector> get_distance_to_nearest(
const std::function<double(imgen::vector, imgen::vector)>& metric,
const imgen::vector a
@@ -144,10 +147,9 @@ void generate_minkowski_voronoi(const double p) {
}
);
}
-~~~
-{:.language-cpp}
+```
-Die Punktmenge ist dabei die, welche in obigen Beispiel Diagrammen zu betrachten ist. Alles, was wir an dieser Stelle über die zentrale Funktion `imgen::write_ppm` wissen müssen, ist, dass diese formell ein Bild über der Menge $$M := \{(x, y) \in \mathbb{Z}^2 \vert \: x \in [-\frac{w}{2}, \frac{w}{2}] \land y \in [-\frac{h}{2}, \frac{h}{2}]\}$$ mit Höhe $$h$$ und Breite $$w$$ aufspannt und für $$\forall \: (x, y) \in M$$ die gegebene Funktion $$\mathbb{Z} \times \mathbb{Z} \rightarrow [255] \times [255] \times [255]$$ aufruft, wobei die Tupel ihrer Bildmenge als Farben interpretiert werden.
+Die Punktmenge ist dabei die, welche in obigen Beispiel Diagrammen zu betrachten ist. Alles, was wir an dieser Stelle über die zentrale Funktion `imgen::write_ppm` wissen müssen, ist, dass diese formell ein Bild über der Menge $M := \{(x, y) \in \mathbb{Z}^2 \vert \: x \in [-\frac{w}{2}, \frac{w}{2}] \land y \in [-\frac{h}{2}, \frac{h}{2}]\}$ mit Höhe $h$ und Breite $w$ aufspannt und für $\forall \: (x, y) \in M$ die gegebene Funktion $\mathbb{Z} \times \mathbb{Z} \rightarrow [255] \times [255] \times [255]$ aufruft, wobei die Tupel ihrer Bildmenge als Farben interpretiert werden.
Zur Kennzeichnung der Referenzvektoren wird jeweils eine abgeschlossene Kugel unter der verwendeten Metrik mit Radius 5 gezogen. Dies hat den schönen Nebeneffekt, dass wir anhand der Form der Punktmarkierungen schon Rückschlüsse auf die zur Generierung verwendete Metrik ziehen können, da die Markierungen nur skalierte Versionen der Einheitskugel sind, welche wir im vorangehenden Abschnitt besprochen haben.
@@ -159,7 +161,7 @@ Wie bereits angedeutet, basiert der hier gewählte Weg zur Generierung von Voron
Eines der wohl einfachsten Dateiformate für Pixelgrafiken ist das **P**ortable **P**ix**M**ap Format, dass nur aus der magischen Zahl `P6` gefolgt von Zeilenumbruch-separierter Breite und Höhe sowie einem Stream der Bildpunkte bestehend aus je drei Bytes für Rot, Grün und Blau in dieser Reihenfolge besteht. Dieses primitive Format führt dazu, dass die im Beispiel verwendete `imgen::write_ppm` Funktion sehr einfach zu implementieren ist:
-~~~
+```cpp
void write_ppm(
const std::string& path,
const std::size_t width,
@@ -179,8 +181,7 @@ void write_ppm(
}
}
}
-~~~
-{:.language-cpp}
+```
Den inhärenten Mehraufwand der Verwendung von `std::function` zur Übergabe der Callbacks für Generierung und Metriken und der Ausgabestreams des Standards in `imgen` sowie der eigentlichen Diagram-Generierung akteptiere ich an dieser Stelle der Klarheit und des Vertrauens in den Compiler wegen. Weiterhin lässt sich die Performance von vielen repetiven Generierungen - die ohnehin nicht an der Ein-Ausgabe-Performance sondern an den konkreten Berechnungen hängt - über Multithreading in verkraftbare Schranken weisen.
@@ -190,9 +191,9 @@ Das in meinen Augen schönste Resultat dieses Artikels ist die Visualisierung de
![Übergang von der Mannheimer in die Euklidische Metrik und zurück](https://static.kummerlaender.eu/media/voronoi_cycle.gif)
-Diese Grafik kann dabei vollautomatisch über das, auf [Imagemagick] basierende, Script [voronoi.sh] rekonstruiert werden. Da die Generierung der für die Animation notwendigen zahlreichen Einzelbilder von Voronoi-Diagrammen mit langsam ansteigendem $$p$$ etwas Zeit kosten kann, lohnt sich die Optimierung durch Aufteilen des Arbeitsaufwands auf mehrere Verarbeitungsstränge. Dies ist einfach möglich, da wir keinerlei veränderliche Daten zwischen einzelnen Voronoi-Diagrammen teilen müssen. Da der Standard mittlerweile schon seit einigen Jahren Unterstützung für Multithreading bietet, gestaltet sich auch die konkrete Umsetzung dieser Optimierung erfreulich kompakt.
+Diese Grafik kann dabei vollautomatisch über das, auf [Imagemagick] basierende, Script [voronoi.sh] rekonstruiert werden. Da die Generierung der für die Animation notwendigen zahlreichen Einzelbilder von Voronoi-Diagrammen mit langsam ansteigendem $p$ etwas Zeit kosten kann, lohnt sich die Optimierung durch Aufteilen des Arbeitsaufwands auf mehrere Verarbeitungsstränge. Dies ist einfach möglich, da wir keinerlei veränderliche Daten zwischen einzelnen Voronoi-Diagrammen teilen müssen. Da der Standard mittlerweile schon seit einigen Jahren Unterstützung für Multithreading bietet, gestaltet sich auch die konkrete Umsetzung dieser Optimierung erfreulich kompakt.
-~~~
+```cpp
void generate_parallel_minkowski_voronoi(
const unsigned int thread_count,
const double lower,
@@ -222,8 +223,7 @@ void generate_parallel_minkowski_voronoi(
thread.join();
}
}
-~~~
-{:.language-cpp}
+```
## Rückblick
diff --git a/pages/about.md b/pages/about.md
index 0330552..0d8ab52 100644
--- a/pages/about.md
+++ b/pages/about.md
@@ -1,6 +1,6 @@
# About me
-![picture of me in Scotland](/media/me_header.png){: .full .clear}
+![picture of me in Scotland](/media/me_header.png){.full .clear}
Hi, my name is Adrian Kummerländer. I am a twenty-two-year-old Software Developer located in southern Germany.
diff --git a/pages/impressum.md b/pages/impressum.md
index e0e422d..91ce0f5 100644
--- a/pages/impressum.md
+++ b/pages/impressum.md
@@ -14,5 +14,4 @@ Sollten sich nicht von mir erstellte Inhalte auf diesen Seiten finden, eine ents
Alle eigenen Inhalte stehen - soweit nicht anders gekennzeichnet - unter einer Creative Commons [CC-BY-SA] Lizenz.
-[Eurid]: http://www.eurid.eu/en/whois-search
[CC-BY-SA]: http://creativecommons.org/licenses/by-sa/3.0/de/
diff --git a/pages/projects/binary_mapping.md b/pages/projects/binary_mapping.md
index a53324d..91acae5 100644
--- a/pages/projects/binary_mapping.md
+++ b/pages/projects/binary_mapping.md
@@ -21,7 +21,7 @@ A explanation of an earlier version of this template library can be found on thi
## Usage example
-~~~
+```cpp
BinaryMapping::Container<
BinaryMapping::Tuple<
BinaryMapping::LittleEndian,
@@ -40,8 +40,7 @@ for ( auto&& tuple : container ) {
}
std::uint32_t test = container.at(5).get<0>();
-~~~
-{: .language-cpp}
+```
The code listed above defines a container of a tuple consisting of a `std::uint32_t`, `std::int16_t`, 3-byte and `std::uint8_t` field with little endianess, instantiates a buffer containing ten instances of this tuple, iterates through all 10 elements, gives them values, transparently converts to the correct endianess and extracts the value of the first field of the fifth tuple contained in the buffer. In short: BinaryMapping is a library that abstracts endianess aware serializing of binary structures into structures, containers and iterators. If you are interested in further details of the usage of all features provided by BinaryMapping don't hesitate to check out the [documentation].
diff --git a/pages/projects/build_xslt.md b/pages/projects/build_xslt.md
index 9c71677..83ce4e6 100644
--- a/pages/projects/build_xslt.md
+++ b/pages/projects/build_xslt.md
@@ -18,17 +18,16 @@ The source code of _BuildXSLT_ is available on both my [Github] profile and [cgi
While _BuildXSLT_ offers enough flexibility for all kinds of different XSLT based generation tasks it was specifically built to cater for the requirements of the [static site generator] this site is built with. As such its module definition file and the _XML Makefile_ used to call it makes for the best demonstration of what one can do with _BuildXSLT_:
-~~~
+```xsl
<transformation mode="chain">
<link>src/steps/list.xsl</link>
<link>src/steps/plan.xsl</link>
<link>src/steps/process.xsl</link>
<link>src/steps/summarize.xsl</link>
</transformation>
-~~~
-{: .language-xsl}
+```
-~~~
+```xsl
<task type="module">
<input mode="embedded">
<datasource>
@@ -40,8 +39,7 @@ While _BuildXSLT_ offers enough flexibility for all kinds of different XSLT base
</input>
<definition mode="file">[StaticXSLT.xml]</definition>
</task>
-~~~
-{: .language-xsl}
+```
[InputXSLT]: /page/input_xslt/
[static site generator]: /page/static_xslt/
diff --git a/pages/projects/codepoint_iterator.md b/pages/projects/codepoint_iterator.md
index 6da24ea..4ba929c 100644
--- a/pages/projects/codepoint_iterator.md
+++ b/pages/projects/codepoint_iterator.md
@@ -18,7 +18,7 @@ For readers versed in German a [blog article] describing the implementation in a
While all features of this class are demonstrated by Google-Test based [Unit-Tests] we can see a basic `UTF8::CodepointIterator` usage example in the following code snippet. The [example text] is written in Old Norse runes.
-~~~
+```cpp
std::string test(u8"ᛖᚴ ᚷᛖᛏ ᛖᛏᛁ ᚧ ᚷᛚᛖᚱ ᛘᚾ ᚦᛖᛋᛋ ᚨᚧ ᚡᛖ ᚱᚧᚨ ᛋᚨᚱ");
for ( UTF8::CodepointIterator iter(test.cbegin());
@@ -26,8 +26,7 @@ for ( UTF8::CodepointIterator iter(test.cbegin());
++iter ) {
std::wcout << static_cast<wchar_t>(*iter);
}
-~~~
-{: .language-cpp}
+```
[Github]: https://github.com/KnairdA/CodepointIterator
[cgit]: http://code.kummerlaender.eu/CodepointIterator/
diff --git a/pages/projects/const_list.md b/pages/projects/const_list.md
index 9a5c18c..efd60a0 100644
--- a/pages/projects/const_list.md
+++ b/pages/projects/const_list.md
@@ -22,7 +22,7 @@ Note that these restrictions were overcome in my [second attempt] at this proble
## Usage example
-~~~
+```cpp
const int sum{
ConstList::foldr(
ConstList::make(1, 2, 3, 4, 5),
@@ -32,8 +32,7 @@ const int sum{
0
)
}; // => 15
-~~~
-{: .language-cpp}
+```
[Github]: https://github.com/KnairdA/ConstList/
[cgit]: http://code.kummerlaender.eu/ConstList/
diff --git a/pages/projects/input_xslt.md b/pages/projects/input_xslt.md
index 8cd8eee..b270aac 100644
--- a/pages/projects/input_xslt.md
+++ b/pages/projects/input_xslt.md
@@ -12,12 +12,13 @@ Contrary to popular opinion I actually like XSLT as a content transformation lan
The following table summarizes all the external functions provided by InputXSLT. They are available under the `InputXSLT` namespace after including `function.inputxslt.application` into the stylesheet element.
-|Function |Description |
-|`read-file` |Reading plain text files as text and XML files as node trees |
-|`read-directory` |Traversing filesystem directories |
-|`external-command` |Executing external commands including support for providing the input stream and capturing the output stream |
-|`write-file` |Committing plain text or node trees to the filesystem |
-|`generate` |Calling transformations including support for capturing the result or committing it directly to the filesystem|
+Function Description
+------------------ --------------------------------------------------------------------------------------------------------------
+`read-file` Reading plain text files as text and XML files as node trees
+`read-directory` Traversing filesystem directories
+`external-command` Executing external commands including support for providing the input stream and capturing the output stream
+`write-file` Committing plain text or node trees to the filesystem
+`generate` Calling transformations including support for capturing the result or committing it directly to the filesystem
The `ixslt` XSLT frontent provided by InputXSLT also implements a custom include entity resolver alongside to an easy to use interface for implementing further custom extension functions.
diff --git a/pages/projects/kv.md b/pages/projects/kv.md
index ff11915..b6fa527 100644
--- a/pages/projects/kv.md
+++ b/pages/projects/kv.md
@@ -8,16 +8,17 @@ The MIT licensed source code may be found on [Github] or [cgit].
## Usage example
-|Command |Description |
-|`kv [show]` |List all stores |
-|`kv [show] test` |List all keys of store _test_ |
-|`kv [show] test dummy` |Print value of key _dummy_ in store _test_ |
-|`kv all` |List all keys and values of all stores |
-|`kv all test` |List all keys and values of store _test_ |
-|`kv all test dummy` |Display key and value of key _dummy_ in store _test_|
-|`kv write test dummy example`|Write value _example_ to key _dummy_ in store _test_|
-|`kv delete test dummy` |Delete key _dummy_ of store _test_ |
-|`kv rename test dummy dummy2`|Rename key _dummy_ of store _test_ to _dummy2_ |
+Command Description
+----------------------------- ----------------------------------------------------
+`kv [show]` List all stores
+`kv [show] test` List all keys of store _test_
+`kv [show] test dummy` Print value of key _dummy_ in store _test_
+`kv all` List all keys and values of all stores
+`kv all test` List all keys and values of store _test_
+`kv all test dummy` Display key and value of key _dummy_ in store _test_
+`kv write test dummy example` Write value _example_ to key _dummy_ in store _test_
+`kv delete test dummy` Delete key _dummy_ of store _test_
+`kv rename test dummy dummy2` Rename key _dummy_ of store _test_ to _dummy2_
[Github]: https://github.com/KnairdA/kv/
[cgit]: http://code.kummerlaender.eu/kv/
diff --git a/pages/projects/static_xslt.md b/pages/projects/static_xslt.md
index 8644a6b..b15a9f4 100644
--- a/pages/projects/static_xslt.md
+++ b/pages/projects/static_xslt.md
@@ -14,13 +14,13 @@ The implementation of the static site generator is contained within the `src/ste
These transformations traverse the given source directory, plan tasks[^2] to be executed, process those tasks and summarize the result for the user.
-~~~
+```
common:~# ixslt --input make.xml --transformation ../BuildXSLT/build.xsl
Tasks processed: 19
Tasks successful: 19
▶ Generation successful.
common:~#
-~~~
+```
The first of these transformations `list.xsl` traverses and lists a `source` directory containing various _levels_ depicting the different stages of the actual static site generation process as a base for all further processing.
diff --git a/pages/projects/telebot.md b/pages/projects/telebot.md
index a29e27e..3f2d2f8 100644
--- a/pages/projects/telebot.md
+++ b/pages/projects/telebot.md
@@ -12,24 +12,22 @@ _Telebot_ is available under the terms of the MIT license on [Github] and [cgit]
All _basic_ API wrappers are named the same as their method name and require the bot's token as their first argument. Further parameters are expected as named key value pairs. Note that the library currently only verifies that all required parameters are supplied at all while type verification is left to _Telegram's_ server side logic.
-~~~
+```lisp
(sendMessage token
chat_id: chat_id
text: text)
-~~~
-{:.language-lisp}
+```
All API wrappers return the raw deserialized JSON results as to not limit the options for further parsing unnecessarily.
The only non-API wrapper provided by this library is `pollUpdates` which enables passing updates acquired via long polling of `getUpdates` to an arbitrary function as follows:
-~~~
+```lisp
(pollUpdates token
(lambda (u)
(begin (print-message u)
(echo-message u))))
-~~~
-{:.language-lisp}
+```
[documentation]: https://core.telegram.org/bots/api
[Github]: https://github.com/KnairdA/telebot/
diff --git a/pages/projects/trie.md b/pages/projects/trie.md
index 11e3463..d0bddb2 100644
--- a/pages/projects/trie.md
+++ b/pages/projects/trie.md
@@ -17,7 +17,7 @@ A prefix tree or _Trie_ is a data structure that can be used to store a dynamic
The following example demonstrates the usage of the `Trie` class template specialized on a key and value type. While the first is obviously required the second may be ommitted if not required. Further usage examples are available as Google-Test based [test cases].
-~~~
+```cpp
Trie<uint8_t, uint8_t> trie;
trie.add({1, 1, 1, 1}, 42);
@@ -28,8 +28,7 @@ trie.add({2, 3, 1, 2}, 45);
std::cout << trie.get({1, 1, 1, 1}) << std::endl; // true
std::cout << trie.get({1, 1, 1, 1}).get() << std::endl; // 42
std::cout << trie.get({1, 2}) << std::endl; // false
-~~~
-{: .language-cpp}
+```
[Github]: https://github.com/KnairdA/Trie
[cgit]: http://code.kummerlaender.eu/Trie/
diff --git a/pages/projects/type_as_value.md b/pages/projects/type_as_value.md
index 5a8e37a..2ee35a1 100644
--- a/pages/projects/type_as_value.md
+++ b/pages/projects/type_as_value.md
@@ -30,7 +30,7 @@ Furthermore an overview of this library alongside some background information is
## Usage example
-~~~
+```cpp
// λ (length (filter odd? (list 1 2 3)))
// 2
@@ -40,8 +40,7 @@ const std::size_t count = tav::Length<
tav::List<tav::Int<1>, tav::Int<2>, tav::Int<3>>
>
>::value;
-~~~
-{: .language-cpp}
+```
More extensive [examples] are available in the form of implementations of the _Sieve of Eratosthenes_ as well as of a _Turing machine_.