Click here to Skip to main content
15,881,600 members
Articles / Programming Languages / C

C++ Wrapper Library for Firebird Embedded SQL

,
Rate me:
Please Sign up or sign in to vote.
4.25/5 (9 votes)
23 Sep 2009CPOL8 min read 45.5K   1.1K   24  
This article is devoted to the Embedded Firebird database usage and also development of C++ wrapper of this database.
#ifndef SERVER_UTIL_H
#define SERVER_UTIL_H

#include <string>
#include <sstream>
#include <vector>

namespace utils
{
//-----------------------------------------------------------------------------
template <int iCanBeNonZero>
class CStaticAssert
{
public:
};

template <>
class CStaticAssert<0>
{
public:
    CStaticAssert()
    {
    }
    virtual void Error()=0;
};
//-----------------------------------------------------------------------------
template<class ContainerType>
typename ContainerType::pointer GetBeginOf(ContainerType & container)
{
    if (container.empty())
        return 0;

    return &container.front();
}
template<class ContainerType>
typename ContainerType::const_pointer GetBeginOf(const ContainerType & container)
{
    if (container.empty())
        return 0;

    return &container.front();
}
//------------------------------------------------------------------------------------------------
template<class charType>
struct builder
{
    typedef std::basic_stringstream<charType> used_stringstream;
    typedef std::basic_string<charType> used_string;

private:
    used_stringstream stream;

    builder(const builder&);
    builder& operator = (const builder&);
public:

    operator used_string() const
    {
        return stream.str();
    }

    template<class T1>
        builder(T1 p1)
    {
        stream << p1;
    }
    template<class T1, class T2>
        builder(T1 p1, T2 p2)
    {
        stream << p1 << p2;
    }
    template<class T1, class T2, class T3>
        builder(T1 p1, T2 p2, T3 p3)
    {
        stream << p1 << p2 << p3;
    }
    template<class T1, class T2, class T3, class T4>
        builder(T1 p1, T2 p2, T3 p3, T4 p4)
    {
        stream << p1 << p2 << p3 << p4;
    }

    template<class T1, class T2, class T3, class T4, class T5>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
    {
        stream << p1 << p2 << p3 << p4 << p5;
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6;
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13 << p14;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13 << p14 << p15;
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16>
        builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16)
    {
        stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13 << p14 << p15 << p16;
    }

    template<class T1>
        static used_string
        build(T1 p1)
    {
        return (used_string)builder(p1);
    }


    template<class T1, class T2>
        static used_string
        build(T1 p1, T2 p2)
    {
        return (used_string)builder(p1, p2);
    }

    template<class T1, class T2, class T3>
        static used_string
        build(T1 p1, T2 p2, T3 p3)
    {
        return (used_string)builder(p1, p2, p3);
    }

    template<class T1, class T2, class T3, class T4>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4)
    {
        return (used_string)builder(p1, p2, p3, p4);
    }

    template<class T1, class T2, class T3, class T4, class T5>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
    {
        return (used_string)builder(p1, p2, p3, p4, p5);
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6);
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7);
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8);
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9);
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
    }

    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);
    }
    template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16>
        static used_string
        build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16)
    {
        return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16);
    }

};

typedef builder<char> strBuilder;
typedef builder<wchar_t> strBuilderW;

//-----------------------------------------------------------------------------
template<class wcharVectorType>
inline void char2wstr(const char * str, size_t strSize, wcharVectorType * res, UINT cpId = CP_ACP)
{
    if(!strSize)
        return;
    res->resize(strSize + 1);//it is enough in 99.99%
    while(1)
    {
        int size = MultiByteToWideChar(cpId, 0, str, (int)strSize, &res->front(), (int)res->size());
        if(size)
        {
            res->resize(size + 1);
            return;
        }
        DWORD error = ::GetLastError();
        if(error != ERROR_INSUFFICIENT_BUFFER)
            return;
        size = MultiByteToWideChar(cpId, 0, str, (int)strSize, 0, 0);
        if(!size)
            return;
        res->resize(size + 1);
    }
}

//-----------------------------------------------------------------------------
inline void wchar2str(const wchar_t * str, size_t strSize, std::vector<char> * res, UINT cpId = CP_ACP)
{
    if(!strSize)
        return;
    res->resize(strSize + 1);//it is enough in 99%
    while(1)
    {
        int size = WideCharToMultiByte(cpId, 0, str, (int)strSize, &(*res)[0], (int)res->size(), 0, 0);
        if(size)
        {
            res->resize(size + 1);
            return;
        }
        DWORD error = ::GetLastError();
        if(error != ERROR_INSUFFICIENT_BUFFER)
            return;
        size = WideCharToMultiByte(cpId, 0, str, (int)strSize, 0, 0, 0, 0);
        if(!size)
            return;
        res->resize(size + 1);
    }
}
//-----------------------------------------------------------------------------

inline std::string wstring2string(const std::wstring &from)
{
    std::vector<char> res;
    wchar2str(from.c_str(), from.size(), &res);
    return res.empty()?"":&res[0];
}

inline std::wstring string2wstring(const std::string &from)
{
    std::vector<wchar_t> res;
    char2wstr(from.c_str(), from.size(), &res);
    return res.empty()?L"":&res[0];
}
//-----------------------------------------------------------------------------
// convert
template<class ToType, class FromType>
struct convert
{
};

// trivials
template<>
struct convert<int, int>
{
    static int from(int value)
    {
        return value;
    }
};

template<>
struct convert<long, long>
{
    static long from(long value)
    {
        return value;
    }
};

template<>
struct convert<long long, long long>
{
    static long long from(long long value)
    {
        return value;
    }
};

// trivials
template<>
struct convert<unsigned int, unsigned int>
{
    static unsigned int from(unsigned int value)
    {
        return value;
    }
};

template<>
struct convert<unsigned long, unsigned long>
{
    static unsigned long from(unsigned long value)
    {
        return value;
    }
};

template<> 
struct convert<unsigned long long, unsigned long long>
{
    static unsigned long long from(unsigned long long value)
    {
        return value;
    }
};


inline size_t longlong2size_t(long long val)
{
    if(val > ULONG_MAX || val < 0)
        throw std::exception("Cannot cast.");
    return static_cast<size_t>(val);	 
}
inline size_t ulonglong2size_t(unsigned long long val)
{
    if(val > ULONG_MAX)
        throw std::exception("Cannot cast.");
    return static_cast<size_t>(val);	 
}
inline long long ulonglong2longlong(unsigned long long val)
{
    if(val > LLONG_MAX)
        throw std::exception("Cannot cast.");
    return static_cast<long long>(val);
}

// non trivials
template<>
struct convert<size_t, long long>
{
    static size_t from(long long value)
    {
        return longlong2size_t(value);
    }
};

template<>
struct convert<size_t, unsigned long long>
{
    static size_t from(unsigned long long value)
    {
        return ulonglong2size_t(value);
    }
};

template<>
struct convert<long long, unsigned long long>
{
    static long long from(unsigned long long value)
    {
        return ulonglong2longlong(value);
    }
};

// from size_t to dword
template<>
struct convert<unsigned long, size_t>
{
    static unsigned long from(size_t value)
    {
        if (value <= ULONG_MAX)
            return (unsigned long)value;
        throw std::exception("Cannot cast");
    }
};

template<>
struct convert<long, size_t>
{
    static long from(size_t value)
    {
        if (value <= LONG_MAX)
            return (long)value;
        throw std::exception("Cannot cast");
    }
};

template<>
struct convert<int, size_t>
{
    static int from(size_t value)
    {
        if (value <= INT_MAX)
            return (int)value;
        throw std::exception("Cannot cast");
    }
};

template<>
struct convert<unsigned char, unsigned long>
{
    static unsigned char from(unsigned long value)
    {
        if (value > UCHAR_MAX)
            throw std::exception("Cannot cast");

        return (unsigned char)(value);
    }
};
//-----------------------------------------------------------------------------
inline void FromHexString(const std::wstring & str, char * pBegin, size_t size)
{
    volatile utils::CStaticAssert<sizeof(unsigned char)==sizeof(char)> char_assert; &char_assert;
    size_t iCurrent = 0;
    size_t stringSize = str.size();
    if (!stringSize)
        return;

    if (stringSize%2)
        throw std::exception("FromHexString.IncorrectInputSize");

    char * pEnd = pBegin + size;
    while(1)
    {
        if (iCurrent >= stringSize-1)
            break;

        if (pBegin >= pEnd)
            throw std::exception("BufferTooSmall");

        wchar_t buff[] = {str[iCurrent], str[iCurrent+1], 0};

        wchar_t * pEnd = 0;
        unsigned char ch = utils::convert<unsigned char, unsigned long>::from(wcstoul(buff, &pEnd, 16));
        if ((buff + (sizeof(buff)/sizeof(buff[0])) -1) != pEnd)
            throw std::exception("InvalidBuffer");

        (unsigned char&)(*pBegin) = ch;
        ++pBegin;
        iCurrent+=2;
    }
}

inline void FromHexString(const std::wstring & str, std::vector<char> * pVec)
{
    pVec->clear();
    if (str.empty())
        return;

    pVec->resize(str.size()/2);
    FromHexString(str, utils::GetBeginOf(*pVec), pVec->size());
}
//-----------------------------------------------------------------------------
//  CustomSymbol
//------------------------------------------------------------------------------------------------
template<typename char_type, char symbol>
struct CustomSymbol
{
};
template<char symbol>
struct CustomSymbol<char, symbol>
{
    static const char sym = symbol;
};
template<char symbol>
struct CustomSymbol<wchar_t, symbol>
{
    static const wchar_t sym = (wchar_t)(unsigned char)symbol;
};
//------------------------------------------------------------------------------------------------
template<class charType>
inline bool isHexNumber(charType ch)
{
    return ((ch >= CustomSymbol<charType, '0'>::sym && ch <= CustomSymbol<charType, '9'>::sym) 
        || (ch >= CustomSymbol<charType, 'A'>::sym && ch <= CustomSymbol<charType, 'F'>::sym) 
        || (ch >= CustomSymbol<charType, 'a'>::sym && ch <= CustomSymbol<charType, 'f'>::sym));
}

template<class strType>
inline bool isHexNumberStr(const strType &str)
{
    strType::size_type len = str.length();   

    for (unsigned int i=0; i<len; ++i)
    {
        if(!isHexNumber(str[i])) 
            return false;
    }

    if (len) 
        return true;

    return false;
}
//-----------------------------------------------------------------------------

inline std::string replace_all
( const std::string& src
 , const std::string& match
 , const std::string& str
 )
{
    std::string s = src;
    for( std::string::size_type pos = 0;;)
    {
        pos = s.find( match, pos);
        if( std::string::npos == pos) break;
        s = s.replace( s.begin() + pos, s.begin() + pos + match.size(), str);
        pos += str.size();
    }
    return s;
}

//-----------------------------------------------------------------------------
template<class ItBegin, class ItEnd, class ItOut>
inline void ToUpperCaseA(ItBegin itBegin,  // in
                         ItEnd itEnd,      // in
                         ItOut itOut)      // out
{
    std::vector<char> temp(itBegin, itEnd);
    DWORD dwSize = (DWORD)(itEnd - itBegin);
    if (CharUpperBuffA( &temp.front(), dwSize)!=dwSize)
        throw std::exception("Cannot convert string");
    std::copy(&temp.front(), &temp.front() + dwSize, itOut);
}

template<class ItBegin, class ItEnd, class ItOut>
inline void ToUpperCaseW(ItBegin itBegin,  // in
                         ItEnd itEnd,      // in
                         ItOut itOut)      // out
{
    std::vector<wchar_t> temp(itBegin, itEnd);
    DWORD dwSize = (DWORD)(itEnd - itBegin);
    if (CharUpperBuffW( &temp.front(), dwSize)!=dwSize)
        throw std::exception("Cannot convert string");
    std::copy(&temp.front(), &temp.front() + dwSize, itOut);
}

inline std::string ToUpperCase(const std::string & in_str)
{
    std::string result;
    result.reserve(in_str.size());
    ToUpperCaseA( in_str.begin(), in_str.end(), std::back_inserter(result));
    return result;
}


// to upper case
inline void ToUpperCase(std::wstring::const_iterator itBegin,  // in
                        std::wstring::const_iterator itEnd,    // in
                        std::vector<wchar_t> * pVec)           // out
{
    pVec->assign( itBegin, itEnd );
    if (CharUpperBuffW( &pVec->front(), (DWORD)pVec->size() )!=pVec->size())
        throw std::exception("Cannot convert string");
}

inline std::wstring ToUpperCase(const std::wstring & in_str)
{
    std::wstring result;
    result.reserve(in_str.size());
    ToUpperCaseW( in_str.begin(), in_str.end(), std::back_inserter(result));
    return result;
}

class CHandleGuard
{
    HANDLE h_;
    CHandleGuard(CHandleGuard&);
    CHandleGuard& operator=(CHandleGuard&);
public:
    explicit CHandleGuard(HANDLE h=0)
        :h_(h){}
        ~CHandleGuard(void)
        {
            if(h_)CloseHandle(h_);
        }
        HANDLE get() const {return h_;}
        HANDLE release()
        {
            HANDLE tmp = h_;
            h_ = 0;
            return tmp;
        }
        void reset(HANDLE h)
        {
            if(h_)CloseHandle(h_);
            h_ = h;
        }
};

inline void LoadFileToStr(const std::wstring& fileName, std::string& data)
{
	HANDLE hFile = CreateFileW(fileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	if(hFile == INVALID_HANDLE_VALUE)
		throw std::logic_error(__FUNCTION__" : can't open file " + wstring2string(fileName));
	utils::CHandleGuard fileGuard(hFile);
	DWORD fileSize = GetFileSize(hFile, NULL);
	if(fileSize == INVALID_FILE_SIZE)
		throw std::logic_error(__FUNCTION__" : can't get file size for ");

	if (!fileSize)
		return;

	data.resize(fileSize);
	DWORD bytesRead = 0;

	if(!ReadFile(hFile, &data[0], fileSize, &bytesRead, 0) || bytesRead != fileSize)
		throw std::logic_error(__FUNCTION__" : can't read file ");
}

inline std::vector< std::string > 
split ( const std::string& str, const std::string& sep )
{
    std::vector<std::string> ret;
    for( size_t pos = 0; pos <= str.size();)
    {
        size_t new_pos = str.find( sep, pos);
        if( std::string::npos == new_pos)
            new_pos = str.size();
        ret.push_back( str.substr( pos, new_pos - pos));
        pos = new_pos + sep.size();
    }
    return ret;
}

inline std::vector< std::wstring > 
split ( const std::wstring& str, const std::wstring& sep )
{
    std::vector<std::wstring> ret;
    for( size_t pos = 0; pos <= str.size();)
    {
        size_t new_pos = str.find( sep, pos);
        if( std::string::npos == new_pos)
            new_pos = str.size();
        ret.push_back( str.substr( pos, new_pos - pos));
        pos = new_pos + sep.size();
    }
    return ret;
}


} // namespace utils

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Written By
Software Developer (Senior) ApriorIT
Ukraine Ukraine
Senior Software Developer of Apriorit Inc.
My favorite tasks are multithreading, networking and WDK.

... But in free time : beer, meat, travelling and photo...)

LinkedIn Profile : Wineblat Eugene

Comments and Discussions