[project @ 2002-10-20 14:29:26 by as49] Documentation fixes.

--  -*-haskell-*-
--  GIMP Toolkit (GTK) @entry Drawable@
--
--  Author : Axel Simon
--  Created: 22 September 2002
--
--  Version $Revision: 1.2 $ from $Date: 2002/10/20 14:29:26 $
--
--  Copyright (c) 2002 Axel Simon
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Library General Public
--  License as published by the Free Software Foundation; either
--  version 2 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Library General Public License for more details.
--
-- @description@ --------------------------------------------------------------
--
--  Drawing primitives.
--
-- @documentation@ ------------------------------------------------------------
--
-- * This module defines drawing primitives that can operate on
--   @ref data DrawWindow@s, @ref data Pixmap@s and
--   @ref data Bitmap@s.
--
-- @todo@ ---------------------------------------------------------------------
--
-- * if gdk_visuals are implemented, do: get_visual
-- * if gdk_colormaps are implemented, do: set_colormap, get_colormap
-- * text drawing functions
--
module Drawable(
  Drawable,
  DrawableClass,
  castToDrawable,
  drawableGetDepth,
  drawableGetSize,
  drawableGetClipRegion,
  drawableGetVisibleRegion,
  drawPoint,
  drawPoints,
  drawLine,
  drawLines,
  drawSegments,
  drawRectangle,
  drawArc,
  drawPolygon,
  drawDrawable) where

import Monad	(liftM)
import Foreign
import UTFCForeign
import GObject	(makeNewGObject)
import Structs  (Point)
{#import Hierarchy#}
{#import Region#}	(Region, makeNewRegion)

{# context lib="gtk" prefix="gdk" #}

-- methods

-- @method drawableGetDepth@ Get the size of pixels.
--
-- * Returns the number of bits which are use to store information on each
--   pixels in this @ref data Drawable@.
--
drawableGetDepth :: DrawableClass d => d -> IO Int
drawableGetDepth d = liftM fromIntegral $
		     {#call unsafe drawable_get_depth#} (toDrawable d)

-- @method drawableGetSize@ Retrieve the size of the @ref type Drawable@.
--
-- * The result might not be up-to-date if there are still resizing messages
--   to be processed.
--
drawableGetSize :: DrawableClass d => d -> IO (Int, Int)
drawableGetSize d = alloca $ \wPtr -> alloca $ \hPtr -> do
  {#call unsafe drawable_get_size#} (toDrawable d) wPtr hPtr
  (w::{#type gint#}) <- peek wPtr
  (h::{#type gint#}) <- peek hPtr
  return (fromIntegral w, fromIntegral h)

-- @method drawableGetClipRegion@ Determine where not to draw.
--
-- * Computes the region of a drawable that potentially can be written
--   to by drawing primitives. This region will not take into account the
--   clip region for the GC, and may also not take into account other
--   factors such as if the window is obscured by other windows, but no
--   area outside of this region will be affected by drawing primitives.
--
drawableGetClipRegion :: DrawableClass d => d -> IO Region
drawableGetClipRegion d = do
  rPtr <- {#call unsafe drawable_get_clip_region#} (toDrawable d)
  makeNewRegion rPtr

-- @method drawableGetVisibleRegion@ Determine what not to redraw.
--
-- * Computes the region of a drawable that is potentially visible.
-- This does not necessarily take into account if the window is obscured
-- by other windows, but no area outside of this region is visible.
--
drawableGetVisibleRegion :: DrawableClass d => d -> IO Region
drawableGetVisibleRegion d = do
  rPtr <- {#call unsafe drawable_get_visible_region#} (toDrawable d)
  makeNewRegion rPtr

-- @method drawPoint@ Draw a point into a @ref type Drawable@.
--
drawPoint :: DrawableClass d => d -> GC -> Point -> IO ()
drawPoint d gc (x,y) = {#call unsafe draw_point#} (toDrawable d)
  (toGC gc) (fromIntegral x) (fromIntegral y)

-- @method drawPoints@ Draw several points into a @ref type Drawable@.
--
-- * This function is more efficient than calling @ref method drawPoint@ on
--   several points.
--
drawPoints :: DrawableClass d => d -> GC -> [Point] -> IO ()
drawPoints d gc points =
  withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
  \(aPtr :: Ptr {#type gint#}) -> {#call unsafe draw_points#} (toDrawable d)
    (toGC gc) (castPtr aPtr) (fromIntegral (length points))

-- @method drawLine@ Draw a line into a @ref type Drawable@.
--
-- * The parameters are x1, y1, x2, y2.
--
-- * Drawing several separate lines can be done more efficiently by
--   @ref method drawSegments@.
--
drawLine :: DrawableClass d => d -> GC -> Point -> Point -> IO ()
drawLine d gc (x1,y1) (x2,y2) = {#call unsafe draw_line#} (toDrawable d)
  (toGC gc) (fromIntegral x1) (fromIntegral y1) (fromIntegral x2)
  (fromIntegral x2)

-- @method drawLines@ Draw several lines.
--
-- * The function uses the current line width, dashing and especially the
--   joining specification in the graphics context (in contrast to
--   @ref method drawSegments@.
--
drawLines :: DrawableClass d => d -> GC -> [Point] -> IO ()
drawLines d gc points =
  withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
  \(aPtr :: Ptr {#type gint#}) -> {#call unsafe draw_lines#} (toDrawable d)
    (toGC gc) (castPtr aPtr) (fromIntegral (length points))

-- @method drawSegments@ Draw several unconnected lines.
--
-- * This method draws several unrelated lines.
--
drawSegments :: DrawableClass d => d -> GC -> [(Point,Point)] -> IO ()
drawSegments d gc pps = withArray (concatMap (\((x1,y1),(x2,y2)) ->
  [fromIntegral x1, fromIntegral y1, fromIntegral x2, fromIntegral y2])
  pps) $ \(aPtr :: Ptr {#type gint#}) ->
    {#call unsafe draw_segments#} (toDrawable d) (toGC gc)
    (castPtr aPtr) (fromIntegral (length pps))

-- @method drawRectangle@ Draw a rectangular object.
--
-- * Draws a rectangular outline or filled rectangle, using the
--   foreground color and other attributes of the @ref type GC@.
--
-- * A rectangle drawn filled is 1 pixel smaller in both dimensions
--   than a rectangle outlined. Calling @ref method drawRectangle@ w gc
--   True 0 0 20 20 results in a filled rectangle 20 pixels wide and 20
--   pixels high. Calling @ref method drawRectangle@ d gc False 0 0 20 20
--   results in an outlined rectangle with corners at (0, 0), (0, 20), (20,
--   20), and (20, 0), which makes it 21 pixels wide and 21 pixels high.
--
drawRectangle :: DrawableClass d => d -> GC -> Bool -> Int -> Int ->
				       Int -> Int -> IO ()
drawRectangle d gc filled x y width height = {#call unsafe draw_rectangle#}
  (toDrawable d) (toGC gc) (fromBool filled) (fromIntegral x)
  (fromIntegral y) (fromIntegral width) (fromIntegral height)

-- @method drawArc@ Draws an arc or a filled 'pie slice'.
--
-- * The arc is defined by the bounding rectangle of the entire
--   ellipse, and the start and end angles of the part of the ellipse to be
--   drawn.
--
-- * The starting angle @ref arg aStart@ is relative to the 3 o'clock
--   position, counter-clockwise, in 1/64ths of a degree. @ref arg aEnd@
--   is measured similarly, but relative to @ref arg aStart@.
--
drawArc :: DrawableClass d => d -> GC -> Bool -> Int -> Int ->
				 Int -> Int -> Int -> Int -> IO ()
drawArc d gc filled x y width height aStart aEnd =
  {#call unsafe draw_arc#} (toDrawable d) (toGC gc) (fromBool filled)
  (fromIntegral x) (fromIntegral y) (fromIntegral width) (fromIntegral height)
  (fromIntegral aStart) (fromIntegral aEnd)

-- @method drawPolygon@ Draws an outlined or filled polygon.
--
-- * The polygon is closed automatically, connecting the last point to
--   the first point if necessary.
--
drawPolygon :: DrawableClass d => d -> GC -> Bool -> [Point] -> IO ()
drawPolygon d gc filled points =
  withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
  \(aPtr::Ptr {#type gint#}) -> {#call unsafe draw_polygon#} (toDrawable d)
  (toGC gc) (fromBool filled) (castPtr aPtr) (fromIntegral (length points))

-- @method drawDrawable@ Copies another @ref type Drawable@.
--
-- * Copies the (width,height) region of the @ref arg src@ at coordinates
--   (@ref arg xSrc@, @ref arg ySrc@) to coordinates (@ref arg xDest@,
--   @ref arg yDest@) in the @ref arg dest@. The @ref arg width@ and/or
--   @ref arg height@ may be given as -1, in which case the entire source
--   drawable will be copied.
--
-- * Most fields in @ref arg gc@ are not used for this operation, but
--   notably the clip mask or clip region will be honored.  The source and
--   destination drawables must have the same visual and colormap, or
--   errors will result. (On X11, failure to match visual/colormap results
--   in a BadMatch error from the X server.)  A common cause of this
--   problem is an attempt to draw a bitmap to a color drawable. The way to
--   draw a bitmap is to set the bitmap as a clip mask on your
--   @ref type GC@, then use @ref method drawRectangle@ to draw a
--   rectangle clipped to the bitmap.
--
drawDrawable :: (DrawableClass src, DrawableClass dest) =>
		dest -> GC -> src -> Int -> Int -> Int -> Int ->
		Int -> Int -> IO ()
drawDrawable dest gc src xSrc ySrc xDest yDest width height =
  {#call unsafe draw_drawable#} (toDrawable dest) (toGC gc)
  (toDrawable src)
  (fromIntegral xSrc) (fromIntegral ySrc) (fromIntegral xDest)
  (fromIntegral yDest) (fromIntegral width) (fromIntegral height)

--  -*-haskell-*-
--  GIMP Toolkit (GTK) @entry Drawable@
--
--  Author : Axel Simon
--  Created: 22 September 2002
--
--  Version $Revision: 1.1 $ from $Date: 2002/10/06 16:14:07 $
--
--  Copyright (c) 2002 Axel Simon
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Library General Public
--  License as published by the Free Software Foundation; either
--  version 2 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Library General Public License for more details.
--
-- @description@ --------------------------------------------------------------
--
--  Drawing primitives.
--
-- @documentation@ ------------------------------------------------------------
--
-- * This module defines drawing primitives that can operate on
--   @ref object DrawWindow@s, @ref object Pixmap@s and
--   @ref object Bitmap@s.
--
-- @todo@ ---------------------------------------------------------------------
--
-- * if gdk_visuals are implemented, do: get_visual
-- * if gdk_colormaps are implemented, do: set_colormap, get_colormap
-- * text drawing functions
--
module Drawable(
  Drawable,
  DrawableClass,
  castToDrawable,
  drawableGetDepth,
  drawableGetSize,
  drawableGetClipRegion,
  drawableGetVisibleRegion,
  drawPoint,
  drawPoints,
  drawLine,
  drawLines,
  drawSegments,
  drawRectangle,
  drawArc,
  drawPolygon,
  drawDrawable) where

import Monad	(liftM)
import Foreign
import UTFCForeign
import GObject	(makeNewGObject)
import Structs  (Point)
{#import Hierarchy#}
{#import Region#}	(Region, makeNewRegion)

{# context lib="gtk" prefix="gdk" #}

-- methods

-- @method drawableGetDepth@ Get the size of pixels.
--
-- * Returns the number of bits which are use to store information on each
--   pixels in this @ref object Drawable@.
--
drawableGetDepth :: DrawableClass d => d -> IO Int
drawableGetDepth d = liftM fromIntegral $
		     {#call unsafe drawable_get_depth#} (toDrawable d)

-- @method drawableGetSize@ Retrieve the size of the @ref type Drawable@.
--
-- * The result might not be up-to-date if there are still resizing messages
--   to be processed.
--
drawableGetSize :: DrawableClass d => d -> IO (Int, Int)
drawableGetSize d = alloca $ \wPtr -> alloca $ \hPtr -> do
  {#call unsafe drawable_get_size#} (toDrawable d) wPtr hPtr
  (w::{#type gint#}) <- peek wPtr
  (h::{#type gint#}) <- peek hPtr
  return (fromIntegral w, fromIntegral h)

-- @method drawableGetClipRegion@ Determine where not to draw.
--
-- * Computes the region of a drawable that potentially can be written
--   to by drawing primitives. This region will not take into account the
--   clip region for the GC, and may also not take into account other
--   factors such as if the window is obscured by other windows, but no
--   area outside of this region will be affected by drawing primitives.
--
drawableGetClipRegion :: DrawableClass d => d -> IO Region
drawableGetClipRegion d = do
  rPtr <- {#call unsafe drawable_get_clip_region#} (toDrawable d)
  makeNewRegion rPtr

-- @method drawableGetVisibleRegion@ Determine what not to redraw.
--
-- * Computes the region of a drawable that is potentially visible.
-- This does not necessarily take into account if the window is obscured
-- by other windows, but no area outside of this region is visible.
--
drawableGetVisibleRegion :: DrawableClass d => d -> IO Region
drawableGetVisibleRegion d = do
  rPtr <- {#call unsafe drawable_get_visible_region#} (toDrawable d)
  makeNewRegion rPtr

-- @method drawPoint@ Draw a point into a @ref type Drawable@.
--
drawPoint :: DrawableClass d => d -> GC -> Point -> IO ()
drawPoint d gc (x,y) = {#call unsafe draw_point#} (toDrawable d)
  (toGC gc) (fromIntegral x) (fromIntegral y)

-- @method drawPoints@ Draw several points into a @ref type Drawable@.
--
-- * This function is more efficient than calling @ref method drawPoint@ on
--   several points.
--
drawPoints :: DrawableClass d => d -> GC -> [Point] -> IO ()
drawPoints d gc points =
  withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
  \(aPtr :: Ptr {#type gint#}) -> {#call unsafe draw_points#} (toDrawable d)
    (toGC gc) (castPtr aPtr) (fromIntegral (length points))

-- @method drawLine@ Draw a line into a @ref type Drawable@.
--
-- * The parameters are x1, y1, x2, y2.
--
-- * Drawing several separate lines can be done more efficiently by
--   @ref method drawSegments@.
--
drawLine :: DrawableClass d => d -> GC -> Point -> Point -> IO ()
drawLine d gc (x1,y1) (x2,y2) = {#call unsafe draw_line#} (toDrawable d)
  (toGC gc) (fromIntegral x1) (fromIntegral y1) (fromIntegral x2)
  (fromIntegral x2)

-- @method drawLines@ Draw several lines.
--
-- * The function uses the current line width, dashing and especially the
--   joining specification in the graphics context (in contrast to
--   @ref method drawSegments@.
--
drawLines :: DrawableClass d => d -> GC -> [Point] -> IO ()
drawLines d gc points =
  withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
  \(aPtr :: Ptr {#type gint#}) -> {#call unsafe draw_lines#} (toDrawable d)
    (toGC gc) (castPtr aPtr) (fromIntegral (length points))

-- @method drawSegments@ Draw several unconnected lines.
--
-- * This method draws several unrelated lines.
--
drawSegments :: DrawableClass d => d -> GC -> [(Point,Point)] -> IO ()
drawSegments d gc pps = withArray (concatMap (\((x1,y1),(x2,y2)) ->
  [fromIntegral x1, fromIntegral y1, fromIntegral x2, fromIntegral y2])
  pps) $ \(aPtr :: Ptr {#type gint#}) ->
    {#call unsafe draw_segments#} (toDrawable d) (toGC gc)
    (castPtr aPtr) (fromIntegral (length pps))

-- @method drawRectangle@ Draw a rectangular object.
--
-- * Draws a rectangular outline or filled rectangle, using the
--   foreground color and other attributes of the @ref type GC@.
--
-- * A rectangle drawn filled is 1 pixel smaller in both dimensions
--   than a rectangle outlined. Calling @ref method drawRectangle@ w gc
--   True 0 0 20 20 results in a filled rectangle 20 pixels wide and 20
--   pixels high. Calling @ref method drawRectangle@ d gc False 0 0 20 20
--   results in an outlined rectangle with corners at (0, 0), (0, 20), (20,
--   20), and (20, 0), which makes it 21 pixels wide and 21 pixels high.
--
drawRectangle :: DrawableClass d => d -> GC -> Bool -> Int -> Int ->
				       Int -> Int -> IO ()
drawRectangle d gc filled x y width height = {#call unsafe draw_rectangle#}
  (toDrawable d) (toGC gc) (fromBool filled) (fromIntegral x)
  (fromIntegral y) (fromIntegral width) (fromIntegral height)

-- @method drawArc@ Draws an arc or a filled 'pie slice'.
--
-- * The arc is defined by the bounding rectangle of the entire
--   ellipse, and the start and end angles of the part of the ellipse to be
--   drawn.
--
-- * The starting angle @ref arg aStart@ is relative to the 3 o'clock
--   position, counter-clockwise, in 1/64ths of a degree. @ref arg aEnd@
--   is measured similarly, but relative to @ref arg aStart@.
--
drawArc :: DrawableClass d => d -> GC -> Bool -> Int -> Int ->
				 Int -> Int -> Int -> Int -> IO ()
drawArc d gc filled x y width height aStart aEnd =
  {#call unsafe draw_arc#} (toDrawable d) (toGC gc) (fromBool filled)
  (fromIntegral x) (fromIntegral y) (fromIntegral width) (fromIntegral height)
  (fromIntegral aStart) (fromIntegral aEnd)

-- @method drawPolygon@ Draws an outlined or filled polygon.
--
-- * The polygon is closed automatically, connecting the last point to
--   the first point if necessary.
--
drawPolygon :: DrawableClass d => d -> GC -> Bool -> [Point] -> IO ()
drawPolygon d gc filled points =
  withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
  \(aPtr::Ptr {#type gint#}) -> {#call unsafe draw_polygon#} (toDrawable d)
  (toGC gc) (fromBool filled) (castPtr aPtr) (fromIntegral (length points))

-- @method drawDrawable@ Copies another @ref type Drawable@.
--
-- * Copies the (width,height) region of the @ref arg src@ at coordinates
--   (@ref arg xSrc@, @ref arg ySrc@) to coordinates (@ref arg xDest@, @ref
--   arg yDest@) in the @ref arg dest@. The @ref arg width@ and/or @ref arg
--   height@ may be given as -1, in which case the entire source drawable
--   will be copied.
--
-- * Most fields in @ref arg gc@ are not used for this operation, but
--   notably the clip mask or clip region will be honored.  The source and
--   destination drawables must have the same visual and colormap, or
--   errors will result. (On X11, failure to match visual/colormap results
--   in a BadMatch error from the X server.)  A common cause of this
--   problem is an attempt to draw a bitmap to a color drawable. The way to
--   draw a bitmap is to set the bitmap as a clip mask on your
--   @ref type GC@, then use @ref method drawRectangle@ to draw a
--   rectangle clipped to the bitmap.
--
drawDrawable :: (DrawableClass src, DrawableClass dest) =>
		dest -> GC -> src -> Int -> Int -> Int -> Int ->
		Int -> Int -> IO ()
drawDrawable dest gc src xSrc ySrc xDest yDest width height =
  {#call unsafe draw_drawable#} (toDrawable dest) (toGC gc)
  (toDrawable src)
  (fromIntegral xSrc) (fromIntegral ySrc) (fromIntegral xDest)
  (fromIntegral yDest) (fromIntegral width) (fromIntegral height)


remove use of image format until needed

remove use of image format until needed

-- -----------------------------------------------------------------------------
-- This file is part of Haskell-Opencl.

-- Haskell-Opencl is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.

-- Haskell-Opencl is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.

-- You should have received a copy of the GNU General Public License
-- along with Haskell-Opencl.  If not, see <http://www.gnu.org/licenses/>.
-- -----------------------------------------------------------------------------
module System.GPU.OpenCL.Types(
  -- * Symple CL Types
  CLbool, CLint, CLuint, CLulong, CLProgram, CLEvent, CLMem, CLPlatformID,
  CLDeviceID, CLContext, CLCommandQueue, CLPlatformInfo_, CLDeviceType_,
  CLDeviceInfo_, CLContextInfo_, CLContextProperty_, CLCommandQueueInfo_,
  CLEventInfo_, CLProfilingInfo_, CLCommandType_, CLCommandQueueProperty_,
  CLMemFlags_, CLImageFormat_p, CLMemObjectType_, CLMemInfo_, CLImageInfo_,
  -- * High Level Types
  CLError(..), ErrorCode(..), CLDeviceFPConfig(..), CLDeviceMemCacheType(..),
  CLDeviceExecCapability(..), CLDeviceLocalMemType(..), CLDeviceType(..),
  CLCommandQueueProperty(..), CLCommandType(..),  CLCommandExecutionStatus(..),
  CLProfilingInfo(..), CLPlatformInfo(..), CLMemFlag(..),
  -- * Functions
  clSuccess, wrapPError, getCLValue, getDeviceLocalMemType,
  getDeviceMemCacheType, getCommandType, getCommandExecutionStatus,
  bitmaskToDeviceTypes, bitmaskFromFlags, bitmaskToCommandQueueProperties,
  bitmaskToFPConfig, bitmaskToExecCapability )
       where

-- -----------------------------------------------------------------------------
import Foreign
import Foreign.C.Types
import Data.List( foldl' )

#include <CL/cl.h>

-- -----------------------------------------------------------------------------

type CLPlatformID = {#type cl_platform_id#}
type CLDeviceID = {#type cl_device_id#}
type CLContext = {#type cl_context#}
type CLCommandQueue = {#type cl_command_queue#}
type CLMem = {#type cl_mem#}
type CLEvent = {#type cl_event#}
type CLProgram = {#type cl_program#}

type CLint = {#type cl_int#}
type CLuint = {#type cl_uint#}
type CLulong = {#type cl_ulong#}
type CLbool = {#type cl_bool#}

type CLPlatformInfo_ = {#type cl_platform_info#}
type CLDeviceType_ = {#type cl_device_type#}
type CLDeviceInfo_ = {#type cl_device_info#}
type CLDeviceFPConfig_ = {#type cl_device_fp_config#}
type CLDeviceMemCacheType_ = {#type cl_device_mem_cache_type#}
type CLDeviceLocalMemType_ = {#type cl_device_local_mem_type#}
type CLDeviceExecCapability_ = {#type cl_device_exec_capabilities#}
type CLContextInfo_ = {#type cl_context_info#}
type CLContextProperty_ = {#type cl_context_properties#}
type CLCommandQueueInfo_ = {#type cl_command_queue_info#}
type CLCommandQueueProperty_ = {#type cl_command_queue_properties#}
type CLEventInfo_ = {#type cl_event_info#}
type CLProfilingInfo_ = {#type cl_profiling_info#}
type CLCommandType_ = {#type cl_command_type#}
type CLMemFlags_ = {#type cl_mem_flags#}
type CLMemObjectType_ = {#type cl_mem_object_type#}
type CLMemInfo_ = {#type cl_mem_info#}
type CLImageInfo_ = {#type cl_image_info#}

{#pointer *cl_image_format as CLImageFormat_p#}

--type CLImageChannelOrder_ = {#type cl_channel_order#}
--type CLImageChannelDataType_ = {#type cl_channel_type#}

-- -----------------------------------------------------------------------------
newtype ErrorCode = ErrorCode CLint deriving( Eq )

clSuccess :: ErrorCode
clSuccess = ErrorCode (0)

-- -----------------------------------------------------------------------------
#c
enum CLError {
  CLBUILD_PROGRAM_FAILURE=CL_BUILD_PROGRAM_FAILURE,
  CLCOMPILER_NOT_AVAILABLE=CL_COMPILER_NOT_AVAILABLE,
  CLDEVICE_NOT_AVAILABLE=CL_DEVICE_NOT_AVAILABLE,
  CLDEVICE_NOT_FOUND=CL_DEVICE_NOT_FOUND,
  CLIMAGE_FORMAT_MISMATCH=CL_IMAGE_FORMAT_MISMATCH,
  CLIMAGE_FORMAT_NOT_SUPPORTED=CL_IMAGE_FORMAT_NOT_SUPPORTED,
  CLINVALID_ARG_INDEX=CL_INVALID_ARG_INDEX,
  CLINVALID_ARG_SIZE=CL_INVALID_ARG_SIZE,
  CLINVALID_ARG_VALUE=CL_INVALID_ARG_VALUE,
  CLINVALID_BINARY=CL_INVALID_BINARY,
  CLINVALID_BUFFER_SIZE=CL_INVALID_BUFFER_SIZE,
  CLINVALID_BUILD_OPTIONS=CL_INVALID_BUILD_OPTIONS,
  CLINVALID_COMMAND_QUEUE=CL_INVALID_COMMAND_QUEUE,
  CLINVALID_CONTEXT=CL_INVALID_CONTEXT,
  CLINVALID_DEVICE=CL_INVALID_DEVICE,
  CLINVALID_DEVICE_TYPE=CL_INVALID_DEVICE_TYPE,
  CLINVALID_EVENT=CL_INVALID_EVENT,
  CLINVALID_EVENT_WAIT_LIST=CL_INVALID_EVENT_WAIT_LIST,
  CLINVALID_GL_OBJECT=CL_INVALID_GL_OBJECT,
  CLINVALID_GLOBAL_OFFSET=CL_INVALID_GLOBAL_OFFSET,
  CLINVALID_HOST_PTR=CL_INVALID_HOST_PTR,
  CLINVALID_IMAGE_FORMAT_DESCRIPTOR=CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
  CLINVALID_IMAGE_SIZE=CL_INVALID_IMAGE_SIZE,
  CLINVALID_KERNEL_NAME=CL_INVALID_KERNEL_NAME,
  CLINVALID_KERNEL=CL_INVALID_KERNEL,
  CLINVALID_KERNEL_ARGS=CL_INVALID_KERNEL_ARGS,
  CLINVALID_KERNEL_DEFINITION=CL_INVALID_KERNEL_DEFINITION,
  CLINVALID_MEM_OBJECT=CL_INVALID_MEM_OBJECT,
  CLINVALID_OPERATION=CL_INVALID_OPERATION,
  CLINVALID_PLATFORM=CL_INVALID_PLATFORM,
  CLINVALID_PROGRAM=CL_INVALID_PROGRAM,
  CLINVALID_PROGRAM_EXECUTABLE=CL_INVALID_PROGRAM_EXECUTABLE,
  CLINVALID_QUEUE_PROPERTIES=CL_INVALID_QUEUE_PROPERTIES,
  CLINVALID_SAMPLER=CL_INVALID_SAMPLER,
  CLINVALID_VALUE=CL_INVALID_VALUE,
  CLINVALID_WORK_DIMENSION=CL_INVALID_WORK_DIMENSION,
  CLINVALID_WORK_GROUP_SIZE=CL_INVALID_WORK_GROUP_SIZE,
  CLINVALID_WORK_ITEM_SIZE=CL_INVALID_WORK_ITEM_SIZE,
  CLMAP_FAILURE=CL_MAP_FAILURE,
  CLMEM_OBJECT_ALLOCATION_FAILURE=CL_MEM_OBJECT_ALLOCATION_FAILURE,
  CLMEM_COPY_OVERLAP=CL_MEM_COPY_OVERLAP,
  CLOUT_OF_HOST_MEMORY=CL_OUT_OF_HOST_MEMORY,
  CLOUT_OF_RESOURCES=CL_OUT_OF_RESOURCES,
  CLPROFILING_INFO_NOT_AVAILABLE=CL_PROFILING_INFO_NOT_AVAILABLE,
  CLSUCCESS=CL_SUCCESS
  };
#endc

{-|
* 'CLBUILD_PROGRAM_FAILURE', Returned if there is a failure to build the
program executable.

 * 'CLCOMPILER_NOT_AVAILABLE', Returned if the parameter program is created with
'clCreateProgramWithSource' and a compiler is not available. For example
'clDeviceCompilerAvalaible' is set to 'False'.

 * 'CLDEVICE_NOT_AVAILABLE', Returned if the specified device is not currently
available.

 * 'CLDEVICE_NOT_FOUND', Returned if no OpenCL devices that match the specified
devices were found.

 * 'CLIMAGE_FORMAT_MISMATCH', Returned if the specified source and destination
images are not valid image objects.

 * 'CLIMAGE_FORMAT_NOT_SUPPORTED', Returned if the specified image format is not
supported.

 * 'CLINVALID_ARG_INDEX', Returned if an invalid argument index is specified.

 * 'CLINVALID_ARG_SIZE', Returned if argument size specified (arg_size) does not
match the size of the data type for an argument that is not a memory object, or
if the argument is a memory object and arg_size != sizeof(cl_mem) or if arg_size
is zero and the argument is declared with the __local qualifier or if the
argument is a sampler and arg_size != sizeof(cl_sampler).

 * 'CLINVALID_ARG_VALUE', Returned if the argument value specified is NULL for
an argument that is not declared with the __local qualifier or vice-versa.

 * 'CLINVALID_BINARY', Returned if the program binary is not a valid binary for
the specified device.

 * 'CLINVALID_BUFFER_SIZE', Returned if the value of the parameter size is 0 or
is greater than 'clDeviceMaxMemAllocSize' for all devices specified in the
parameter context.

 * 'CLINVALID_BUILD_OPTIONS', Returned if the specified build options are
invalid.

 * 'CLINVALID_COMMAND_QUEUE', Returned if the specified command-queue is not a
valid command-queue.

 * 'CLINVALID_CONTEXT', Returned if the specified context is not a valid OpenCL
context, or the context associated with certain parameters are not the same.

 * 'CLINVALID_DEVICE', Returned if the device or devices specified are not
valid.

 * 'CLINVALID_DEVICE_TYPE', Returned if device type specified is not valid.

 * 'CLINVALID_EVENT', Returned if the event objects specified are not valid.

 * 'CLINVALID_EVENT_WAIT_LIST', Returned if event_wait_list is NULL and
num_events_in_wait_list > 0, or event_wait_list_list is not NULL and
num_events_in_wait_list is 0, or specified event objects are not valid events.

 * 'CLINVALID_GL_OBJECT', Returned if obj is not a vaild GL object or is a GL
object but does not have an existing data store.

 * 'CLINVALID_GLOBAL_OFFSET', Returned if global_work_offset is not NULL.

 * 'CLINVALID_HOST_PTR', Returned if host_ptr is NULL and 'CLMEM_USE_HOST_PTR'
or 'CLMEM_COPY_HOST_PTR' are set in flags or if host_ptr is not NULL but
'CLMEM_COPY_HOST_PTR' or 'CLMEM_USE_HOST_PTR' are not set in flags.

 * 'CLINVALID_IMAGE_FORMAT_DESCRIPTOR', Returned if the image format specified
is not valid or is NULL or does not map to a supported OpenCL image format.

 * 'CLINVALID_IMAGE_SIZE', Returned if the specified image width or height are
invalid or if the image row pitch and image slice pitch do not follow the rules.

 * 'CLINVALID_KERNEL_NAME', Returned if the specified kernel name is not found
in program.

 * 'CLINVALID_KERNEL', Returned if the specified kernel is not a valid kernel
object.

 * 'CLINVALID_KERNEL_ARGS', Returned if the kernel argument values have not been
specified.

 * 'CLINVALID_KERNEL_DEFINITION', Returned if the function definition for
__kernel function given by kernel_name such as the number of arguments, the
argument types are not the same for all devices for which the program executable
has been built.

 * 'CLINVALID_MEM_OBJECT', Returned if a parameter is not a valid memory, image,
or buffer object.

 * 'CLINVALID_OPERATION', Returned if there are no devices in context that
support images. Returned if the build of a program executable for any of the
devices specified by a previous call to 'clBuildProgram' for program has not
completed, or if there are kernel objects attached to program. Returned by
'clEnqueueNativeKernel' if the specified device cannot execute the native
kernel.

 * 'CLINVALID_PLATFORM', Returned if the specified platform is not a valid
platform, or no platform could be selected, or if platform value specified in
properties is not a valid platform.

 * 'CLINVALID_PROGRAM', Returned if the specified program is not a valid program
object.

 * 'CLINVALID_PROGRAM_EXECUTABLE', Returned if there is no successfully built
executable for program, or if there is no device in program. Returned if there
is no successfully built program executable available for device associated with
command_queue.

 * 'CLINVALID_QUEUE_PROPERTIES', Returned if specified properties are valid but
are not supported by the device.

 * 'CLINVALID_SAMPLER', Returned if the specified sampler is not a valid sampler
object, or for an argument declared to be of type sampler_t when the specified
arg_value is not a valid sampler object.

 * 'CLINVALID_VALUE', Returned if a parameter is not an expected value.

 * 'CLINVALID_WORK_DIMENSION', Returned if work_dim is not a valid value.

 * 'CLINVALID_WORK_GROUP_SIZE', Returned if local_work_size is specified and
number of workitems specified by global_work_size is not evenly divisible by
size of work-group given by local_work_size or does not match the work-group
size specified for kernel using the __attribute__((reqd_work_group_size(X, Y,
Z))) qualifier in program source.

 * 'CLINVALID_WORK_ITEM_SIZE', Returned if the number of work-items specified in
any of local_work_size... [0]... local_work_size[work_dim - 1] is greater than
the corresponding values specified by 'clDeviceMaxWorkItemSizes'.

 * 'CLMAP_FAILURE', Returned by if there is a failure to map the requested
region into the host address space. This error cannot occur for buffer objects
created with 'CLMEM_USE_HOST_PTR' or 'CLMEM_ALLOC_HOST_PTR'.

 * 'CLMEM_OBJECT_ALLOCATION_FAILURE', Returned if there is a failure to allocate
memory for data store associated with image or buffer objects specified as
arguments to kernel.

 * 'CLMEM_COPY_OVERLAP', Returned if the source and destination images are the
same image (or the source and destination buffers are the same buffer), and the
source and destination regions overlap.

 * 'CL_OUT_OF_HOST_MEMORY', Returned in the event of a failure to allocate
resources required by the OpenCL implementation on the host.

 * 'CLOUT_OF_RESOURCES', Returned in the event of a failure to queue the
execution instance of kernel on the command-queue because of insufficient
resources needed to execute the kernel.

 * 'CLPROFILING_INFO_NOT_AVAILABLE', Returned if the 'CLQUEUE_PROFILING_ENABLE'
flag is not set for the command-queue and the profiling information is currently
not available (because the command identified by event has not completed).

 * 'CLSUCCESS', Indicates that the function executed successfully.
-}
{#enum CLError {} deriving( Show, Eq ) #}

wrapPError :: (Ptr CLint -> IO a) -> IO (Either CLError a)
wrapPError f = alloca $ \perr -> do
  v <- f perr
  errcode <- peek perr >>= return . toEnum . fromIntegral
  if errcode == CLSUCCESS
    then return $ Right v
    else return $ Left errcode

-- -----------------------------------------------------------------------------
#c
enum CLPlatformInfo {
CLPLATFORM_PROFILE=CL_PLATFORM_PROFILE,
CLPLATFORM_VERSION=CL_PLATFORM_VERSION,
CLPLATFORM_NAME=CL_PLATFORM_NAME,
CLPLATFORM_VENDOR=CL_PLATFORM_VENDOR,
CLPLATFORM_EXTENSIONS=CL_PLATFORM_EXTENSIONS
  };
#endc

{-|
 * 'CLPLATFORM_PROFILE', OpenCL profile string. Returns the profile name
supported by the implementation. The profile name returned can be one of the
following strings:

 [@FULL_PROFILE@] If the implementation supports the OpenCL specification
(functionality defined as part of the core specification and does not require
any extensions to be supported).

 [@EMBEDDED_PROFILE@] If the implementation supports the OpenCL embedded
profile. The embedded profile is  defined to be a subset for each version of
OpenCL.

 * 'CLPLATFORM_VERSION', OpenCL version string. Returns the OpenCL version
supported by the implementation. This version string has the following format:
/OpenCL major_version.minor_version platform-specific information/ The
/major_version.minor_version/ value returned will be 1.0.

 * 'CLPLATFORM_NAME', Platform name string.

 * 'CLPLATFORM_VENDOR', Platform vendor string.

 * 'CLPLATFORM_EXTENSIONS', Returns a space-separated list of extension names
(the extension names themselves do not contain any spaces) supported by the
platform. Extensions defined here must be supported by all devices associated
with this platform.
-}
{#enum CLPlatformInfo {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
#c
enum CLDeviceType {
CLDEVICE_TYPE_CPU=CL_DEVICE_TYPE_CPU,
CLDEVICE_TYPE_GPU=CL_DEVICE_TYPE_GPU,
CLDEVICE_TYPE_ACCELERATOR=CL_DEVICE_TYPE_ACCELERATOR,
CLDEVICE_TYPE_DEFAULT=CL_DEVICE_TYPE_DEFAULT,
CLDEVICE_TYPE_ALL=CL_DEVICE_TYPE_ALL
  };
#endc

{-|
 * 'CLDEVICE_TYPE_CPU', An OpenCL device that is the host processor. The host
processor runs the OpenCL implementations and is a single or multi-core CPU.

 * 'CLDEVICE_TYPE_GPU', An OpenCL device that is a GPU. By this we mean that the
device can also be used to accelerate a 3D API such as OpenGL or DirectX.

 * 'CLDEVICE_TYPE_ACCELERATOR', Dedicated OpenCL accelerators (for example the
IBM CELL Blade). These devices communicate with the host processor using a
peripheral interconnect such as PCIe.

 * 'CLDEVICE_TYPE_DEFAULT', The default OpenCL device in the system.

 * 'CLDEVICE_TYPE_ALL', All OpenCL devices available in the system.
-}
{#enum CLDeviceType {} deriving( Show ) #}

#c
enum CLCommandQueueProperty {
  CLQUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE=CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
  CLQUEUE_PROFILING_ENABLE=CL_QUEUE_PROFILING_ENABLE
  };
#endc

{-|
 * 'CLQUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE', Determines whether the commands
queued in the command-queue are executed in-order or out-of-order. If set, the
commands in the command-queue are executed out-of-order. Otherwise, commands are
executed in-order.

 * 'CLQUEUE_PROFILING_ENABLE', Enable or disable profiling of commands in the
command-queue. If set, the profiling of commands is enabled. Otherwise profiling
of commands is disabled. See 'clGetEventProfilingInfo' for more information.
-}
{#enum CLCommandQueueProperty {} deriving( Show, Bounded, Eq, Ord ) #}

#c
enum CLDeviceFPConfig {
  CLFP_DENORM=CL_FP_DENORM, CLFP_INF_NAN=CL_FP_INF_NAN,
  CLFP_ROUND_TO_NEAREST=CL_FP_ROUND_TO_NEAREST,
  CLFP_ROUND_TO_ZERO=CL_FP_ROUND_TO_ZERO,
  CLFP_ROUND_TO_INF=CL_FP_ROUND_TO_INF, CLFP_FMA=CL_FP_FMA,
  };
#endc

{-|
 * 'CLFP_DENORM', denorms are supported.

 * 'CLFP_INF_NAN', INF and NaNs are supported.

 * 'CLFP_ROUND_TO_NEAREST', round to nearest even rounding mode supported.

 * 'CLFP_ROUND_TO_ZERO', round to zero rounding mode supported.

 * 'CLFP_ROUND_TO_INF', round to +ve and -ve infinity rounding modes supported.

 * 'CLFP_FMA', IEEE754-2008 fused multiply-add is supported.
-}
{#enum CLDeviceFPConfig {} deriving( Show, Bounded, Eq, Ord ) #}

#c
enum CLDeviceExecCapability {
  CLEXEC_KERNEL=CL_EXEC_KERNEL,
  CLEXEC_NATIVE_KERNEL=CL_EXEC_NATIVE_KERNEL
  };
#endc

{-|
 * 'CLEXEC_KERNEL', The OpenCL device can execute OpenCL kernels.

 * 'CLEXEC_NATIVE_KERNEL', The OpenCL device can execute native kernels.
-}
{#enum CLDeviceExecCapability {} deriving( Show, Bounded, Eq, Ord ) #}

#c
enum CLDeviceMemCacheType {
  CLNONE=CL_NONE,CLREAD_ONLY_CACHE=CL_READ_ONLY_CACHE,
  CLREAD_WRITE_CACHE=CL_READ_WRITE_CACHE
  };
#endc

{#enum CLDeviceMemCacheType {} deriving( Show ) #}

#c
enum CLDeviceLocalMemType {
  CLLOCAL=CL_LOCAL, CLGLOBAL=CL_GLOBAL
  };
#endc

{#enum CLDeviceLocalMemType {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
#c
enum CLCommandType {
  CLCOMMAND_NDRANGE_KERNEL=CL_COMMAND_NDRANGE_KERNEL,
  CLCOMMAND_TASK=CL_COMMAND_TASK ,
  CLCOMMAND_NATIVE_KERNEL=CL_COMMAND_NATIVE_KERNEL,
  CLCOMMAND_READ_BUFFER=CL_COMMAND_READ_BUFFER,
  CLCOMMAND_WRITE_BUFFER=CL_COMMAND_WRITE_BUFFER,
  CLCOMMAND_COPY_BUFFER=CL_COMMAND_COPY_BUFFER,
  CLCOMMAND_READ_IMAGE=CL_COMMAND_READ_IMAGE,
  CLCOMMAND_WRITE_IMAGE=CL_COMMAND_WRITE_IMAGE,
  CLCOMMAND_COPY_IMAGE=CL_COMMAND_COPY_IMAGE,
  CLCOMMAND_COPY_BUFFER_TO_IMAGE=CL_COMMAND_COPY_BUFFER_TO_IMAGE,
  CLCOMMAND_COPY_IMAGE_TO_BUFFER=CL_COMMAND_COPY_IMAGE_TO_BUFFER,
  CLCOMMAND_MAP_BUFFER=CL_COMMAND_MAP_BUFFER,
  CLCOMMAND_MAP_IMAGE=CL_COMMAND_MAP_IMAGE,
  CLCOMMAND_UNMAP_MEM_OBJECT=CL_COMMAND_UNMAP_MEM_OBJECT,
  CLCOMMAND_MARKER=CL_COMMAND_MARKER,
  CLCOMMAND_ACQUIRE_GL_OBJECTS=CL_COMMAND_ACQUIRE_GL_OBJECTS,
  CLCOMMAND_RELEASE_GL_OBJECTS=CL_COMMAND_RELEASE_GL_OBJECTS
  };
#endc

-- | Command associated with an event.
{#enum CLCommandType {} deriving( Show ) #}

#c
enum CLCommandExecutionStatus {
  CLQUEUED=CL_QUEUED, CLSUBMITTED=CL_SUBMITTED, CLRUNNING=CL_RUNNING,
  CLCOMPLETE=CL_COMPLETE, CLEXEC_ERROR= -1
  };
#endc

{-|
 * 'CLQUEUED', command has been enqueued in the command-queue.

 * 'CLSUBMITTED', enqueued command has been submitted by the host to the
device associated with the command-queue.

 * 'CLRUNNING', device is currently executing this command.

 * 'CLCOMPLETE', the command has completed.

 * 'CLEXEC_ERROR', command was abnormally terminated.
-}
{#enum CLCommandExecutionStatus {} deriving( Show ) #}

#c
enum CLProfilingInfo {
  CLPROFILING_COMMAND_QUEUED=CL_PROFILING_COMMAND_QUEUED,
  CLPROFILING_COMMAND_SUBMIT=CL_PROFILING_COMMAND_SUBMIT,
  CLPROFILING_COMMAND_START=CL_PROFILING_COMMAND_START,
  CLPROFILING_COMMAND_END=CL_PROFILING_COMMAND_END
  };
#endc

{-| Specifies the profiling data.

 * 'CLPROFILING_COMMAND_QUEUED', A 64-bit value that describes the current
device time counter in nanoseconds when the command identified by event is
enqueued in a command-queue by the host.

 * 'CLPROFILING_COMMAND_SUBMIT', A 64-bit value that describes the current
device time counter in nanoseconds when the command identified by event that has
been enqueued is submitted by the host to the device associated with the
commandqueue.

 * 'CLPROFILING_COMMAND_START',	 A 64-bit value that describes the current
device time counter in nanoseconds when the command identified by event starts
execution on the device.

 * 'CLPROFILING_COMMAND_END', A 64-bit value that describes the current device
time counter in nanoseconds when the command identified by event has finished
execution on the device.
-}
{#enum CLProfilingInfo {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
#c
enum CLMemFlag {
  CLMEM_READ_WRITE=CL_MEM_READ_WRITE,
  CLMEM_WRITE_ONLY=CL_MEM_WRITE_ONLY,
  CLMEM_READ_ONLY=CL_MEM_READ_ONLY,
  CLMEM_USE_HOST_PTR=CL_MEM_USE_HOST_PTR,
  CLMEM_ALLOC_HOST_PTR=CL_MEM_ALLOC_HOST_PTR,
  CLMEM_COPY_HOST_PTR=CL_MEM_COPY_HOST_PTR
  };
#endc
{-|
* 'CLMEM_READ_WRITE', This flag specifies that the memory object will be
read and written by a kernel. This is the default.

 * 'CLMEM_WRITE_ONLY', This flags specifies that the memory object will be
written but not read by a kernel. Reading from a buffer or image object created
with 'CLMEM_WRITE_ONLY' inside a kernel is undefined.

 * 'CLMEM_READ_ONLY', This flag specifies that the memory object is a read-only
memory object when used inside a kernel. Writing to a buffer or image object
created with 'CLMEM_READ_ONLY' inside a kernel is undefined.

 * 'CLMEM_USE_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
specified, it indicates that the application wants the OpenCL implementation to
use memory referenced by host_ptr as the storage bits for the memory
object. OpenCL implementations are allowed to cache the buffer contents pointed
to by host_ptr in device memory. This cached copy can be used when kernels are
executed on a device. The result of OpenCL commands that operate on multiple
buffer objects created with the same host_ptr or overlapping host regions is
considered to be undefined.

 * 'CLMEM_ALLOC_HOST_PTR', This flag specifies that the application wants the
OpenCL implementation to allocate memory from host accessible
memory. 'CLMEM_ALLOC_HOST_PTR' and 'CLMEM_USE_HOST_PTR' are mutually exclusive.

 * 'CLMEM_COPY_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
specified, it indicates that the application wants the OpenCL implementation to
allocate memory for the memory object and copy the data from memory referenced
by host_ptr. 'CLMEM_COPY_HOST_PTR' and 'CLMEM_USE_HOST_PTR' are mutually
exclusive. 'CLMEM_COPY_HOST_PTR' can be used with 'CLMEM_ALLOC_HOST_PTR' to
initialize the contents of the cl_mem object allocated using host-accessible
(e.g. PCIe) memory.
-}
{#enum CLMemFlag {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
getCLValue :: (Enum a, Integral b) => a -> b
getCLValue = fromIntegral . fromEnum

getDeviceMemCacheType :: CLDeviceMemCacheType_ -> Maybe CLDeviceMemCacheType
getDeviceMemCacheType = Just . toEnum . fromIntegral

getDeviceLocalMemType :: CLDeviceLocalMemType_ -> Maybe CLDeviceLocalMemType
getDeviceLocalMemType = Just . toEnum . fromIntegral

getCommandType :: CLCommandType_ -> Maybe CLCommandType
getCommandType = Just . toEnum . fromIntegral

getCommandExecutionStatus :: CLint -> Maybe CLCommandExecutionStatus
getCommandExecutionStatus n
  | n < 0 = Just CLEXEC_ERROR
  | otherwise = Just . toEnum . fromIntegral $ n

-- -----------------------------------------------------------------------------
binaryFlags :: (Ord b, Enum b, Bounded b) => b -> [b]
binaryFlags m = map toEnum . takeWhile (<= (fromEnum m)) $ [1 `shiftL` n | n <- [0..]]

testMask :: Bits b => b -> b -> Bool
testMask mask v = (v .&. mask) == v

bitmaskFromFlags :: (Enum a, Bits b) => [a] -> b
bitmaskFromFlags = foldl' (.|.) 0 . map (fromIntegral . fromEnum)

bitmaskToDeviceTypes :: CLDeviceType_ -> [CLDeviceType]
bitmaskToDeviceTypes mask = filter (testMask mask . fromIntegral . fromEnum) $ [CLDEVICE_TYPE_CPU,CLDEVICE_TYPE_GPU,CLDEVICE_TYPE_ACCELERATOR,CLDEVICE_TYPE_DEFAULT,CLDEVICE_TYPE_ALL]

bitmaskToCommandQueueProperties :: CLCommandQueueProperty_ -> [CLCommandQueueProperty]
bitmaskToCommandQueueProperties mask = filter (testMask mask . fromIntegral . fromEnum) $ binaryFlags maxBound

bitmaskToFPConfig :: CLDeviceFPConfig_ -> [CLDeviceFPConfig]
bitmaskToFPConfig mask = filter (testMask mask . fromIntegral . fromEnum) $ binaryFlags maxBound

bitmaskToExecCapability :: CLDeviceExecCapability_ -> [CLDeviceExecCapability]
bitmaskToExecCapability mask = filter (testMask mask . fromIntegral . fromEnum) $ binaryFlags maxBound

-- -----------------------------------------------------------------------------

-- -----------------------------------------------------------------------------
-- This file is part of Haskell-Opencl.

-- Haskell-Opencl is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.

-- Haskell-Opencl is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.

-- You should have received a copy of the GNU General Public License
-- along with Haskell-Opencl.  If not, see <http://www.gnu.org/licenses/>.
-- -----------------------------------------------------------------------------
module System.GPU.OpenCL.Types(
  -- * Symple CL Types
  CLbool, CLint, CLuint, CLulong, CLProgram, CLEvent, CLMem, CLPlatformID,
  CLDeviceID, CLContext, CLCommandQueue, CLPlatformInfo_, CLDeviceType_,
  CLDeviceInfo_, CLContextInfo_, CLContextProperty_, CLCommandQueueInfo_,
  CLEventInfo_, CLProfilingInfo_, CLCommandType_, CLCommandQueueProperty_,
  CLMemFlags_, CLImageFormat_p, CLMemObjectType_, CLMemInfo_, CLImageInfo_,
  -- * High Level Types
  CLError(..), ErrorCode(..), CLDeviceFPConfig(..), CLDeviceMemCacheType(..),
  CLDeviceExecCapability(..), CLDeviceLocalMemType(..), CLDeviceType(..),
  CLCommandQueueProperty(..), CLCommandType(..),  CLCommandExecutionStatus(..),
  CLProfilingInfo(..), CLImageFormat(..), CLPlatformInfo(..), CLMemFlag(..),
  -- * Functions
  clSuccess, wrapPError, getCLValue, getImageFormat,
  getDeviceLocalMemType, getDeviceMemCacheType,
  getCommandType, getCommandExecutionStatus, bitmaskToDeviceTypes,
  bitmaskFromFlags, bitmaskToCommandQueueProperties, bitmaskToFPConfig,
  bitmaskToExecCapability )
       where

-- -----------------------------------------------------------------------------
import Foreign
import Foreign.C.Types
import Data.List( foldl' )

#include <CL/cl.h>

-- -----------------------------------------------------------------------------

type CLPlatformID = {#type cl_platform_id#}
type CLDeviceID = {#type cl_device_id#}
type CLContext = {#type cl_context#}
type CLCommandQueue = {#type cl_command_queue#}
type CLMem = {#type cl_mem#}
type CLEvent = {#type cl_event#}
type CLProgram = {#type cl_program#}

type CLint = {#type cl_int#}
type CLuint = {#type cl_uint#}
type CLulong = {#type cl_ulong#}
type CLbool = {#type cl_bool#}

type CLPlatformInfo_ = {#type cl_platform_info#}
type CLDeviceType_ = {#type cl_device_type#}
type CLDeviceInfo_ = {#type cl_device_info#}
type CLDeviceFPConfig_ = {#type cl_device_fp_config#}
type CLDeviceMemCacheType_ = {#type cl_device_mem_cache_type#}
type CLDeviceLocalMemType_ = {#type cl_device_local_mem_type#}
type CLDeviceExecCapability_ = {#type cl_device_exec_capabilities#}
type CLContextInfo_ = {#type cl_context_info#}
type CLContextProperty_ = {#type cl_context_properties#}
type CLCommandQueueInfo_ = {#type cl_command_queue_info#}
type CLCommandQueueProperty_ = {#type cl_command_queue_properties#}
type CLEventInfo_ = {#type cl_event_info#}
type CLProfilingInfo_ = {#type cl_profiling_info#}
type CLCommandType_ = {#type cl_command_type#}
type CLMemFlags_ = {#type cl_mem_flags#}
type CLMemObjectType_ = {#type cl_mem_object_type#}
type CLMemInfo_ = {#type cl_mem_info#}
type CLImageInfo_ = {#type cl_image_info#}

{#pointer *cl_image_format as CLImageFormat_p#}

type CLImageChannelOrder_ = {#type cl_channel_order#}
type CLImageChannelDataType_ = {#type cl_channel_type#}

-- -----------------------------------------------------------------------------
newtype ErrorCode = ErrorCode CLint deriving( Eq )

clSuccess :: ErrorCode
clSuccess = ErrorCode (0)

-- -----------------------------------------------------------------------------
#c
enum CLError {
  CLBUILD_PROGRAM_FAILURE=CL_BUILD_PROGRAM_FAILURE,
  CLCOMPILER_NOT_AVAILABLE=CL_COMPILER_NOT_AVAILABLE,
  CLDEVICE_NOT_AVAILABLE=CL_DEVICE_NOT_AVAILABLE,
  CLDEVICE_NOT_FOUND=CL_DEVICE_NOT_FOUND,
  CLIMAGE_FORMAT_MISMATCH=CL_IMAGE_FORMAT_MISMATCH,
  CLIMAGE_FORMAT_NOT_SUPPORTED=CL_IMAGE_FORMAT_NOT_SUPPORTED,
  CLINVALID_ARG_INDEX=CL_INVALID_ARG_INDEX,
  CLINVALID_ARG_SIZE=CL_INVALID_ARG_SIZE,
  CLINVALID_ARG_VALUE=CL_INVALID_ARG_VALUE,
  CLINVALID_BINARY=CL_INVALID_BINARY,
  CLINVALID_BUFFER_SIZE=CL_INVALID_BUFFER_SIZE,
  CLINVALID_BUILD_OPTIONS=CL_INVALID_BUILD_OPTIONS,
  CLINVALID_COMMAND_QUEUE=CL_INVALID_COMMAND_QUEUE,
  CLINVALID_CONTEXT=CL_INVALID_CONTEXT,
  CLINVALID_DEVICE=CL_INVALID_DEVICE,
  CLINVALID_DEVICE_TYPE=CL_INVALID_DEVICE_TYPE,
  CLINVALID_EVENT=CL_INVALID_EVENT,
  CLINVALID_EVENT_WAIT_LIST=CL_INVALID_EVENT_WAIT_LIST,
  CLINVALID_GL_OBJECT=CL_INVALID_GL_OBJECT,
  CLINVALID_GLOBAL_OFFSET=CL_INVALID_GLOBAL_OFFSET,
  CLINVALID_HOST_PTR=CL_INVALID_HOST_PTR,
  CLINVALID_IMAGE_FORMAT_DESCRIPTOR=CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
  CLINVALID_IMAGE_SIZE=CL_INVALID_IMAGE_SIZE,
  CLINVALID_KERNEL_NAME=CL_INVALID_KERNEL_NAME,
  CLINVALID_KERNEL=CL_INVALID_KERNEL,
  CLINVALID_KERNEL_ARGS=CL_INVALID_KERNEL_ARGS,
  CLINVALID_KERNEL_DEFINITION=CL_INVALID_KERNEL_DEFINITION,
  CLINVALID_MEM_OBJECT=CL_INVALID_MEM_OBJECT,
  CLINVALID_OPERATION=CL_INVALID_OPERATION,
  CLINVALID_PLATFORM=CL_INVALID_PLATFORM,
  CLINVALID_PROGRAM=CL_INVALID_PROGRAM,
  CLINVALID_PROGRAM_EXECUTABLE=CL_INVALID_PROGRAM_EXECUTABLE,
  CLINVALID_QUEUE_PROPERTIES=CL_INVALID_QUEUE_PROPERTIES,
  CLINVALID_SAMPLER=CL_INVALID_SAMPLER,
  CLINVALID_VALUE=CL_INVALID_VALUE,
  CLINVALID_WORK_DIMENSION=CL_INVALID_WORK_DIMENSION,
  CLINVALID_WORK_GROUP_SIZE=CL_INVALID_WORK_GROUP_SIZE,
  CLINVALID_WORK_ITEM_SIZE=CL_INVALID_WORK_ITEM_SIZE,
  CLMAP_FAILURE=CL_MAP_FAILURE,
  CLMEM_OBJECT_ALLOCATION_FAILURE=CL_MEM_OBJECT_ALLOCATION_FAILURE,
  CLMEM_COPY_OVERLAP=CL_MEM_COPY_OVERLAP,
  CLOUT_OF_HOST_MEMORY=CL_OUT_OF_HOST_MEMORY,
  CLOUT_OF_RESOURCES=CL_OUT_OF_RESOURCES,
  CLPROFILING_INFO_NOT_AVAILABLE=CL_PROFILING_INFO_NOT_AVAILABLE,
  CLSUCCESS=CL_SUCCESS
  };
#endc

{-|
* 'CLBUILD_PROGRAM_FAILURE', Returned if there is a failure to build the
program executable.

 * 'CLCOMPILER_NOT_AVAILABLE', Returned if the parameter program is created with
'clCreateProgramWithSource' and a compiler is not available. For example
'clDeviceCompilerAvalaible' is set to 'False'.

 * 'CLDEVICE_NOT_AVAILABLE', Returned if the specified device is not currently
available.

 * 'CLDEVICE_NOT_FOUND', Returned if no OpenCL devices that match the specified
devices were found.

 * 'CLIMAGE_FORMAT_MISMATCH', Returned if the specified source and destination
images are not valid image objects.

 * 'CLIMAGE_FORMAT_NOT_SUPPORTED', Returned if the specified image format is not
supported.

 * 'CLINVALID_ARG_INDEX', Returned if an invalid argument index is specified.

 * 'CLINVALID_ARG_SIZE', Returned if argument size specified (arg_size) does not
match the size of the data type for an argument that is not a memory object, or
if the argument is a memory object and arg_size != sizeof(cl_mem) or if arg_size
is zero and the argument is declared with the __local qualifier or if the
argument is a sampler and arg_size != sizeof(cl_sampler).

 * 'CLINVALID_ARG_VALUE', Returned if the argument value specified is NULL for
an argument that is not declared with the __local qualifier or vice-versa.

 * 'CLINVALID_BINARY', Returned if the program binary is not a valid binary for
the specified device.

 * 'CLINVALID_BUFFER_SIZE', Returned if the value of the parameter size is 0 or
is greater than 'clDeviceMaxMemAllocSize' for all devices specified in the
parameter context.

 * 'CLINVALID_BUILD_OPTIONS', Returned if the specified build options are
invalid.

 * 'CLINVALID_COMMAND_QUEUE', Returned if the specified command-queue is not a
valid command-queue.

 * 'CLINVALID_CONTEXT', Returned if the specified context is not a valid OpenCL
context, or the context associated with certain parameters are not the same.

 * 'CLINVALID_DEVICE', Returned if the device or devices specified are not
valid.

 * 'CLINVALID_DEVICE_TYPE', Returned if device type specified is not valid.

 * 'CLINVALID_EVENT', Returned if the event objects specified are not valid.

 * 'CLINVALID_EVENT_WAIT_LIST', Returned if event_wait_list is NULL and
num_events_in_wait_list > 0, or event_wait_list_list is not NULL and
num_events_in_wait_list is 0, or specified event objects are not valid events.

 * 'CLINVALID_GL_OBJECT', Returned if obj is not a vaild GL object or is a GL
object but does not have an existing data store.

 * 'CLINVALID_GLOBAL_OFFSET', Returned if global_work_offset is not NULL.

 * 'CLINVALID_HOST_PTR', Returned if host_ptr is NULL and 'CLMEM_USE_HOST_PTR'
or 'CLMEM_COPY_HOST_PTR' are set in flags or if host_ptr is not NULL but
'CLMEM_COPY_HOST_PTR' or 'CLMEM_USE_HOST_PTR' are not set in flags.

 * 'CLINVALID_IMAGE_FORMAT_DESCRIPTOR', Returned if the image format specified
is not valid or is NULL or does not map to a supported OpenCL image format.

 * 'CLINVALID_IMAGE_SIZE', Returned if the specified image width or height are
invalid or if the image row pitch and image slice pitch do not follow the rules.

 * 'CLINVALID_KERNEL_NAME', Returned if the specified kernel name is not found
in program.

 * 'CLINVALID_KERNEL', Returned if the specified kernel is not a valid kernel
object.

 * 'CLINVALID_KERNEL_ARGS', Returned if the kernel argument values have not been
specified.

 * 'CLINVALID_KERNEL_DEFINITION', Returned if the function definition for
__kernel function given by kernel_name such as the number of arguments, the
argument types are not the same for all devices for which the program executable
has been built.

 * 'CLINVALID_MEM_OBJECT', Returned if a parameter is not a valid memory, image,
or buffer object.

 * 'CLINVALID_OPERATION', Returned if there are no devices in context that
support images. Returned if the build of a program executable for any of the
devices specified by a previous call to 'clBuildProgram' for program has not
completed, or if there are kernel objects attached to program. Returned by
'clEnqueueNativeKernel' if the specified device cannot execute the native
kernel.

 * 'CLINVALID_PLATFORM', Returned if the specified platform is not a valid
platform, or no platform could be selected, or if platform value specified in
properties is not a valid platform.

 * 'CLINVALID_PROGRAM', Returned if the specified program is not a valid program
object.

 * 'CLINVALID_PROGRAM_EXECUTABLE', Returned if there is no successfully built
executable for program, or if there is no device in program. Returned if there
is no successfully built program executable available for device associated with
command_queue.

 * 'CLINVALID_QUEUE_PROPERTIES', Returned if specified properties are valid but
are not supported by the device.

 * 'CLINVALID_SAMPLER', Returned if the specified sampler is not a valid sampler
object, or for an argument declared to be of type sampler_t when the specified
arg_value is not a valid sampler object.

 * 'CLINVALID_VALUE', Returned if a parameter is not an expected value.

 * 'CLINVALID_WORK_DIMENSION', Returned if work_dim is not a valid value.

 * 'CLINVALID_WORK_GROUP_SIZE', Returned if local_work_size is specified and
number of workitems specified by global_work_size is not evenly divisible by
size of work-group given by local_work_size or does not match the work-group
size specified for kernel using the __attribute__((reqd_work_group_size(X, Y,
Z))) qualifier in program source.

 * 'CLINVALID_WORK_ITEM_SIZE', Returned if the number of work-items specified in
any of local_work_size... [0]... local_work_size[work_dim - 1] is greater than
the corresponding values specified by 'clDeviceMaxWorkItemSizes'.

 * 'CLMAP_FAILURE', Returned by if there is a failure to map the requested
region into the host address space. This error cannot occur for buffer objects
created with 'CLMEM_USE_HOST_PTR' or 'CLMEM_ALLOC_HOST_PTR'.

 * 'CLMEM_OBJECT_ALLOCATION_FAILURE', Returned if there is a failure to allocate
memory for data store associated with image or buffer objects specified as
arguments to kernel.

 * 'CLMEM_COPY_OVERLAP', Returned if the source and destination images are the
same image (or the source and destination buffers are the same buffer), and the
source and destination regions overlap.

 * 'CL_OUT_OF_HOST_MEMORY', Returned in the event of a failure to allocate
resources required by the OpenCL implementation on the host.

 * 'CLOUT_OF_RESOURCES', Returned in the event of a failure to queue the
execution instance of kernel on the command-queue because of insufficient
resources needed to execute the kernel.

 * 'CLPROFILING_INFO_NOT_AVAILABLE', Returned if the 'CLQUEUE_PROFILING_ENABLE'
flag is not set for the command-queue and the profiling information is currently
not available (because the command identified by event has not completed).

 * 'CLSUCCESS', Indicates that the function executed successfully.
-}
{#enum CLError {} deriving( Show, Eq ) #}

wrapPError :: (Ptr CLint -> IO a) -> IO (Either CLError a)
wrapPError f = alloca $ \perr -> do
  v <- f perr
  errcode <- peek perr >>= return . toEnum . fromIntegral
  if errcode == CLSUCCESS
    then return $ Right v
    else return $ Left errcode

-- -----------------------------------------------------------------------------
#c
enum CLPlatformInfo {
CLPLATFORM_PROFILE=CL_PLATFORM_PROFILE,
CLPLATFORM_VERSION=CL_PLATFORM_VERSION,
CLPLATFORM_NAME=CL_PLATFORM_NAME,
CLPLATFORM_VENDOR=CL_PLATFORM_VENDOR,
CLPLATFORM_EXTENSIONS=CL_PLATFORM_EXTENSIONS
  };
#endc

{-|
 * 'CLPLATFORM_PROFILE', OpenCL profile string. Returns the profile name
supported by the implementation. The profile name returned can be one of the
following strings:

 [@FULL_PROFILE@] If the implementation supports the OpenCL specification
(functionality defined as part of the core specification and does not require
any extensions to be supported).

 [@EMBEDDED_PROFILE@] If the implementation supports the OpenCL embedded
profile. The embedded profile is  defined to be a subset for each version of
OpenCL.

 * 'CLPLATFORM_VERSION', OpenCL version string. Returns the OpenCL version
supported by the implementation. This version string has the following format:
/OpenCL major_version.minor_version platform-specific information/ The
/major_version.minor_version/ value returned will be 1.0.

 * 'CLPLATFORM_NAME', Platform name string.

 * 'CLPLATFORM_VENDOR', Platform vendor string.

 * 'CLPLATFORM_EXTENSIONS', Returns a space-separated list of extension names
(the extension names themselves do not contain any spaces) supported by the
platform. Extensions defined here must be supported by all devices associated
with this platform.
-}
{#enum CLPlatformInfo {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
#c
enum CLDeviceType {
CLDEVICE_TYPE_CPU=CL_DEVICE_TYPE_CPU,
CLDEVICE_TYPE_GPU=CL_DEVICE_TYPE_GPU,
CLDEVICE_TYPE_ACCELERATOR=CL_DEVICE_TYPE_ACCELERATOR,
CLDEVICE_TYPE_DEFAULT=CL_DEVICE_TYPE_DEFAULT,
CLDEVICE_TYPE_ALL=CL_DEVICE_TYPE_ALL
  };
#endc

{-|
 * 'CLDEVICE_TYPE_CPU', An OpenCL device that is the host processor. The host
processor runs the OpenCL implementations and is a single or multi-core CPU.

 * 'CLDEVICE_TYPE_GPU', An OpenCL device that is a GPU. By this we mean that the
device can also be used to accelerate a 3D API such as OpenGL or DirectX.

 * 'CLDEVICE_TYPE_ACCELERATOR', Dedicated OpenCL accelerators (for example the
IBM CELL Blade). These devices communicate with the host processor using a
peripheral interconnect such as PCIe.

 * 'CLDEVICE_TYPE_DEFAULT', The default OpenCL device in the system.

 * 'CLDEVICE_TYPE_ALL', All OpenCL devices available in the system.
-}
{#enum CLDeviceType {} deriving( Show ) #}

#c
enum CLCommandQueueProperty {
  CLQUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE=CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
  CLQUEUE_PROFILING_ENABLE=CL_QUEUE_PROFILING_ENABLE
  };
#endc

{-|
 * 'CLQUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE', Determines whether the commands
queued in the command-queue are executed in-order or out-of-order. If set, the
commands in the command-queue are executed out-of-order. Otherwise, commands are
executed in-order.

 * 'CLQUEUE_PROFILING_ENABLE', Enable or disable profiling of commands in the
command-queue. If set, the profiling of commands is enabled. Otherwise profiling
of commands is disabled. See 'clGetEventProfilingInfo' for more information.
-}
{#enum CLCommandQueueProperty {} deriving( Show, Bounded, Eq, Ord ) #}

#c
enum CLDeviceFPConfig {
  CLFP_DENORM=CL_FP_DENORM, CLFP_INF_NAN=CL_FP_INF_NAN,
  CLFP_ROUND_TO_NEAREST=CL_FP_ROUND_TO_NEAREST,
  CLFP_ROUND_TO_ZERO=CL_FP_ROUND_TO_ZERO,
  CLFP_ROUND_TO_INF=CL_FP_ROUND_TO_INF, CLFP_FMA=CL_FP_FMA,
  };
#endc

{-|
 * 'CLFP_DENORM', denorms are supported.

 * 'CLFP_INF_NAN', INF and NaNs are supported.

 * 'CLFP_ROUND_TO_NEAREST', round to nearest even rounding mode supported.

 * 'CLFP_ROUND_TO_ZERO', round to zero rounding mode supported.

 * 'CLFP_ROUND_TO_INF', round to +ve and -ve infinity rounding modes supported.

 * 'CLFP_FMA', IEEE754-2008 fused multiply-add is supported.
-}
{#enum CLDeviceFPConfig {} deriving( Show, Bounded, Eq, Ord ) #}

#c
enum CLDeviceExecCapability {
  CLEXEC_KERNEL=CL_EXEC_KERNEL,
  CLEXEC_NATIVE_KERNEL=CL_EXEC_NATIVE_KERNEL
  };
#endc

{-|
 * 'CLEXEC_KERNEL', The OpenCL device can execute OpenCL kernels.

 * 'CLEXEC_NATIVE_KERNEL', The OpenCL device can execute native kernels.
-}
{#enum CLDeviceExecCapability {} deriving( Show, Bounded, Eq, Ord ) #}

#c
enum CLDeviceMemCacheType {
  CLNONE=CL_NONE,CLREAD_ONLY_CACHE=CL_READ_ONLY_CACHE,
  CLREAD_WRITE_CACHE=CL_READ_WRITE_CACHE
  };
#endc

{#enum CLDeviceMemCacheType {} deriving( Show ) #}

#c
enum CLDeviceLocalMemType {
  CLLOCAL=CL_LOCAL, CLGLOBAL=CL_GLOBAL
  };
#endc

{#enum CLDeviceLocalMemType {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
#c
enum CLCommandType {
  CLCOMMAND_NDRANGE_KERNEL=CL_COMMAND_NDRANGE_KERNEL,
  CLCOMMAND_TASK=CL_COMMAND_TASK ,
  CLCOMMAND_NATIVE_KERNEL=CL_COMMAND_NATIVE_KERNEL,
  CLCOMMAND_READ_BUFFER=CL_COMMAND_READ_BUFFER,
  CLCOMMAND_WRITE_BUFFER=CL_COMMAND_WRITE_BUFFER,
  CLCOMMAND_COPY_BUFFER=CL_COMMAND_COPY_BUFFER,
  CLCOMMAND_READ_IMAGE=CL_COMMAND_READ_IMAGE,
  CLCOMMAND_WRITE_IMAGE=CL_COMMAND_WRITE_IMAGE,
  CLCOMMAND_COPY_IMAGE=CL_COMMAND_COPY_IMAGE,
  CLCOMMAND_COPY_BUFFER_TO_IMAGE=CL_COMMAND_COPY_BUFFER_TO_IMAGE,
  CLCOMMAND_COPY_IMAGE_TO_BUFFER=CL_COMMAND_COPY_IMAGE_TO_BUFFER,
  CLCOMMAND_MAP_BUFFER=CL_COMMAND_MAP_BUFFER,
  CLCOMMAND_MAP_IMAGE=CL_COMMAND_MAP_IMAGE,
  CLCOMMAND_UNMAP_MEM_OBJECT=CL_COMMAND_UNMAP_MEM_OBJECT,
  CLCOMMAND_MARKER=CL_COMMAND_MARKER,
  CLCOMMAND_ACQUIRE_GL_OBJECTS=CL_COMMAND_ACQUIRE_GL_OBJECTS,
  CLCOMMAND_RELEASE_GL_OBJECTS=CL_COMMAND_RELEASE_GL_OBJECTS
  };
#endc

-- | Command associated with an event.
{#enum CLCommandType {} deriving( Show ) #}

#c
enum CLCommandExecutionStatus {
  CLQUEUED=CL_QUEUED, CLSUBMITTED=CL_SUBMITTED, CLRUNNING=CL_RUNNING,
  CLCOMPLETE=CL_COMPLETE, CLEXEC_ERROR= -1
  };
#endc

{-|
 * 'CLQUEUED', command has been enqueued in the command-queue.

 * 'CLSUBMITTED', enqueued command has been submitted by the host to the
device associated with the command-queue.

 * 'CLRUNNING', device is currently executing this command.

 * 'CLCOMPLETE', the command has completed.

 * 'CLEXEC_ERROR', command was abnormally terminated.
-}
{#enum CLCommandExecutionStatus {} deriving( Show ) #}

#c
enum CLProfilingInfo {
  CLPROFILING_COMMAND_QUEUED=CL_PROFILING_COMMAND_QUEUED,
  CLPROFILING_COMMAND_SUBMIT=CL_PROFILING_COMMAND_SUBMIT,
  CLPROFILING_COMMAND_START=CL_PROFILING_COMMAND_START,
  CLPROFILING_COMMAND_END=CL_PROFILING_COMMAND_END
  };
#endc

{-| Specifies the profiling data.

 * 'CLPROFILING_COMMAND_QUEUED', A 64-bit value that describes the current
device time counter in nanoseconds when the command identified by event is
enqueued in a command-queue by the host.

 * 'CLPROFILING_COMMAND_SUBMIT', A 64-bit value that describes the current
device time counter in nanoseconds when the command identified by event that has
been enqueued is submitted by the host to the device associated with the
commandqueue.

 * 'CLPROFILING_COMMAND_START',	 A 64-bit value that describes the current
device time counter in nanoseconds when the command identified by event starts
execution on the device.

 * 'CLPROFILING_COMMAND_END', A 64-bit value that describes the current device
time counter in nanoseconds when the command identified by event has finished
execution on the device.
-}
{#enum CLProfilingInfo {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
#c
enum CLMemFlag {
  CLMEM_READ_WRITE=CL_MEM_READ_WRITE,
  CLMEM_WRITE_ONLY=CL_MEM_WRITE_ONLY,
  CLMEM_READ_ONLY=CL_MEM_READ_ONLY,
  CLMEM_USE_HOST_PTR=CL_MEM_USE_HOST_PTR,
  CLMEM_ALLOC_HOST_PTR=CL_MEM_ALLOC_HOST_PTR,
  CLMEM_COPY_HOST_PTR=CL_MEM_COPY_HOST_PTR
  };
#endc
{-|
* 'CLMEM_READ_WRITE', This flag specifies that the memory object will be
read and written by a kernel. This is the default.

 * 'CLMEM_WRITE_ONLY', This flags specifies that the memory object will be
written but not read by a kernel. Reading from a buffer or image object created
with 'CLMEM_WRITE_ONLY' inside a kernel is undefined.

 * 'CLMEM_READ_ONLY', This flag specifies that the memory object is a read-only
memory object when used inside a kernel. Writing to a buffer or image object
created with 'CLMEM_READ_ONLY' inside a kernel is undefined.

 * 'CLMEM_USE_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
specified, it indicates that the application wants the OpenCL implementation to
use memory referenced by host_ptr as the storage bits for the memory
object. OpenCL implementations are allowed to cache the buffer contents pointed
to by host_ptr in device memory. This cached copy can be used when kernels are
executed on a device. The result of OpenCL commands that operate on multiple
buffer objects created with the same host_ptr or overlapping host regions is
considered to be undefined.

 * 'CLMEM_ALLOC_HOST_PTR', This flag specifies that the application wants the
OpenCL implementation to allocate memory from host accessible
memory. 'CLMEM_ALLOC_HOST_PTR' and 'CLMEM_USE_HOST_PTR' are mutually exclusive.

 * 'CLMEM_COPY_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
specified, it indicates that the application wants the OpenCL implementation to
allocate memory for the memory object and copy the data from memory referenced
by host_ptr. 'CLMEM_COPY_HOST_PTR' and 'CLMEM_USE_HOST_PTR' are mutually
exclusive. 'CLMEM_COPY_HOST_PTR' can be used with 'CLMEM_ALLOC_HOST_PTR' to
initialize the contents of the cl_mem object allocated using host-accessible
(e.g. PCIe) memory.
-}
{#enum CLMemFlag {} deriving( Show ) #}

-- -----------------------------------------------------------------------------
--getImageChannelOrder :: CLImageFormat_p -> IO CLImageChannelOrder_
--getImageChannelOrder = {#get cl_image_format->image_channel_order#}

--getImageChannelDataType :: CLImageFormat_p -> IO CLImageChannelDataType_
--getImageChannelDataType = {#get cl_image_format->image_channel_data_type#}

data CLImageFormat = CLImageFormat {
  image_channel_order :: CLImageChannelOrder_,
  image_channel_data_type :: CLImageChannelDataType_
  } deriving( Show )

getImageFormat :: CLImageFormat_p -> IO CLImageFormat
getImageFormat p = do
--  order <- getImageChannelOrder p
--  datatype <- getImageChannelDataType p
--  return $ CLImageFormat order datatype
  return $ CLImageFormat 0 0

getCLValue :: (Enum a, Integral b) => a -> b
getCLValue = fromIntegral . fromEnum

getDeviceMemCacheType :: CLDeviceMemCacheType_ -> Maybe CLDeviceMemCacheType
getDeviceMemCacheType = Just . toEnum . fromIntegral

getDeviceLocalMemType :: CLDeviceLocalMemType_ -> Maybe CLDeviceLocalMemType
getDeviceLocalMemType = Just . toEnum . fromIntegral

getCommandType :: CLCommandType_ -> Maybe CLCommandType
getCommandType = Just . toEnum . fromIntegral

getCommandExecutionStatus :: CLint -> Maybe CLCommandExecutionStatus
getCommandExecutionStatus n
  | n < 0 = Just CLEXEC_ERROR
  | otherwise = Just . toEnum . fromIntegral $ n

-- -----------------------------------------------------------------------------
binaryFlags :: (Ord b, Enum b, Bounded b) => b -> [b]
binaryFlags m = map toEnum . takeWhile (<= (fromEnum m)) $ [1 `shiftL` n | n <- [0..]]

testMask :: Bits b => b -> b -> Bool
testMask mask v = (v .&. mask) == v

bitmaskFromFlags :: (Enum a, Bits b) => [a] -> b
bitmaskFromFlags = foldl' (.|.) 0 . map (fromIntegral . fromEnum)

bitmaskToDeviceTypes :: CLDeviceType_ -> [CLDeviceType]
bitmaskToDeviceTypes mask = filter (testMask mask . fromIntegral . fromEnum) $ [CLDEVICE_TYPE_CPU,CLDEVICE_TYPE_GPU,CLDEVICE_TYPE_ACCELERATOR,CLDEVICE_TYPE_DEFAULT,CLDEVICE_TYPE_ALL]

bitmaskToCommandQueueProperties :: CLCommandQueueProperty_ -> [CLCommandQueueProperty]
bitmaskToCommandQueueProperties mask = filter (testMask mask . fromIntegral . fromEnum) $ binaryFlags maxBound

bitmaskToFPConfig :: CLDeviceFPConfig_ -> [CLDeviceFPConfig]
bitmaskToFPConfig mask = filter (testMask mask . fromIntegral . fromEnum) $ binaryFlags maxBound

bitmaskToExecCapability :: CLDeviceExecCapability_ -> [CLDeviceExecCapability]
bitmaskToExecCapability mask = filter (testMask mask . fromIntegral . fromEnum) $ binaryFlags maxBound

-- -----------------------------------------------------------------------------


lcb_store3 callback

lcb_store3 callback

{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}

module Couchbase.Raw where

import qualified Data.ByteString as B
import Foreign
import Foreign.C.String
import Foreign.C.Types

#define __int128 int

#include <libcouchbase/couchbase.h>

{# context lib="libcouchbase" #}

{# enum lcb_type_t as LcbType {underscoreToCase} deriving (Eq, Show) #}

{# pointer *lcb_create_st as LcbCreateSt #}

{# pointer lcb_t as Lcb foreign finalizer lcb_destroy newtype #}

{# enum lcb_error_t as LcbError {underscoreToCase} deriving (Eq, Show) #}

{# fun lcb_get_errtype as ^ {`LcbError'} -> `Int' #}

{# fun lcb_strerror as ^ {`Lcb', `LcbError'} -> `String' #}

-- lcb_errmap_default
-- lcb_set_errmap_callback

newLcb :: Ptr Lcb -> IO Lcb
newLcb ptr =
  Lcb <$> newForeignPtr lcb_destroy ptr

peekLcb :: Ptr (Ptr Lcb) -> IO Lcb
peekLcb ptr =
  peek ptr >>= newLcb

{# fun lcb_create as lcbCreateRaw {alloca- `Lcb' peekLcb*, `LcbCreateSt'} -> `LcbError' #}

data ConnectionParams =
  ConnectionParams
  { connectionString :: String
  , password :: Maybe String
  , lcbType :: LcbType
  } deriving (Show)

lcbCreate :: ConnectionParams -> IO (LcbError, Lcb)
lcbCreate params = do
  allocaBytes {# sizeof lcb_create_st #} $ \st -> do
    fillBytes st 0 {# sizeof lcb_create_st #}
    {# set lcb_create_st.version #} st 3
    {# set lcb_create_st.v.v3.type #} st $ fromIntegral $ fromEnum $ lcbType params
    withCString (connectionString params) $ \connstr -> do
      {# set lcb_create_st.v.v3.connstr #} st connstr
      case password params of
        Just pwd ->
          withCString pwd $ \passwd -> do
            {# set lcb_create_st.v.v3.passwd #} st passwd
            lcbCreateRaw st
        Nothing ->
          lcbCreateRaw st

{# fun lcb_connect as ^ {`Lcb'} -> `LcbError' #}

-- lcb_set_bootstrap_callback

{# fun lcb_get_bootstrap_status as ^ {`Lcb'} -> `LcbError' #}

{# enum lcb_CALLBACKTYPE as LcbCallbackType {underscoreToCase} deriving (Eq, Show) #}

type LcbCallbackRaw =
  Ptr Lcb -> CInt -> Ptr () -> IO ()

foreign import ccall "wrapper"
  mkLcbCallbackFunPtr :: LcbCallbackRaw -> IO (FunPtr LcbCallbackRaw)

type LcbCallback =
  LcbCallbackType -> Ptr () -> IO ()

withLcbCallback :: LcbCallback -> (FunPtr LcbCallbackRaw -> IO a) -> IO a
withLcbCallback callback f =
  mkLcbCallbackFunPtr (\ _ cb p -> callback (toEnum (fromIntegral cb)) p) >>= f

type OldCallbackPtr = FunPtr LcbCallbackRaw

{# fun lcb_install_callback3 as ^ {`Lcb', `LcbCallbackType', withLcbCallback* `LcbCallback'} -> `OldCallbackPtr' id #}

-- lcb_get_callback3
-- lcb_strcbtype
-- lcb_get3
-- lcb_rget3

{# enum lcb_KVBUFTYPE as LcbKvBufType {underscoreToCase} deriving (Eq, Show) #}

_lcbKreqSimple :: Ptr () -> B.ByteString -> IO ()
_lcbKreqSimple p bs =
  B.useAsCStringLen bs $ \(pv, len) -> do
    {# set lcb_KEYBUF.type #} p $ fromIntegral $ fromEnum LcbKvCopy
    {# set lcb_KEYBUF.contig.bytes #} p $ castPtr pv
    {# set lcb_KEYBUF.contig.nbytes #} p $ fromIntegral len

_lcbCmdStoreSetKey :: Ptr () -> B.ByteString -> IO ()
_lcbCmdStoreSetKey p bs =
  _lcbKreqSimple (plusPtr p {# offsetof lcb_CMDSTORE.key #}) bs

_lcbCmdStoreSetValue :: Ptr () -> B.ByteString -> IO ()
_lcbCmdStoreSetValue p bs =
  B.useAsCStringLen bs $ \(pv, len) -> do
    {# set lcb_CMDSTORE.value.vtype #} p $ fromIntegral $ fromEnum LcbKvCopy
    {# set lcb_CMDSTORE.value.u_buf.contig.bytes #} p $ castPtr pv
    {# set lcb_CMDSTORE.value.u_buf.contig.nbytes #} p $ fromIntegral len

{# enum lcb_storage_t as LcbStorage {underscoreToCase} deriving (Eq, Show) #}

data LcbCmdStore =
  LcbCmdStore
  { operation :: LcbStorage
  , key :: B.ByteString
  , value :: B.ByteString
  } deriving (Show)

{# fun lcb_store3 as lcbStore3Raw {`Lcb', `Ptr ()', `Ptr ()'} -> `LcbError' #}

type LcbCookie = Ptr ()

lcbStore3 :: Lcb -> LcbCookie -> LcbCmdStore -> IO LcbError
lcbStore3 lcb cookie cmd =
  allocaBytes {# sizeof lcb_CMDSTORE #} $ \st -> do
    fillBytes st 0 {# sizeof lcb_CMDSTORE #}
    {# set lcb_CMDSTORE.operation #} st $ fromIntegral $ fromEnum $ operation cmd
    _lcbCmdStoreSetKey st $ key cmd
    _lcbCmdStoreSetValue st $ value cmd
    lcbStore3Raw lcb cookie st

{# pointer *lcb_RESPSTORE as LcbRespStorePtr #}

lcbRespStoreGetOp :: LcbRespStorePtr -> IO LcbStorage
lcbRespStoreGetOp p = (toEnum . fromIntegral) <$> {# get lcb_RESPSTORE.op #} p

_lcbRespBaseGetCookie :: Ptr () -> IO LcbCookie
_lcbRespBaseGetCookie p = {# get lcb_RESPBASE.cookie #} p

lcbRespStoreGetCookie :: LcbRespStorePtr -> IO LcbCookie
lcbRespStoreGetCookie = _lcbRespBaseGetCookie . castPtr

_lcbRespBaseGetKey :: Ptr () -> IO B.ByteString
_lcbRespBaseGetKey p = do
  pv <- {# get lcb_RESPBASE.key #} p
  len <- {# get lcb_RESPBASE.nkey #} p
  B.packCStringLen (castPtr pv, fromIntegral len)

lcbRespStoreGetKey :: LcbRespStorePtr -> IO B.ByteString
lcbRespStoreGetKey = _lcbRespBaseGetKey . castPtr

_lcbRespBaseGetStatus :: Ptr () -> IO LcbError
_lcbRespBaseGetStatus p = (toEnum . fromIntegral) <$> {# get lcb_RESPBASE.rc #} p

lcbRespStoreGetStatus :: LcbRespStorePtr -> IO LcbError
lcbRespStoreGetStatus = _lcbRespBaseGetStatus . castPtr

type LcbCas = {# type lcb_CAS #}

_lcbRespBaseGetCas :: Ptr () -> IO LcbCas
_lcbRespBaseGetCas p = {# get lcb_RESPBASE.cas #} p

lcbRespStoreGetCas :: LcbRespStorePtr -> IO LcbCas
lcbRespStoreGetCas = _lcbRespBaseGetCas . castPtr

type LcbRespStoreCallback =
  LcbRespStorePtr -> IO ()

lcbInstallRespStoreCallback :: Lcb -> LcbRespStoreCallback -> IO OldCallbackPtr
lcbInstallRespStoreCallback lcb callback =
  lcbInstallCallback3 lcb LcbCallbackStore $ \ _ p -> callback (castPtr p)

-- lcb_remove3
-- lcb_endure3_ctxnew
-- lcb_storedur3
-- lcb_durability_validate
-- lcb_observe3_ctxnew
-- lcb_observe_seqno3
-- lcb_resp_get_mutation_token
-- lcb_get_mutation_token
-- lcb_counter3
-- lcb_unlock3
-- lcb_touch3
-- lcb_stats3
-- lcb_server_versions3
-- lcb_server_verbosity3
-- lcb_cbflush3
-- lcb_flush3
-- lcb_http3
-- lcb_cancel_http_request
-- lcb_set_cookie
-- lcb_get_cookie

{# fun lcb_wait as ^ {`Lcb'} -> `LcbError' #}

-- lcb_tick_nowait

{# enum lcb_WAITFLAGS as LcbWaitFlags {underscoreToCase} deriving (Eq, Show) #}

{# fun lcb_wait3 as ^ {`Lcb', `LcbWaitFlags'} -> `()' #}

-- lcb_breakout
-- lcb_is_waiting
-- lcb_refresh_config
-- lcb_sched_enter
-- lcb_sched_leave
-- lcb_sched_fail
-- lcb_sched_flush

{# fun lcb_destroy as ^ {`Lcb'} -> `()' #}

-- lcb_set_destroy_callback
-- lcb_destroy_async
-- lcb_get_node
-- lcb_get_keynode
-- lcb_get_num_replicas
-- lcb_get_num_nodes
-- lcb_get_server_list
-- lcb_dump
-- lcb_cntl
-- lcb_cntl_string
-- lcb_cntl_setu32
-- lcb_cntl_getu32
-- lcb_cntl_exists
-- lcb_enable_timings
-- lcb_disable_timings
-- lcb_get_timings
-- lcb_get_version
-- lcb_supports_feature
-- lcb_mem_alloc
-- lcb_mem_free
-- lcb_run_loop
-- lcb_stop_loop
-- lcb_nstime
-- lcb_histogram_create
-- lcb_histogram_destroy
-- lcb_histogram_record
-- lcb_histogram_read
-- lcb_histogram_print
-- lcb_subdoc3
-- lcb_sdresult_next

{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}

module Couchbase.Raw where

import qualified Data.ByteString as B
import Foreign
import Foreign.C.String
import Foreign.C.Types

#define __int128 int

#include <libcouchbase/couchbase.h>

{# context lib="libcouchbase" #}

{# enum lcb_type_t as LcbType {underscoreToCase} deriving (Eq, Show) #}

{# pointer *lcb_create_st as LcbCreateSt #}

{# pointer lcb_t as Lcb foreign finalizer lcb_destroy newtype #}

{# enum lcb_error_t as LcbError {underscoreToCase} deriving (Eq, Show) #}

{# fun lcb_get_errtype as ^ {`LcbError'} -> `Int' #}

{# fun lcb_strerror as ^ {`Lcb', `LcbError'} -> `String' #}

-- lcb_errmap_default
-- lcb_set_errmap_callback

newLcb :: Ptr Lcb -> IO Lcb
newLcb ptr =
  Lcb <$> newForeignPtr lcb_destroy ptr

peekLcb :: Ptr (Ptr Lcb) -> IO Lcb
peekLcb ptr =
  peek ptr >>= newLcb

{# fun lcb_create as lcbCreateRaw {alloca- `Lcb' peekLcb*, `LcbCreateSt'} -> `LcbError' #}

data ConnectionParams =
  ConnectionParams
  { connectionString :: String
  , password :: Maybe String
  , lcbType :: LcbType
  } deriving (Show)

lcbCreate :: ConnectionParams -> IO (LcbError, Lcb)
lcbCreate params = do
  allocaBytes {# sizeof lcb_create_st #} $ \st -> do
    fillBytes st 0 {# sizeof lcb_create_st #}
    {# set lcb_create_st.version #} st 3
    {# set lcb_create_st.v.v3.type #} st $ fromIntegral $ fromEnum $ lcbType params
    withCString (connectionString params) $ \connstr -> do
      {# set lcb_create_st.v.v3.connstr #} st connstr
      case password params of
        Just pwd ->
          withCString pwd $ \passwd -> do
            {# set lcb_create_st.v.v3.passwd #} st passwd
            lcbCreateRaw st
        Nothing ->
          lcbCreateRaw st

{# fun lcb_connect as ^ {`Lcb'} -> `LcbError' #}

-- lcb_set_bootstrap_callback

{# fun lcb_get_bootstrap_status as ^ {`Lcb'} -> `LcbError' #}

-- lcb_install_callback3
-- lcb_get_callback3
-- lcb_strcbtype
-- lcb_get3
-- lcb_rget3

{# enum lcb_KVBUFTYPE as LcbKvBufType {underscoreToCase} deriving (Eq, Show) #}

_lcbKreqSimple :: Ptr () -> B.ByteString -> IO ()
_lcbKreqSimple p bs =
  B.useAsCStringLen bs $ \(pv, len) -> do
    {# set lcb_KEYBUF.type #} p $ fromIntegral $ fromEnum LcbKvCopy
    {# set lcb_KEYBUF.contig.bytes #} p $ castPtr pv
    {# set lcb_KEYBUF.contig.nbytes #} p $ fromIntegral len

_lcbCmdStoreSetKey :: Ptr () -> B.ByteString -> IO ()
_lcbCmdStoreSetKey p bs =
  _lcbKreqSimple (plusPtr p {# offsetof lcb_CMDSTORE.key #}) bs

_lcbCmdStoreSetValue :: Ptr () -> B.ByteString -> IO ()
_lcbCmdStoreSetValue p bs =
  B.useAsCStringLen bs $ \(pv, len) -> do
    {# set lcb_CMDSTORE.value.vtype #} p $ fromIntegral $ fromEnum LcbKvCopy
    {# set lcb_CMDSTORE.value.u_buf.contig.bytes #} p $ castPtr pv
    {# set lcb_CMDSTORE.value.u_buf.contig.nbytes #} p $ fromIntegral len

{# enum lcb_storage_t as LcbStorage {underscoreToCase} deriving (Eq, Show) #}

data LcbCmdStore =
  LcbCmdStore
  { operation :: LcbStorage
  , key :: B.ByteString
  , value :: B.ByteString
  } deriving (Show)

{# fun lcb_store3 as lcbStore3Raw {`Lcb', `Ptr ()', `Ptr ()'} -> `LcbError' #}

type LcbCookie = Ptr ()

lcbStore3 :: Lcb -> LcbCookie -> LcbCmdStore -> IO LcbError
lcbStore3 lcb cookie cmd =
  allocaBytes {# sizeof lcb_CMDSTORE #} $ \st -> do
    fillBytes st 0 {# sizeof lcb_CMDSTORE #}
    {# set lcb_CMDSTORE.operation #} st $ fromIntegral $ fromEnum $ operation cmd
    _lcbCmdStoreSetKey st $ key cmd
    _lcbCmdStoreSetValue st $ value cmd
    lcbStore3Raw lcb cookie st

-- lcb_remove3
-- lcb_endure3_ctxnew
-- lcb_storedur3
-- lcb_durability_validate
-- lcb_observe3_ctxnew
-- lcb_observe_seqno3
-- lcb_resp_get_mutation_token
-- lcb_get_mutation_token
-- lcb_counter3
-- lcb_unlock3
-- lcb_touch3
-- lcb_stats3
-- lcb_server_versions3
-- lcb_server_verbosity3
-- lcb_cbflush3
-- lcb_flush3
-- lcb_http3
-- lcb_cancel_http_request
-- lcb_set_cookie
-- lcb_get_cookie

{# fun lcb_wait as ^ {`Lcb'} -> `LcbError' #}

-- lcb_tick_nowait

{# enum lcb_WAITFLAGS as LcbWaitFlags {underscoreToCase} deriving (Eq, Show) #}

{# fun lcb_wait3 as ^ {`Lcb', `LcbWaitFlags'} -> `()' #}

-- lcb_breakout
-- lcb_is_waiting
-- lcb_refresh_config
-- lcb_sched_enter
-- lcb_sched_leave
-- lcb_sched_fail
-- lcb_sched_flush

{# fun lcb_destroy as ^ {`Lcb'} -> `()' #}

-- lcb_set_destroy_callback
-- lcb_destroy_async
-- lcb_get_node
-- lcb_get_keynode
-- lcb_get_num_replicas
-- lcb_get_num_nodes
-- lcb_get_server_list
-- lcb_dump
-- lcb_cntl
-- lcb_cntl_string
-- lcb_cntl_setu32
-- lcb_cntl_getu32
-- lcb_cntl_exists
-- lcb_enable_timings
-- lcb_disable_timings
-- lcb_get_timings
-- lcb_get_version
-- lcb_supports_feature
-- lcb_mem_alloc
-- lcb_mem_free
-- lcb_run_loop
-- lcb_stop_loop
-- lcb_nstime
-- lcb_histogram_create
-- lcb_histogram_destroy
-- lcb_histogram_record
-- lcb_histogram_read
-- lcb_histogram_print
-- lcb_subdoc3
-- lcb_sdresult_next


whitespace only

whitespace only