User Tools

Site Tools


c:start

C++

Parcel Pattern

// STL Archive + stuff
#include <boost/serialization/export.hpp>
#include <boost/serialization/base_object.hpp> 
#include <boost/serialization/list.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
 
// IMPORTANT: Archive Headers at last
// include headers that implement a archive in xml format
#include <boost/archive/archive_exception.hpp>
 
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
 
typedef boost::archive::text_oarchive oarchive;
typedef boost::archive::text_iarchive iarchive;
 
#include <iostream>
#include <sstream>
#include <fstream>
#include <functional>
#include <string>
#include <memory>
 
struct runtime
{
	template <typename T>
	void accept(const T& t)
	{
		std::cout << "runtime::accept(): " << t << std::endl;
	}
};
 
struct base
{
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version)
	{
		// we need it, even it is empty for the serialization
	}
	virtual void operator()(runtime& rt) = 0;
};
 
template <typename T>
struct parcel : base
{
	parcel() : data(T()) {}
	parcel(const T& d)
	{
		data = d;
	}
 
	T data;
 
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version)
	{
		ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
 
		ar & BOOST_SERIALIZATION_NVP(data);
	}
	virtual void operator()(runtime& rt) override
	{
		rt.accept(data);
	}
};
 
template <typename T>
std::unique_ptr<base> create_parcel(const T& d)
{
	 return std::make_unique<parcel<T>>(parcel<T>(d));
}
 
std::string wrap_parcel(base* p_envelope)
{
	std::string ret;
	{
		std::ostringstream oss;
		boost::archive::text_oarchive oa(oss);
 
		// serialize the base pointer
		oa & BOOST_SERIALIZATION_NVP(p_envelope);
 
		ret = oss.str();
	}
	return ret;
}
 
std::unique_ptr<base> unwarp_parcel(std::string data)
{
	std::istringstream iss(data);
	boost::archive::text_iarchive ia(iss);
	base* p = nullptr;
	ia & BOOST_SERIALIZATION_NVP(p);
	return std::unique_ptr<base>(p);
}
 
void out()
{
	std::ofstream ofs("test.txt");
	int payload{ 100 };
	auto envelope = create_parcel(payload);
	auto data = wrap_parcel(envelope.get());
	ofs << data;
}
void in()
{
	std::ifstream ifs("test.txt");
	std::string data;
	std::getline(ifs, data, '\0');
	auto a = unwarp_parcel(data);
 
	runtime rt;
	(*a)(rt);
}
 
BOOST_CLASS_EXPORT(parcel<int>)
 
int main(int argc, char* argv[])
{
	out();
	in();
}

Android NDK

C++11

user defined literals

Aus den Talk von Bjarne Stroustroup [1] habe ich hier ein kleines kompilierbares File gemacht. Es zeigt die Verwendung von user defined literals anhand der physikalischen Einheiten Distanz/Zeit/Geschwindigkeit. Ich finde das schon sehr cool. Damit gibt es keine Einheitenfehler mehr. Es ist immer klar in welcher Einheit ein Wert ist. Generel finde ich diesen Talk Klasse und er zeigt einem viele bessere Wege wie man mit C++11 viele schöne Sachen machen kann.

template<int M, int K, int S> 
struct Unit { // a unit in the MKS system
	enum {m=M, kg=K, s=S };
};
 
template <typename Unit> // a magnitude with a unit
struct Value {
	double val;	// the magnitude
	constexpr Value(double d) : val(d) {}
};
 
// Time
using sec = Unit<0,0,1>;		// the base unit
using min = Unit<0,0,60>;		// minitues
using hour = Unit<0,0,3600>;		// hour
using time = Value<sec>;		// time: base unit seconds
constexpr time operator"" s(long double d)
{
        return time(d);
}
constexpr time operator"" min(long double d)
{
	return time(d * min::s);
}
constexpr time operator"" h(long double d)
{
	return time(d * hour::s);
}
 
// Time square
using sec2 = Unit<0,0,2>;		// base unit
using time2 = Value<sec2>;		// the physical value
constexpr time2 operator"" s2(long double d)
{
	return time2(d);
}
 
// distance
using m = Unit<1,0,0>;			// base unit
using km = Unit<1000,0,0>;		// kilometers
using distance = Value<m>;		// the physical value
constexpr distance operator"" m(long double d)
{
	return distance(d);
}
constexpr distance operator"" km(long double d)
{
	return distance(d * km::m);
}
 
// acceleration
using m_s2 = Unit<1,0,-2>;		// base unit meters/second/second
using accel = Value<m_s2>;		// the physical value
constexpr accel operator"" m_s2 (long double d)
{
	return accel(d);
}
 
// speed
using m_s = Unit<1,0,1>;		// the base unit
using speed = Value<m_s>;		// the physical value
 
using km_h = Unit<1000,0,3600>;		// km/h
constexpr speed operator"" m_s(long double d)
{
	return speed(d);
}
 
constexpr speed operator/(distance d, time t)
{
	return speed(d.val/t.val);
}
int main(int argc, char** argv)
{
	time t = 1.0s;
	speed s1 = 100.0m / 9.8s; // very fast for a human
 
	speed s2 = 1.2km / 0.5h; // slow going
	speed s3 = 1.2km / 30.0min; // the same speed
 
	// speed s2 = 100 / 9.8s; // error
}

[1] http://www.youtube.com/watch?v=0iWb_qi2-uI

Code Snippets

Schneller Test ob eine Ganzzahl eine Zweierpotenz ist:

if (x != 0 && (x & (x-1)) == 0)

Ganze Datei in einem Rutsch in einen Vector oder beliebigen Container einlesen mit back_inserter.

#include <vector>
#include <iterator>
#include <algorithm>
#include <fstream>
 
// target vector
std::vector<unsigned char> buffer; 
 
std::ifstream ifs("filename", ios_base::binary);
if (ifs.is_open())
{
	ifs.unsetf(skipws); 
	std::copy(std::istream_iterator<unsigned char>(ifs), 
  		std::istream_iterator<unsigned char>(), 
       		std::back_inserter(buffer));   
}

Ganze Text Datei in einem Rutsch in einen string einlesen. Es wird bei einer Hex 0 in der Datei gestoppt.

#include <string>
#include <fstream>
 
std::string buffer;
std::ifstream ifs("filename", ios_base::binary);
if (ifs.is_open())
{
	std::getline(ifs, buffer, '\0');
}

Zeilenweises einlesen einer Textdatei

#include <fstream>
#include <string>
 
std::ifstream ifs("filename");
if (ifs.is_open())
{
	std::string line;
	while (std::getline(ifs,line))
	{
		// do stuff with the line
	}	
}
else
{
	// handle error
}

Container in einen std::ostream schieben

#include <iterator>
#include <algorithm>

std::ofstream ofs1("/tmp/s_encoded.txt");
ostream_iterator<char> os1( ofs1, "" );				
std::copy(s_encoded.begin(), s_encoded.end(), os1);

Git workflow mit submodulen

Workflow “Push to origin”:

  • Kompilierbar machen und Testen
  • commit
  • evtl. Testen ob neue Version(commit id) einkompiliert wurde
  • git clone abc xyz
  • testen ob xyz kompiliert und ok ist
  • rm -Rf xyz
  • cd abc
  • git push origin

Der “Zwischenclone” verhindert, dass Versionen comittet werden welche nicht kompilierbar sind, da es vorkommen könnte, dass bsp. Submodule oder andere Dateien nicht im commit enthalten sind. Dies ist der Test, damit ein anderer Entwickler nach einem clone eine funktionierende Kopie erhält.

Workflow “clone from public”:

  • git clone
  • git submodule update –init
This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
c/start.txt · Last modified: 2017/04/20 07:44 by georg