/*$
mlk in apdtool
Copyright (c) 2020 Azel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
$*/

#ifndef MLK_H
#define MLK_H

#include "mlk_config.h"
#include <stdint.h>

typedef int       mlkerr;
typedef uint8_t   mlkbool;
typedef uintptr_t mlksize;
typedef int64_t   mlkfoff;
typedef uint32_t  mlkuchar;
typedef uint16_t  mlkuchar16;
typedef uint32_t  mRgbCol;

typedef struct _mFileStat mFileStat;
typedef struct _mImageBuf mImageBuf;
typedef struct _mImageBuf2 mImageBuf2;

typedef struct _mFontSystem mFontSystem;
typedef struct _mFont mFont;
typedef struct _mFontInfo mFontInfo;
typedef struct _mFontDrawInfo mFontDrawInfo;

typedef void (*mFuncEmpty)(void);


/*---- macro ----*/

#undef NULL
#undef TRUE
#undef FALSE

#define NULL    (0)
#define NULLPTR ((void *)0)
#define TRUE    (1)
#define FALSE   (0)

#define MLK_DIRSEP  '/'

#define MLK_MATH_PI    (3.14159265358979323846)
#define MLK_MATH_PI_2  (1.57079632679489661923)
#define MLK_MATH_1_PI  (0.318309886183790671538)
#define MLK_MATH_2_PI  (0.636619772367581343076)
#define MLK_MATH_DBL_EPSILON  (2.2204460492503131e-016)

#define MLK_MAKE32_2(hi,low)   (((uint32_t)(hi) << 16) | (low))
#define MLK_MAKE32_4(a,b,c,d)  (((uint32_t)(a) << 24) | ((b) << 16) | ((c) << 8) | (d))
#define MLK_RGB(r,g,b)         (((uint32_t)(r) << 16) | ((g) << 8) | (b))
#define MLK_ARGB(r,g,b,a)      (((uint32_t)(a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define MLK_RGB_R(c)           (((c) >> 16) & 0xff)
#define MLK_RGB_G(c)           (((c) >> 8) & 0xff)
#define MLK_RGB_B(c)           ((c) & 0xff)
#define MLK_ARGB_A(c)          ((c) >> 24)
#define MLK_FREE_NULL(p)       mFree(p); p = NULL
#define MLK_PTR_TO_UINT16(p)   (*((uint16_t *)(p)))
#define MLK_PTR_TO_UINT32(p)   (*((uint32_t *)(p)))
#define MLK_FLAG_ON(v,f)       v |= f
#define MLK_FLAG_OFF(v,f)      v &= ~(f)

#define MLK_TO_STR(a)  #a
#define MLK_TO_STR_MACRO(a)  MLK_TO_STR(a)

#if defined(__STDC_VERSION__) && __STDC_VERSION__ < 201102L
#define _Alignas(n)  __attribute__((aligned(n)))
#endif

/*---- enum ----*/

enum MLKERR
{
	MLKERR_OK = 0,
	MLKERR_UNKNOWN,
	MLKERR_ALLOC,
	MLKERR_OPEN,
	MLKERR_IO,
	MLKERR_OVER_DATA,
	MLKERR_NEED_MORE,
	MLKERR_INVALID_VALUE,
	MLKERR_UNSUPPORTED,
	MLKERR_MAX_SIZE,
	MLKERR_FORMAT_HEADER,
	MLKERR_DAMAGED,
	MLKERR_DECODE,
	MLKERR_ENCODE,
	MLKERR_LONGJMP,
	MLKERR_UNFOUND
};

/*---- struct ----*/

typedef struct _mPoint
{
	int32_t x,y;
}mPoint;

typedef struct _mDoublePoint
{
	double x,y;
}mDoublePoint;

typedef struct _mSize
{
	uint32_t w,h;
}mSize;

typedef struct _mRect
{
	int32_t x1,y1,x2,y2;
}mRect;

typedef struct _mBox
{
	int32_t x,y,w,h;
}mBox;

typedef struct _mBuf
{
	uint8_t *buf;
	mlksize allocsize,
		expand_size,
		cursize;
}mBuf;

/* mStr */

typedef struct _mStr mStr;

struct _mStr
{
	char *buf;
	int len,allocsize;
};

#define MSTR_INIT {0,0,0}

/* mList */

typedef struct _mList     mList;
typedef struct _mListItem mListItem;
typedef struct _mListCacheItem mListCacheItem;

struct _mListItem
{
	mListItem *prev,*next;
};

struct _mListCacheItem
{
	mListItem *prev,*next;
	uint32_t refcnt;
};

struct _mList
{
	mListItem *top,*bottom;
	void (*item_destroy)(mList *,mListItem *);
	uint32_t num;
};

#define MLIST_INIT   {0,0,0,0}
#define MLISTITEM(p)      ((mListItem *)(p))
#define MLISTCACHEITEM(p) ((mListCacheItem *)(p))

/* mTree */

typedef struct _mTree mTree;
typedef struct _mTreeItem mTreeItem;

struct _mTreeItem
{
	mTreeItem *prev,*next,
		*first,*last,
		*parent;
};

struct _mTree
{
	mTreeItem *top,*bottom;
	void (*item_destroy)(mTree *,mTreeItem *);
};

#define MTREE_INIT    {0,0,0}
#define MLK_TREE(p)      ((mTree *)(p))
#define MLK_TREEITEM(p)  ((mTreeItem *)(p))



/*---- function ----*/

#ifdef __cplusplus
extern "C" {
#endif

void mDebug(const char *format,...);
void mError(const char *format,...);
void mWarning(const char *format,...);

void mFree_r(void *ptr);
void *mMalloc_r(mlksize size);
void *mMalloc0_r(mlksize size);
void *mRealloc_r(void *ptr,mlksize size);
void *mMallocAlign_r(mlksize size,int alignment);
char *mStrdup_r(const char *str);
char *mStrndup_r(const char *str,int len);

void mMemset0(void *buf,mlksize size);
void *mMemdup(const void *src,mlksize size);

int mStrlen(const char *str);
int mStrdup_getlen(const char *str,char **dst);
char *mStrdup_free(char **dst,const char *src);
char *mStrdup_upper(const char *str);
int mStrncpy(char *dst,const char *src,int size);

mRgbCol mBlendRGB_a256(mRgbCol src,mRgbCol dst,int a);

/* memdebug */

#ifdef MLK_MEMDEBUG

void mFree_debug(void *ptr);
void *mMalloc_debug(mlksize size,const char *filename,int line);
void *mMalloc0_debug(mlksize size,const char *filename,int line);
void *mRealloc_debug(void *ptr,mlksize size,const char *filename,int line);
void *mMallocAlign_debug(mlksize size,int alignment,const char *filename,int line);
char *mStrdup_debug(const char *str,const char *filename,int line);
char *mStrndup_debug(const char *str,int len,const char *filename,int line);

#define mFree(ptr)           mFree_debug(ptr)
#define mMalloc(size)        mMalloc_debug(size, __FILE__, __LINE__)
#define mMalloc0(size)       mMalloc0_debug(size, __FILE__, __LINE__)
#define mRealloc(ptr,size)   mRealloc_debug(ptr, size, __FILE__, __LINE__)
#define mMallocAlign(size,align) mMallocAlign_debug(size, align, __FILE__, __LINE__)
#define mStrdup(str)         mStrdup_debug(str, __FILE__, __LINE__)
#define mStrndup(str,len)    mStrndup_debug(str, len, __FILE__, __LINE__)

#else

#define mFree(ptr)           mFree_r(ptr)
#define mMalloc(size)        mMalloc_r(size)
#define mMalloc0(size)       mMalloc0_r(size)
#define mRealloc(ptr,size)   mRealloc_r(ptr, size)
#define mMallocAlign(size,align) mMallocAlign_r(size, align)
#define mStrdup(str)         mStrdup_r(str)
#define mStrndup(str,len)    mStrndup_r(str, len)

#endif /* MLK_MEMDEBUG < */

#ifdef __cplusplus
}
#endif

#endif
