Encode Fix messages with boost::fusion


#include <boost/fusion/container/set.hpp>
#include <boost/fusion/include/at_key.hpp>
#include <boost/fusion/include/fold.hpp>
#include <cstring>
#include <iostream>

struct Tag1
{
    char value;

    void set(char v)
    {
        value = v;
    }

    int print(char* buf, std::size_t size) const
    {
        return std::snprintf(buf, size, "35=%c", value);
    }
};

struct Tag2
{
    int value;

    void set(int v)
    {
        value = v;
    }

    int print(char* buf, std::size_t size) const
    {
        return std::snprintf(buf, size, "\00121=%d", value);
    }
};

struct Tag3
{
    char value[32];

    void set(const char* v)
    {
        std::strncpy(value, v, sizeof(value));
        value[sizeof(value) - 1] = 0;
    }

    int print(char* buf, std::size_t size) const
    {
        return std::snprintf(buf, size, "\00155=%s", value);
    }
};

struct Writer
{
private:
    struct Func
    {
        Func(char* data, int capacity) : m_data(data), m_capacity(capacity) {}

        template <typename T>
        int operator()(int size, const T& data) const
        {
            if (m_capacity < size)
            {
                return -1;
            }

            int res = data.print(m_data + size, static_cast<std::size_t>(m_capacity - size));
            if (res < 0)
            {
                return res;
            }

            return size + res;
        }
    private:
        char* m_data;
        int m_capacity;
    };

public:
    template<typename T>
    int operator()(const T& msg, char* buffer, int capacity)
    {
        Func func{buffer, capacity};
        return boost::fusion::fold(msg, 0, func);
    }
};

int main()
{
    using Msg = boost::fusion::set<Tag1, Tag3, Tag2>;

    Msg msg;
    boost::fusion::at_key<Tag1>(msg).set('A');
    boost::fusion::at_key<Tag2>(msg).set(123);
    boost::fusion::at_key<Tag3>(msg).set("AAPL");

    char buf[109];
    int size = Writer()(msg, buf, sizeof(buf));
    if (size > 0)
        std::cout << std::string(buf, static_cast<std::size_t>(size)) << std::endl;
}

Advertisements
Posted in Programming | Leave a comment

Scheme call/cc iterator step by step

 
#lang scheme

(define (consume)
  (call/cc control))

(define (control ret)
  (call/cc (lambda (resume)
             (set! control resume)
             (ret 1)))
  (call/cc (lambda (resume)
             (set! control resume)
             (ret 2)))
  (call/cc (lambda (resume)
             (set! control resume)
             (ret 3))))

(consume)
(consume)

Every time control is called, it resets itself to “resume”, which is next expression to be executed.

Next step, we rewrite control function to take numbers from a list. It is done by adding for-each and a lambda function to consume every number in the list:

#lang scheme
(define (consume)
  (call/cc control))

(define (control ret)
  (for-each
   (lambda (elem)
     (call/cc (lambda (resume)
                (set! control resume)
                (ret elem))))
   '(1 2 3)))

Finally, we put both consume and control functions inside a function itor. We take a list as parameter, instead of hard coded input.

#lang scheme
(define (itor lst)
  (define (consume)
    (call/cc control))
  
  (define (control ret)
    (for-each
     (lambda (elem)
       (call/cc (lambda (resume)
                  (set! control resume)
                  (ret elem))))
     lst))

  consume)

(define consume (itor '(a b c)))
(consume)
(consume)

Posted in Programming | Leave a comment

Notes on learning haskell (1)

----------------------------------
--   A DFA that accepts (abc)*
----------------------------------
--   State transition table:
----------------------------------
--    (0, 'a')  -> (True, 1)
--    (1, 'b')  -> (True, 2)
--    (2, 'c')  -> (True, 0)
--    otherwise -> (False, (-1))
----------------------------------

data DFA s a = DFA { runDFA:: s -> (a, s) }

instance Monad (DFA s) where
    return a = DFA $ \s -> (a, s)
    m >>= f  = DFA $ \s ->
        let (a, s') = runDFA m s
            n = f a
        in  runDFA n s'

onOneChar c = DFA $ \state -> case (state, c) of
    (0, 'a') -> (True, 1)
    (1, 'b') -> (True, 2)
    (2, 'c') -> (True, 0)
    _        -> (False, (-1))

parse [] = do return ()
parse (c:cs) = do
    shouldContinue <- onOneChar c
    if shouldContinue then parse cs else return ()

acceptable str = let (_, state) = runDFA (parse str) 0 in state == 0
Posted in Programming | Leave a comment

Cheap dummy head node

It is well known that adding a dummy head node can simplify the insertion and deletion on a linked list, by eliminating the need of special cases (For example: http://www.classes.cs.uchicago.edu/archive/2001/spring/CS117/Lectures/HTML/0406/html/slide_5.html). However, a dummy node uses extra memory, which is not always affordable especially when the size of node is large. In this blog, we will show that a dummy node can be as cheap as a pointer to pointer.

Consider the insertion on a sorted linked list:

void ins(node **l, int x) {
    node **p = l;
    while (*p && (*p)->data <= x)
        p = &((*p)->next);
    *p = new node(x, *p);
}
Posted in Programming | Leave a comment

Python implementation of sieve of Eratosthenes

Lazy functional programming languages can support infinite data structure that contains infinite number of elements. You can define your computation on the infinite data structure. Since the evaluation is lazy, the actual computation will be delayed until it is needed. Some algorithms can be very naturally implemented with this feature.

Python is not a lazy programming language but we can simulate this behavior using generator.

def int2():
    x = 2
    while True:
        yield x
        x = x + 1

int2 is a generater that produces all integers greater than 1.

def filter(gen):
    x = gen.next() #take the first element
    yield x
    while True:
        y = gen.next()
        if y % x != 0: yield y

filter takes a generator as input, and converts it into another generator by filtering out any number that is multiplier of the first element of the input generator.

def seive():
    g = filter(int2())
    while True:
        yield g.next()
        g = filter(g)

prime = seive()

Here prime is a generator that conceptually contains all prime numbers! Let us take first 10 from it:

for x in xrange(0, 10): print prime.next()
Posted in Programming | Leave a comment

Chinese Scholar’s Garden in Staten Island

Posted in Programming | Leave a comment

A puzzle…

Here is a puzzle discussed on Terence Tao’s blog (Yes, Terence Tao!)

http://terrytao.wordpress.com/2011/04/07/the-blue-eyed-islanders-puzzle-repost/

 

Posted in Programming | Leave a comment