blob: 5953f362b79d5bc5064ff85fd070ca4d5ca47afa [file] [log] [blame]
#include "precompiled.h"
//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// utilities.cpp: Conversion functions and other utility routines.
#include "libGLESv2/utilities.h"
#include "libGLESv2/mathutil.h"
namespace gl
{
int UniformComponentCount(GLenum type)
{
switch (type)
{
case GL_BOOL:
case GL_FLOAT:
case GL_INT:
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
return 1;
case GL_BOOL_VEC2:
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
return 2;
case GL_INT_VEC3:
case GL_FLOAT_VEC3:
case GL_BOOL_VEC3:
return 3;
case GL_BOOL_VEC4:
case GL_FLOAT_VEC4:
case GL_INT_VEC4:
case GL_FLOAT_MAT2:
return 4;
case GL_FLOAT_MAT3:
return 9;
case GL_FLOAT_MAT4:
return 16;
default:
UNREACHABLE();
}
return 0;
}
GLenum UniformComponentType(GLenum type)
{
switch(type)
{
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
return GL_BOOL;
case GL_FLOAT:
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4:
return GL_FLOAT;
case GL_INT:
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
return GL_INT;
default:
UNREACHABLE();
}
return GL_NONE;
}
size_t UniformComponentSize(GLenum type)
{
switch(type)
{
case GL_BOOL: return sizeof(GLint);
case GL_FLOAT: return sizeof(GLfloat);
case GL_INT: return sizeof(GLint);
default: UNREACHABLE();
}
return 0;
}
size_t UniformInternalSize(GLenum type)
{
// Expanded to 4-element vectors
return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4;
}
size_t UniformExternalSize(GLenum type)
{
return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type);
}
int VariableRowCount(GLenum type)
{
switch (type)
{
case GL_NONE:
return 0;
case GL_BOOL:
case GL_FLOAT:
case GL_INT:
case GL_BOOL_VEC2:
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_FLOAT_VEC3:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
case GL_FLOAT_VEC4:
case GL_INT_VEC4:
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
return 1;
case GL_FLOAT_MAT2:
return 2;
case GL_FLOAT_MAT3:
return 3;
case GL_FLOAT_MAT4:
return 4;
default:
UNREACHABLE();
}
return 0;
}
int VariableColumnCount(GLenum type)
{
switch (type)
{
case GL_NONE:
return 0;
case GL_BOOL:
case GL_FLOAT:
case GL_INT:
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
return 1;
case GL_BOOL_VEC2:
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_FLOAT_MAT2:
return 2;
case GL_INT_VEC3:
case GL_FLOAT_VEC3:
case GL_BOOL_VEC3:
case GL_FLOAT_MAT3:
return 3;
case GL_BOOL_VEC4:
case GL_FLOAT_VEC4:
case GL_INT_VEC4:
case GL_FLOAT_MAT4:
return 4;
default:
UNREACHABLE();
}
return 0;
}
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
{
ASSERT(allocationSize <= bitsSize);
unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
{
if ((*bits & mask) == 0)
{
*bits |= mask;
return i;
}
mask <<= 1;
}
return -1;
}
GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment)
{
ASSERT(alignment > 0 && isPow2(alignment));
GLsizei rawPitch = ComputePixelSize(internalformat) * width;
return (rawPitch + alignment - 1) & ~(alignment - 1);
}
GLsizei ComputeCompressedPitch(GLsizei width, GLenum internalformat)
{
return ComputeCompressedSize(width, 1, internalformat);
}
GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat)
{
switch (internalformat)
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return 8 * ((width + 3) / 4) * ((height + 3) / 4);
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
return 16 * ((width + 3) / 4) * ((height + 3) / 4);
default:
return 0;
}
}
bool IsCompressed(GLenum format)
{
if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
{
return true;
}
else
{
return false;
}
}
bool IsDepthTexture(GLenum format)
{
if (format == GL_DEPTH_COMPONENT ||
format == GL_DEPTH_STENCIL_OES ||
format == GL_DEPTH_COMPONENT16 ||
format == GL_DEPTH_COMPONENT32_OES ||
format == GL_DEPTH24_STENCIL8_OES)
{
return true;
}
return false;
}
bool IsStencilTexture(GLenum format)
{
if (format == GL_DEPTH_STENCIL_OES ||
format == GL_DEPTH24_STENCIL8_OES)
{
return true;
}
return false;
}
void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
{
int upsampleCount = 0;
if (isCompressed)
{
// Don't expand the size of full textures that are at least 4x4
// already.
if (isImage || *requestWidth < 4 || *requestHeight < 4)
{
while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
{
*requestWidth <<= 1;
*requestHeight <<= 1;
upsampleCount++;
}
}
}
*levelOffset = upsampleCount;
}
// Returns the size, in bytes, of a single texel in an Image
int ComputePixelSize(GLint internalformat)
{
switch (internalformat)
{
case GL_ALPHA8_EXT: return sizeof(unsigned char);
case GL_LUMINANCE8_EXT: return sizeof(unsigned char);
case GL_ALPHA32F_EXT: return sizeof(float);
case GL_LUMINANCE32F_EXT: return sizeof(float);
case GL_ALPHA16F_EXT: return sizeof(unsigned short);
case GL_LUMINANCE16F_EXT: return sizeof(unsigned short);
case GL_LUMINANCE8_ALPHA8_EXT: return sizeof(unsigned char) * 2;
case GL_LUMINANCE_ALPHA32F_EXT: return sizeof(float) * 2;
case GL_LUMINANCE_ALPHA16F_EXT: return sizeof(unsigned short) * 2;
case GL_RGB8_OES: return sizeof(unsigned char) * 3;
case GL_RGB565: return sizeof(unsigned short);
case GL_RGB32F_EXT: return sizeof(float) * 3;
case GL_RGB16F_EXT: return sizeof(unsigned short) * 3;
case GL_RGBA8_OES: return sizeof(unsigned char) * 4;
case GL_RGBA4: return sizeof(unsigned short);
case GL_RGB5_A1: return sizeof(unsigned short);
case GL_RGBA32F_EXT: return sizeof(float) * 4;
case GL_RGBA16F_EXT: return sizeof(unsigned short) * 4;
case GL_BGRA8_EXT: return sizeof(unsigned char) * 4;
case GL_BGRA4_ANGLEX: return sizeof(unsigned short);
case GL_BGR5_A1_ANGLEX: return sizeof(unsigned short);
default: UNREACHABLE();
}
return 0;
}
bool IsCubemapTextureTarget(GLenum target)
{
return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
}
bool IsInternalTextureTarget(GLenum target)
{
return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
}
GLint ConvertSizedInternalFormat(GLenum format, GLenum type)
{
switch (format)
{
case GL_ALPHA:
switch (type)
{
case GL_UNSIGNED_BYTE: return GL_ALPHA8_EXT;
case GL_FLOAT: return GL_ALPHA32F_EXT;
case GL_HALF_FLOAT_OES: return GL_ALPHA16F_EXT;
default: UNIMPLEMENTED();
}
break;
case GL_LUMINANCE:
switch (type)
{
case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_EXT;
case GL_FLOAT: return GL_LUMINANCE32F_EXT;
case GL_HALF_FLOAT_OES: return GL_LUMINANCE16F_EXT;
default: UNIMPLEMENTED();
}
break;
case GL_LUMINANCE_ALPHA:
switch (type)
{
case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_ALPHA8_EXT;
case GL_FLOAT: return GL_LUMINANCE_ALPHA32F_EXT;
case GL_HALF_FLOAT_OES: return GL_LUMINANCE_ALPHA16F_EXT;
default: UNIMPLEMENTED();
}
break;
case GL_RGB:
switch (type)
{
case GL_UNSIGNED_BYTE: return GL_RGB8_OES;
case GL_UNSIGNED_SHORT_5_6_5: return GL_RGB565;
case GL_FLOAT: return GL_RGB32F_EXT;
case GL_HALF_FLOAT_OES: return GL_RGB16F_EXT;
default: UNIMPLEMENTED();
}
break;
case GL_RGBA:
switch (type)
{
case GL_UNSIGNED_BYTE: return GL_RGBA8_OES;
case GL_UNSIGNED_SHORT_4_4_4_4: return GL_RGBA4;
case GL_UNSIGNED_SHORT_5_5_5_1: return GL_RGB5_A1;
case GL_FLOAT: return GL_RGBA32F_EXT;
case GL_HALF_FLOAT_OES: return GL_RGBA16F_EXT;
break;
default: UNIMPLEMENTED();
}
break;
case GL_BGRA_EXT:
switch (type)
{
case GL_UNSIGNED_BYTE: return GL_BGRA8_EXT;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return GL_BGRA4_ANGLEX;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return GL_BGR5_A1_ANGLEX;
default: UNIMPLEMENTED();
}
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
return format;
case GL_DEPTH_COMPONENT:
switch (type)
{
case GL_UNSIGNED_SHORT: return GL_DEPTH_COMPONENT16;
case GL_UNSIGNED_INT: return GL_DEPTH_COMPONENT32_OES;
default: UNIMPLEMENTED();
}
break;
case GL_DEPTH_STENCIL_OES:
switch (type)
{
case GL_UNSIGNED_INT_24_8_OES: return GL_DEPTH24_STENCIL8_OES;
default: UNIMPLEMENTED();
}
break;
default:
UNIMPLEMENTED();
}
return GL_NONE;
}
GLenum ExtractFormat(GLenum internalformat)
{
switch (internalformat)
{
case GL_RGB565: return GL_RGB;
case GL_RGBA4: return GL_RGBA;
case GL_RGB5_A1: return GL_RGBA;
case GL_RGB8_OES: return GL_RGB;
case GL_RGBA8_OES: return GL_RGBA;
case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA;
case GL_LUMINANCE8_EXT: return GL_LUMINANCE;
case GL_ALPHA8_EXT: return GL_ALPHA;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
case GL_RGBA32F_EXT: return GL_RGBA;
case GL_RGB32F_EXT: return GL_RGB;
case GL_ALPHA32F_EXT: return GL_ALPHA;
case GL_LUMINANCE32F_EXT: return GL_LUMINANCE;
case GL_LUMINANCE_ALPHA32F_EXT: return GL_LUMINANCE_ALPHA;
case GL_RGBA16F_EXT: return GL_RGBA;
case GL_RGB16F_EXT: return GL_RGB;
case GL_ALPHA16F_EXT: return GL_ALPHA;
case GL_LUMINANCE16F_EXT: return GL_LUMINANCE;
case GL_LUMINANCE_ALPHA16F_EXT: return GL_LUMINANCE_ALPHA;
case GL_BGRA8_EXT: return GL_BGRA_EXT;
case GL_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT;
case GL_DEPTH_COMPONENT32_OES: return GL_DEPTH_COMPONENT;
case GL_DEPTH24_STENCIL8_OES: return GL_DEPTH_STENCIL_OES;
default: return GL_NONE; // Unsupported
}
}
GLenum ExtractType(GLenum internalformat)
{
switch (internalformat)
{
case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
case GL_RGB8_OES: return GL_UNSIGNED_BYTE;
case GL_RGBA8_OES: return GL_UNSIGNED_BYTE;
case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE;
case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
case GL_RGBA32F_EXT: return GL_FLOAT;
case GL_RGB32F_EXT: return GL_FLOAT;
case GL_ALPHA32F_EXT: return GL_FLOAT;
case GL_LUMINANCE32F_EXT: return GL_FLOAT;
case GL_LUMINANCE_ALPHA32F_EXT: return GL_FLOAT;
case GL_RGBA16F_EXT: return GL_HALF_FLOAT_OES;
case GL_RGB16F_EXT: return GL_HALF_FLOAT_OES;
case GL_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
case GL_LUMINANCE16F_EXT: return GL_HALF_FLOAT_OES;
case GL_LUMINANCE_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
case GL_DEPTH_COMPONENT16: return GL_UNSIGNED_SHORT;
case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
case GL_DEPTH24_STENCIL8_OES: return GL_UNSIGNED_INT_24_8_OES;
default: return GL_NONE; // Unsupported
}
}
bool IsColorRenderable(GLenum internalformat)
{
switch (internalformat)
{
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGB565:
case GL_RGB8_OES:
case GL_RGBA8_OES:
return true;
case GL_DEPTH_COMPONENT16:
case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES:
return false;
case GL_BGRA8_EXT:
return true;
default:
UNIMPLEMENTED();
}
return false;
}
bool IsDepthRenderable(GLenum internalformat)
{
switch (internalformat)
{
case GL_DEPTH_COMPONENT16:
case GL_DEPTH24_STENCIL8_OES:
return true;
case GL_STENCIL_INDEX8:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGB565:
case GL_RGB8_OES:
case GL_RGBA8_OES:
return false;
default:
UNIMPLEMENTED();
}
return false;
}
bool IsStencilRenderable(GLenum internalformat)
{
switch (internalformat)
{
case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES:
return true;
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGB565:
case GL_RGB8_OES:
case GL_RGBA8_OES:
case GL_DEPTH_COMPONENT16:
return false;
default:
UNIMPLEMENTED();
}
return false;
}
bool IsFloat32Format(GLint internalformat)
{
switch (internalformat)
{
case GL_RGBA32F_EXT:
case GL_RGB32F_EXT:
case GL_ALPHA32F_EXT:
case GL_LUMINANCE32F_EXT:
case GL_LUMINANCE_ALPHA32F_EXT:
return true;
default:
return false;
}
}
bool IsFloat16Format(GLint internalformat)
{
switch (internalformat)
{
case GL_RGBA16F_EXT:
case GL_RGB16F_EXT:
case GL_ALPHA16F_EXT:
case GL_LUMINANCE16F_EXT:
case GL_LUMINANCE_ALPHA16F_EXT:
return true;
default:
return false;
}
}
unsigned int GetAlphaSize(GLenum colorFormat)
{
switch (colorFormat)
{
case GL_RGBA16F_EXT:
return 16;
case GL_RGBA32F_EXT:
return 32;
case GL_RGBA4:
return 4;
case GL_RGBA8_OES:
case GL_BGRA8_EXT:
return 8;
case GL_RGB5_A1:
return 1;
case GL_RGB8_OES:
case GL_RGB565:
case GL_RGB32F_EXT:
case GL_RGB16F_EXT:
return 0;
default:
return 0;
}
}
unsigned int GetRedSize(GLenum colorFormat)
{
switch (colorFormat)
{
case GL_RGBA16F_EXT:
case GL_RGB16F_EXT:
return 16;
case GL_RGBA32F_EXT:
case GL_RGB32F_EXT:
return 32;
case GL_RGBA4:
return 4;
case GL_RGBA8_OES:
case GL_BGRA8_EXT:
case GL_RGB8_OES:
return 8;
case GL_RGB5_A1:
case GL_RGB565:
return 5;
default:
return 0;
}
}
unsigned int GetGreenSize(GLenum colorFormat)
{
switch (colorFormat)
{
case GL_RGBA16F_EXT:
case GL_RGB16F_EXT:
return 16;
case GL_RGBA32F_EXT:
case GL_RGB32F_EXT:
return 32;
case GL_RGBA4:
return 4;
case GL_RGBA8_OES:
case GL_BGRA8_EXT:
case GL_RGB8_OES:
return 8;
case GL_RGB5_A1:
return 5;
case GL_RGB565:
return 6;
default:
return 0;
}
}
unsigned int GetBlueSize(GLenum colorFormat)
{
switch (colorFormat)
{
case GL_RGBA16F_EXT:
case GL_RGB16F_EXT:
return 16;
case GL_RGBA32F_EXT:
case GL_RGB32F_EXT:
return 32;
case GL_RGBA4:
return 4;
case GL_RGBA8_OES:
case GL_BGRA8_EXT:
case GL_RGB8_OES:
return 8;
case GL_RGB5_A1:
case GL_RGB565:
return 5;
default:
return 0;
}
}
unsigned int GetDepthSize(GLenum depthFormat)
{
switch (depthFormat)
{
case GL_DEPTH_COMPONENT16: return 16;
case GL_DEPTH_COMPONENT32_OES: return 32;
case GL_DEPTH24_STENCIL8_OES: return 24;
default: return 0;
}
}
unsigned int GetStencilSize(GLenum stencilFormat)
{
switch (stencilFormat)
{
case GL_DEPTH24_STENCIL8_OES: return 8;
default: return 0;
}
}
bool IsTriangleMode(GLenum drawMode)
{
switch (drawMode)
{
case GL_TRIANGLES:
case GL_TRIANGLE_FAN:
case GL_TRIANGLE_STRIP:
return true;
case GL_POINTS:
case GL_LINES:
case GL_LINE_LOOP:
case GL_LINE_STRIP:
return false;
default: UNREACHABLE();
}
return false;
}
}
#if defined(__LB_XB360__)
#include <stdio.h>
static DWORD GetTempPathW(DWORD nBufferLength, LPTSTR lpBuffer)
{
return !wcsncpy_s(lpBuffer, nBufferLength, _wP_tmpdir, nBufferLength);
}
static UINT GetTempFileNameW(LPCTSTR lpPathName, LPCTSTR lpPrefixString,
UINT uUnique, LPTSTR lpTempFileName)
{
LPCTSTR tempname = _wtempnam(lpPathName, lpPrefixString);
if (!tempname) return 0;
return !wcsncpy_s(lpTempFileName, MAX_PATH, tempname, MAX_PATH);
}
static DWORD GetShortPathNameW(LPCTSTR lpszLongPath, LPTSTR lpszShortPath,
DWORD cchBuffer)
{
return !wcsncpy_s(lpszShortPath, cchBuffer, lpszLongPath, cchBuffer);
}
#endif // defined(__LB_XB360__)
std::string getTempPath()
{
#ifdef __LB_SHELL__FOR_RELEASE__
return std::string();
#else
wchar_t widePath[MAX_PATH];
if (GetTempPathW(MAX_PATH, widePath) == 0)
{
UNREACHABLE();
return std::string();
}
wchar_t wideFileName[MAX_PATH];
if (GetTempFileNameW(widePath, L"sh", 0, wideFileName) == 0)
{
UNREACHABLE();
return std::string();
}
wchar_t shortPath[MAX_PATH];
if (GetShortPathNameW(wideFileName, shortPath, MAX_PATH) == 0)
{
UNREACHABLE();
return std::string();
}
// Short paths should not contain any non-ASCII characters which means
// that the resulting UTF-8 should be pure ASCII, even if the original
// name had special UNICODE characters
int bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, shortPath, -1,
NULL, 0, NULL, NULL);
std::string result(bytesNeeded, 0);
if (WideCharToMultiByte(CP_UTF8, 0, shortPath, -1,
&result[0], bytesNeeded, NULL, NULL) == 0)
{
UNREACHABLE();
return std::string();
}
return result;
#endif
}
void writeFile(const char* path, const void* content, size_t size)
{
#ifndef __LB_SHELL__FOR_RELEASE__
FILE* file = fopen(path, "w");
if (!file)
{
UNREACHABLE();
return;
}
fwrite(content, sizeof(char), size, file);
fclose(file);
#endif
}