

For this example we'll be creating our own custom type of eina value. Eina value can already store struct timeval(man gettimeofday for more information) but it has no type to store struct timezone, so that's what this example will do. \begin{DoxyNote}{Note}
struct timezone is actually obsolete, so using it in real world programs is probably not a good idea, but this is an example so, bear with us.
\end{DoxyNote}
To create our own custom eina value type we need to define functions to do the following operations on it\+: \begin{DoxyItemize}
\item Setup \item Flush \item Copy \item Compare \item Set \item Get \item Conversion\end{DoxyItemize}
Most of this functions are very simple, so let's look at them, starting with setup which only clear the memory so that we can be certain we won't be using stale data\+: 
\begin{DoxyCodeInclude}
\textcolor{comment}{//Compile with:}
\textcolor{comment}{//gcc eina\_value\_03.c -o eina\_value\_03 `pkg-config --cflags --libs eina`}

\textcolor{preprocessor}{#include <\hyperlink{Eina_8h}{Eina.h}>}
\textcolor{preprocessor}{#include <sys/time.h>}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_tz\_setup(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type, \textcolor{keywordtype}{void} *mem)
\{
   memset(mem, 0, type->\hyperlink{struct__Eina__Value__Type_affba7af9a991458855e9c1bdd956210b}{value\_size});
   \textcolor{keywordflow}{return} \hyperlink{group__Eina__Types__Group_ga05c12dacc8b4058994df842b41be85fc}{EINA\_TRUE};
\}

\end{DoxyCodeInclude}


Now the flush function, which is even simpler, it does nothing, that's because there is nothing we need to do, all the necessary steps are taken by eina value itself\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_tz\_flush(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type EINA\_UNUSED, \textcolor{keywordtype}{void} *mem EINA\_UNUSED)
\{
   \textcolor{keywordflow}{return} \hyperlink{group__Eina__Types__Group_ga05c12dacc8b4058994df842b41be85fc}{EINA\_TRUE};
\}

\end{DoxyCodeInclude}


Our next function, copy, is a bit more interesting, but not much, it just casts our void pointers to struct timezone pointers and does the copy\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_tz\_copy(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type EINA\_UNUSED, \textcolor{keyword}{const} \textcolor{keywordtype}{void} *src, \textcolor{keywordtype}{void} * dst)
\{
   \textcolor{keyword}{struct }timezone *tzsrc = (\textcolor{keyword}{struct }timezone *)src;
   \textcolor{keyword}{struct }timezone *tzdst = dst;
   *tzdst = *tzsrc;
   \textcolor{keywordflow}{return} \hyperlink{group__Eina__Types__Group_ga05c12dacc8b4058994df842b41be85fc}{EINA\_TRUE};
\}

\end{DoxyCodeInclude}
 \begin{DoxyNote}{Note}
By now you might be wondering why our functions receive void pointers instead of pointers to struct timezone, and this is a good point. The reason for this is that eina value doesn't know anything about our type so it must use a generic void pointer, casting that pointer into a proper value is the job of the implementor of the new type.
\end{DoxyNote}
Next we have the comparison function, which compares the {\ttfamily tz\+\_\+minuteswest} field of struct timezone, we don't compare {\ttfamily tz\+\_\+dsttime} because that field is not used in linux\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \textcolor{keywordtype}{int}
\_tz\_compare(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type EINA\_UNUSED, \textcolor{keyword}{const} \textcolor{keywordtype}{void} *a, \textcolor{keyword}{const} \textcolor{keywordtype}{void} *b)
\{
   \textcolor{keyword}{struct }timezone tza = *(\textcolor{keyword}{struct }timezone*)a;
   \textcolor{keyword}{struct }timezone tzb = *(\textcolor{keyword}{struct }timezone*)b;

   \textcolor{keywordflow}{if} (tza.tz\_minuteswest < tzb.tz\_minuteswest)
     \textcolor{keywordflow}{return} -1;
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (tza.tz\_minuteswest > tzb.tz\_minuteswest)
     \textcolor{keywordflow}{return} 1;
   \textcolor{keywordflow}{return} 0;
\}

\end{DoxyCodeInclude}


Next we have setting, this however requires not one but rather two functions, the reason for this is because to be able to receive arguments of any type eina value uses \href{https://wikipedia.org/wiki/Variadic_functions}{\tt variadic functions}, so we need a function to get the argument from a va\+\_\+list and another to actually to the setting.

Lets first look at the pset function which sets the received value to a pointer\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_tz\_pset(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type EINA\_UNUSED, \textcolor{keywordtype}{void} *mem, \textcolor{keyword}{const} \textcolor{keywordtype}{void} *ptr)
\{
   *(\textcolor{keyword}{struct }timezone*)mem = *(\textcolor{keyword}{struct} timezone*)ptr;
   \textcolor{keywordflow}{return} \hyperlink{group__Eina__Types__Group_ga05c12dacc8b4058994df842b41be85fc}{EINA\_TRUE};
\}

\end{DoxyCodeInclude}


Next we have the vset function which get the argument from the va\+\_\+list and passes it to the pset function\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_tz\_vset(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type, \textcolor{keywordtype}{void} *mem, va\_list args)
\{
   \textcolor{keyword}{const} \textcolor{keyword}{struct }timezone tz = va\_arg(args, \textcolor{keyword}{struct} timezone);
   \textcolor{keywordflow}{return} \_tz\_pset(type, mem, &tz);
\}

\end{DoxyCodeInclude}


And now the function to get the value, a very simple copying of the value to the given pointer\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_tz\_pget(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type, \textcolor{keyword}{const} \textcolor{keywordtype}{void} *mem, \textcolor{keywordtype}{void} *ptr)
\{
   memcpy(ptr, mem, type->\hyperlink{struct__Eina__Value__Type_affba7af9a991458855e9c1bdd956210b}{value\_size});
   \textcolor{keywordflow}{return} \hyperlink{group__Eina__Types__Group_ga05c12dacc8b4058994df842b41be85fc}{EINA\_TRUE};
\}

\end{DoxyCodeInclude}


And finally our conversion function, this is our longest and most interesting one. For numeric type we simply assign the value of {\ttfamily tz\+\_\+minuteswest} to the new type and call a set function using it\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_tz\_convert\_to(\textcolor{keyword}{const} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *type EINA\_UNUSED, \textcolor{keyword}{const} 
      \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} *convert, \textcolor{keyword}{const} \textcolor{keywordtype}{void} *type\_mem, \textcolor{keywordtype}{void} *convert\_mem)
\{
   \textcolor{keyword}{struct }timezone v = *(\textcolor{keyword}{struct }timezone*)type\_mem;

   \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga798f7b7886e75d016d782c13332c9f7d}{EINA\_VALUE\_TYPE\_UCHAR})
     \{
        \textcolor{keywordtype}{unsigned} \textcolor{keywordtype}{char} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga50bc262dd61c71bac1024b07c7cb1143}{EINA\_VALUE\_TYPE\_USHORT})
     \{
        \textcolor{keywordtype}{unsigned} \textcolor{keywordtype}{short} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga2067ec9d7a8b415f78aaa9a0f5f53348}{EINA\_VALUE\_TYPE\_UINT})
     \{
        \textcolor{keywordtype}{unsigned} \textcolor{keywordtype}{int} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} ((convert == \hyperlink{group__Eina__Value__Group_gaba83e2d960a53456d059f1aca2f3d7d1}{EINA\_VALUE\_TYPE\_ULONG}) || (convert == 
      \hyperlink{group__Eina__Value__Group_ga4406e1fba3da9b1dcb52e4b175370b78}{EINA\_VALUE\_TYPE\_TIMESTAMP}))
     \{
        \textcolor{keywordtype}{unsigned} \textcolor{keywordtype}{long} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_gac700d404e013551f960489cc49df7849}{EINA\_VALUE\_TYPE\_UINT64})
     \{
        uint64\_t other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga0d54e0b952b44b7ac4f2fd573f7839c0}{EINA\_VALUE\_TYPE\_CHAR})
     \{
        \textcolor{keywordtype}{char} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga85845b9a6328ff7bfc202f38fe7cbd4c}{EINA\_VALUE\_TYPE\_SHORT})
     \{
        \textcolor{keywordtype}{short} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga17974fd9ab773a3efefd591ffde58f77}{EINA\_VALUE\_TYPE\_INT})
     \{
        \textcolor{keywordtype}{int} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_gaf8b9c1de294c0287cf28f514c59204a1}{EINA\_VALUE\_TYPE\_LONG})
     \{
        \textcolor{keywordtype}{long} other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga127af77aa29eca66320f21145304ba64}{EINA\_VALUE\_TYPE\_INT64})
     \{
        int64\_t other\_mem = v.tz\_minuteswest;
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_gaa9881efc130366d176e617c8f0f98cf8}{EINA\_VALUE\_TYPE\_FLOAT})
     \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &v.tz\_minuteswest);
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga959961fb03cd94a84ab469245c543732}{EINA\_VALUE\_TYPE\_DOUBLE})
     \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &v.tz\_minuteswest);

\end{DoxyCodeInclude}
 \begin{DoxyNote}{Note}
It would be a good idea to add checks for over and underflow for these types and return \hyperlink{group__Eina__Types__Group_ga1feb115f8e9913e806e090d9bd5a7301}{E\+I\+N\+A\+\_\+\+F\+A\+L\+S\+E} in thoses cases, we omit this here for brevity.
\end{DoxyNote}
For string types we use {\ttfamily snprintf()} to format our {\ttfamily tz\+\_\+minuteswest} field and put it in a string(again {\ttfamily tz\+\_\+dsttime} is ignored because it's not used)\+: 
\begin{DoxyCodeInclude}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (convert == \hyperlink{group__Eina__Value__Group_ga9edaffb2d45ab4d820223289def3e888}{EINA\_VALUE\_TYPE\_STRINGSHARE} ||
            convert == \hyperlink{group__Eina__Value__Group_ga916f76c8d5ffd4c3ee3c322a54efd0b7}{EINA\_VALUE\_TYPE\_STRING})
     \{
        \textcolor{keyword}{const} \textcolor{keywordtype}{char} *other\_mem;
        \textcolor{keywordtype}{char} buf[64];
        snprintf(buf, \textcolor{keyword}{sizeof}(buf), \textcolor{stringliteral}{"%d"}, v.tz\_minuteswest);
        other\_mem = buf; \textcolor{comment}{/* required due &buf == buf */}
        \textcolor{keywordflow}{return} \hyperlink{group__Eina__Value__Type__Group_gaa1db66cf99d88b020f41763cd171a98d}{eina\_value\_type\_pset}(convert, convert\_mem, &other\_mem);
     \}

\end{DoxyCodeInclude}


Finally we handle any other types by returning an error in that case\+: 
\begin{DoxyCodeInclude}
   \textcolor{keywordflow}{return} \hyperlink{group__Eina__Types__Group_ga1feb115f8e9913e806e090d9bd5a7301}{EINA\_FALSE};
\}

\end{DoxyCodeInclude}


Now that we have all the functions, we can populate an {\ttfamily Eina\+\_\+\+Value\+\_\+\+Type} to later use it with {\ttfamily \hyperlink{group__Eina__Value__Value__Group_gab5c6558b1b8be2ad597d71a765cbf5f6}{eina\+\_\+value\+\_\+setup()}}\+: 
\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{struct__Eina__Value__Type}{Eina\_Value\_Type} TZ\_TYPE = \{
   \hyperlink{group__Eina__Value__Type__Group_ga16a703617b8fc48e3ee95663db7becb2}{EINA\_VALUE\_TYPE\_VERSION},
   \textcolor{keyword}{sizeof}(\textcolor{keyword}{struct }timezone),
   "struct timezone",
   \_tz\_setup,
   \_tz\_flush,
   \_tz\_copy,
   \_tz\_compare,
   \_tz\_convert\_to,
   NULL, \textcolor{comment}{//No convert from}
   \_tz\_vset,
   \_tz\_pset,
   \_tz\_pget
\};

\end{DoxyCodeInclude}


We can now finally use our new T\+Z\+\_\+\+T\+Y\+P\+E with eina value, so lets conclude our example by practicing that by setting its value and printing it\+: 
\begin{DoxyCodeInclude}

\textcolor{keywordtype}{int} main(\textcolor{keywordtype}{int} argc EINA\_UNUSED, \textcolor{keywordtype}{char} **argv EINA\_UNUSED)
\{
   \hyperlink{struct__Eina__Value}{Eina\_Value} vtv, vtz;
   \textcolor{keyword}{struct }timeval tv;
   \textcolor{keyword}{struct }timezone tz;
   \textcolor{keywordtype}{char} *s;

   \hyperlink{group__Eina__Main__Group_gabf448ada5bc81a07342b66c6f818ee5e}{eina\_init}();

   \hyperlink{group__Eina__Value__Value__Group_gab5c6558b1b8be2ad597d71a765cbf5f6}{eina\_value\_setup}(&vtv, \hyperlink{group__Eina__Value__Group_ga0dc75915976bd83b0d15f72a5ba34412}{EINA\_VALUE\_TYPE\_TIMEVAL});
   \hyperlink{group__Eina__Value__Value__Group_gab5c6558b1b8be2ad597d71a765cbf5f6}{eina\_value\_setup}(&vtz, &TZ\_TYPE);

   gettimeofday(&tv, &tz);
   \hyperlink{group__Eina__Value__Value__Group_ga9a1407c953694c3d6f40ab01ebe9a294}{eina\_value\_set}(&vtv, tv);
   \hyperlink{group__Eina__Value__Value__Group_ga9a1407c953694c3d6f40ab01ebe9a294}{eina\_value\_set}(&vtz, tz);

   s = \hyperlink{group__Eina__Value__Value__Group_ga8f34b6d6639654dd88cd197c9def78a3}{eina\_value\_to\_string}(&vtv);
   printf(\textcolor{stringliteral}{"time: %s\(\backslash\)n"}, s);
   free(s);
   s = \hyperlink{group__Eina__Value__Value__Group_ga8f34b6d6639654dd88cd197c9def78a3}{eina\_value\_to\_string}(&vtz);
   printf(\textcolor{stringliteral}{"timezone: %s\(\backslash\)n"}, s);
   free(s);

   \hyperlink{group__Eina__Value__Value__Group_ga940660709a2862bafac92f47bb721a68}{eina\_value\_flush}(&vtz);
   \hyperlink{group__Eina__Value__Value__Group_ga940660709a2862bafac92f47bb721a68}{eina\_value\_flush}(&vtv);
\}

\end{DoxyCodeInclude}


For the full source code see \hyperlink{eina_value_03_c}{eina\+\_\+value\+\_\+03.\+c}. 