add angle
This commit is contained in:
parent
6c2c3a2d70
commit
c59d299f5d
|
@ -8,7 +8,8 @@ public class FCLConfig implements Serializable {
|
|||
|
||||
public enum Renderer implements Serializable {
|
||||
RENDERER_GL4ES("libgl4es.so:libgl4es_egl.so"),
|
||||
RENDERER_ZINK("libGL.so:libEGL.so");
|
||||
RENDERER_ZINK("libGL.so:libEGL.so"),
|
||||
RENDERER_ANGLE("lib.so:libEGL_angle.so");
|
||||
|
||||
private final String glInfo;
|
||||
private String glVersion;
|
||||
|
|
|
@ -140,6 +140,9 @@ public class FCLauncher {
|
|||
if (renderer.getGlVersion() != null) {
|
||||
envMap.put("LIBGL_GL", renderer.getGlVersion());
|
||||
}
|
||||
if("libtinywrapper.so".equals(renderer.getGlLibName())) {
|
||||
envMap.put("LIBGL_ES","3");
|
||||
}
|
||||
envMap.put("LIBGL_MIPMAP", "3");
|
||||
envMap.put("LIBGL_NORMALIZE", "1");
|
||||
envMap.put("LIBGL_VSYNC", "1");
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := angle_gles2
|
||||
LOCAL_SRC_FILES := tinywrapper/angle-gles/$(TARGET_ARCH_ABI)/libGLESv2_angle.so
|
||||
include $(PREBUILT_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := tinywrapper
|
||||
LOCAL_SHARED_LIBRARIES := angle_gles2
|
||||
LOCAL_SRC_FILES := tinywrapper/main.c tinywrapper/string_utils.c
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/tinywrapper
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := xhook
|
||||
LOCAL_SRC_FILES := xhook/xhook.c \
|
||||
|
|
|
@ -277,6 +277,8 @@ GLFWbool _glfwInitEGL(void)
|
|||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
|
||||
_glfw.egl.GetConfigs = (PFN_eglGetConfigs)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
|
||||
_glfw.egl.ChooseConfig = (PFN_eglChooseConfig)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglChooseConfig");
|
||||
_glfw.egl.GetDisplay = (PFN_eglGetDisplay)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
|
||||
_glfw.egl.GetError = (PFN_eglGetError)
|
||||
|
@ -382,12 +384,6 @@ void _glfwTerminateEGL(void)
|
|||
}
|
||||
}
|
||||
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
//
|
||||
|
@ -395,10 +391,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
EGLint attribs[40];
|
||||
EGLConfig config;
|
||||
EGLConfig config=malloc(sizeof(EGLConfig));
|
||||
EGLContext share = NULL;
|
||||
int index = 0;
|
||||
|
||||
if (!_glfw.egl.display)
|
||||
{
|
||||
|
@ -409,13 +403,33 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
if (ctxconfig->share)
|
||||
share = ctxconfig->share->context.egl.handle;
|
||||
|
||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
EGLint egl_attributes[] = {
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT|0x0001,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint num_configs = 0;
|
||||
const EGLint egl_context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, getenv("LIBGL_ES"), EGL_NONE };
|
||||
if (eglChooseConfig(_glfw.egl.display, egl_attributes, NULL, 0, &num_configs) != GLFW_TRUE) {
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "eglChooseConfig() failed: %04x",
|
||||
eglGetError());
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (num_configs == 0) {
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "%s",
|
||||
"eglChooseConfig() found no matching config");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
eglChooseConfig(_glfw.egl.display, egl_attributes, &config, 1, &num_configs);
|
||||
// eglGetConfigAttrib(_glfw.egl.display, config, EGL_NATIVE_VISUAL_ID, 0);
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
if (!eglBindAPI(EGL_OPENGL_ES_API))
|
||||
|
@ -437,82 +451,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
}
|
||||
}
|
||||
|
||||
if (_glfw.egl.KHR_create_context)
|
||||
{
|
||||
int mask = 0, flags = 0;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (ctxconfig->forward)
|
||||
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
|
||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
||||
}
|
||||
|
||||
if (ctxconfig->debug)
|
||||
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
|
||||
if (ctxconfig->robustness)
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
}
|
||||
|
||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||
}
|
||||
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.egl.KHR_create_context_no_error)
|
||||
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
|
||||
if (flags)
|
||||
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
}
|
||||
|
||||
if (_glfw.egl.KHR_context_flush_control)
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
|
||||
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
||||
config, share, attribs);
|
||||
config, share, egl_context_attributes);
|
||||
|
||||
if (window->context.egl.handle == EGL_NO_CONTEXT)
|
||||
{
|
||||
|
@ -522,25 +462,11 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// Set up attributes for surface creation
|
||||
index = 0;
|
||||
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
if (!fbconfig->doublebuffer)
|
||||
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
|
||||
window->context.egl.surface =
|
||||
eglCreateWindowSurface(_glfw.egl.display,
|
||||
config,
|
||||
_GLFW_EGL_NATIVE_WINDOW,
|
||||
attribs);
|
||||
NULL);
|
||||
if (window->context.egl.surface == EGL_NO_SURFACE)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
|
@ -548,7 +474,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.egl.config = config;
|
||||
|
||||
// Load the appropriate client library
|
||||
|
@ -567,7 +492,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
};
|
||||
const char* glsonames[] =
|
||||
{
|
||||
"libgl4es.so",
|
||||
getenv("LIBGL_NAME"),
|
||||
};
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
|
@ -610,7 +535,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -79,6 +79,7 @@ typedef void* EGLSurface;
|
|||
// EGL function pointer typedefs
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
|
||||
typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
|
||||
|
@ -95,6 +96,7 @@ typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
|
|||
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
||||
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
||||
#define eglGetConfigs _glfw.egl.GetConfigs
|
||||
#define eglChooseConfig _glfw.egl.ChooseConfig
|
||||
#define eglGetDisplay _glfw.egl.GetDisplay
|
||||
#define eglGetError _glfw.egl.GetError
|
||||
#define eglInitialize _glfw.egl.Initialize
|
||||
|
@ -144,6 +146,7 @@ typedef struct _GLFWlibraryEGL
|
|||
|
||||
PFN_eglGetConfigAttrib GetConfigAttrib;
|
||||
PFN_eglGetConfigs GetConfigs;
|
||||
PFN_eglChooseConfig ChooseConfig;
|
||||
PFN_eglGetDisplay GetDisplay;
|
||||
PFN_eglGetError GetError;
|
||||
PFN_eglInitialize Initialize;
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,201 @@
|
|||
//#import <Foundation/Foundation.h>
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "GLES3/gl32.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
#define LOOKUP_FUNC(func) \
|
||||
if (!gles_##func) { \
|
||||
gles_##func = dlsym(RTLD_NEXT, #func); \
|
||||
} if (!gles_##func) { \
|
||||
gles_##func = dlsym(RTLD_DEFAULT, #func); \
|
||||
}
|
||||
|
||||
int proxy_width, proxy_height, proxy_intformat, maxTextureSize;
|
||||
|
||||
void glBindFragDataLocationEXT(GLuint program, GLuint colorNumber, const char * name);
|
||||
|
||||
void(*gles_glGetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint *params);
|
||||
void(*gles_glShaderSource)(GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length);
|
||||
void(*gles_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data);
|
||||
|
||||
void glBindFragDataLocation(GLuint program, GLuint colorNumber, const char * name) {
|
||||
glBindFragDataLocationEXT(program, colorNumber, name);
|
||||
}
|
||||
|
||||
void glClearDepth(GLdouble depth) {
|
||||
glClearDepthf(depth);
|
||||
}
|
||||
|
||||
void *glMapBuffer(GLenum target, GLenum access) {
|
||||
// Use: GL_EXT_map_buffer_range
|
||||
|
||||
GLenum access_range;
|
||||
GLint length;
|
||||
|
||||
switch (target) {
|
||||
// GL 4.2
|
||||
case GL_ATOMIC_COUNTER_BUFFER:
|
||||
|
||||
// GL 4.3
|
||||
case GL_DISPATCH_INDIRECT_BUFFER:
|
||||
case GL_SHADER_STORAGE_BUFFER :
|
||||
|
||||
// GL 4.4
|
||||
case GL_QUERY_BUFFER:
|
||||
printf("ERROR: glMapBuffer unsupported target=0x%x", target);
|
||||
break; // not supported for now
|
||||
|
||||
case GL_DRAW_INDIRECT_BUFFER:
|
||||
case GL_TEXTURE_BUFFER:
|
||||
printf("ERROR: glMapBuffer unimplemented target=0x%x", target);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (access) {
|
||||
case GL_READ_ONLY:
|
||||
access_range = GL_MAP_READ_BIT;
|
||||
break;
|
||||
|
||||
case GL_WRITE_ONLY:
|
||||
access_range = GL_MAP_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case GL_READ_WRITE:
|
||||
access_range = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);
|
||||
return glMapBufferRange(target, 0, length, access_range);
|
||||
}
|
||||
|
||||
void glShaderSource(GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length) {
|
||||
LOOKUP_FUNC(glShaderSource)
|
||||
|
||||
// DBG(printf("glShaderSource(%d, %d, %p, %p)\n", shader, count, string, length);)
|
||||
char *source = NULL;
|
||||
char *converted;
|
||||
|
||||
// get the size of the shader sources and than concatenate in a single string
|
||||
int l = 0;
|
||||
for (int i=0; i<count; i++) l+=(length && length[i] >= 0)?length[i]:strlen(string[i]);
|
||||
if (source) free(source);
|
||||
source = calloc(1, l+1);
|
||||
if(length) {
|
||||
for (int i=0; i<count; i++) {
|
||||
if(length[i] >= 0)
|
||||
strncat(source, string[i], length[i]);
|
||||
else
|
||||
strcat(source, string[i]);
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<count; i++)
|
||||
strcat(source, string[i]);
|
||||
}
|
||||
|
||||
char *source2 = strchr(source, '#');
|
||||
if (!source2) {
|
||||
source2 = source;
|
||||
}
|
||||
// are there #version?
|
||||
if (!strncmp(source2, "#version ", 9)) {
|
||||
converted = strdup(source2);
|
||||
if (converted[9] == '1') {
|
||||
if (converted[10] - '0' < 2) {
|
||||
// 100, 110 -> 120
|
||||
converted[10] = '2';
|
||||
} else if (converted[10] - '0' < 6) {
|
||||
// 130, 140, 150 -> 330
|
||||
converted[9] = converted[10] = '3';
|
||||
}
|
||||
}
|
||||
// remove "core", is it safe?
|
||||
if (!strncmp(&converted[13], "core", 4)) {
|
||||
strncpy(&converted[13], "\n//c", 4);
|
||||
}
|
||||
} else {
|
||||
converted = calloc(1, strlen(source) + 13);
|
||||
strcpy(converted, "#version 120\n");
|
||||
strcpy(&converted[13], strdup(source));
|
||||
}
|
||||
|
||||
int convertedLen = strlen(converted);
|
||||
|
||||
#ifdef __APPLE__
|
||||
// patch OptiFine 1.17.x
|
||||
if (FindString(converted, "\nuniform mat4 textureMatrix = mat4(1.0);")) {
|
||||
InplaceReplace(converted, &convertedLen, "\nuniform mat4 textureMatrix = mat4(1.0);", "\n#define textureMatrix mat4(1.0)");
|
||||
}
|
||||
#endif
|
||||
|
||||
// some needed exts
|
||||
const char* extensions =
|
||||
"#extension GL_EXT_blend_func_extended : enable\n"
|
||||
// For OptiFine (see patch above)
|
||||
"#extension GL_EXT_shader_non_constant_global_initializers : enable\n";
|
||||
converted = InplaceInsert(GetLine(converted, 1), extensions, converted, &convertedLen);
|
||||
|
||||
gles_glShaderSource(shader, 1, (const GLchar * const*)((converted)?(&converted):(&source)), NULL);
|
||||
|
||||
free(source);
|
||||
free(converted);
|
||||
}
|
||||
|
||||
int isProxyTexture(GLenum target) {
|
||||
switch (target) {
|
||||
case GL_PROXY_TEXTURE_1D:
|
||||
case GL_PROXY_TEXTURE_2D:
|
||||
case GL_PROXY_TEXTURE_3D:
|
||||
case GL_PROXY_TEXTURE_RECTANGLE_ARB:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inline nlevel(int size, int level) {
|
||||
if(size) {
|
||||
size>>=level;
|
||||
if(!size) size=1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {
|
||||
LOOKUP_FUNC(glGetTexLevelParameteriv)
|
||||
// NSLog("glGetTexLevelParameteriv(%x, %d, %x, %p)", target, level, pname, params);
|
||||
if (isProxyTexture(target)) {
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_WIDTH:
|
||||
(*params) = nlevel(proxy_width,level);
|
||||
break;
|
||||
case GL_TEXTURE_HEIGHT:
|
||||
(*params) = nlevel(proxy_height,level);
|
||||
break;
|
||||
case GL_TEXTURE_INTERNAL_FORMAT:
|
||||
(*params) = proxy_intformat;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
gles_glGetTexLevelParameteriv(target, level, pname, params);
|
||||
}
|
||||
}
|
||||
|
||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data) {
|
||||
LOOKUP_FUNC(glTexImage2D)
|
||||
if (isProxyTexture(target)) {
|
||||
if (!maxTextureSize) {
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||
// maxTextureSize = 16384;
|
||||
// NSLog(@"Maximum texture size: %d", maxTextureSize);
|
||||
}
|
||||
proxy_width = ((width<<level)>maxTextureSize)?0:width;
|
||||
proxy_height = ((height<<level)>maxTextureSize)?0:height;
|
||||
proxy_intformat = internalformat;
|
||||
// swizzle_internalformat((GLenum *) &internalformat, format, type);
|
||||
} else {
|
||||
gles_glTexImage2D(target, level, internalformat, width, height, border, format, type, data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "string_utils.h"
|
||||
|
||||
const char* AllSeparators = " \t\n\r.,;()[]{}-<>+*/%&\\\"'^$=!:?";
|
||||
|
||||
char* ResizeIfNeeded(char* pBuffer, int *size, int addsize);
|
||||
|
||||
char* InplaceReplace(char* pBuffer, int* size, const char* S, const char* D)
|
||||
{
|
||||
int lS = strlen(S), lD = strlen(D);
|
||||
pBuffer = ResizeIfNeeded(pBuffer, size, (lD-lS)*CountString(pBuffer, S));
|
||||
char* p = pBuffer;
|
||||
while((p = strstr(p, S)))
|
||||
{
|
||||
// found an occurence of S
|
||||
// check if good to replace, strchr also found '\0' :)
|
||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL)) {
|
||||
// move out rest of string
|
||||
memmove(p+lD, p+lS, strlen(p)-lS+1);
|
||||
// replace
|
||||
memcpy(p, D, strlen(D));
|
||||
// next
|
||||
p+=lD;
|
||||
} else p+=lS;
|
||||
}
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
char* InplaceInsert(char* pBuffer, const char* S, char* master, int* size)
|
||||
{
|
||||
char* m = ResizeIfNeeded(master, size, strlen(S));
|
||||
if(m!=master) {
|
||||
pBuffer += (m-master);
|
||||
master = m;
|
||||
}
|
||||
char* p = pBuffer;
|
||||
int lS = strlen(S), ll = strlen(pBuffer);
|
||||
memmove(p+lS, p, ll+1);
|
||||
memcpy(p, S, lS);
|
||||
|
||||
return master;
|
||||
}
|
||||
|
||||
char* GetLine(char* pBuffer, int num)
|
||||
{
|
||||
char *p = pBuffer;
|
||||
while(num-- && (p=strstr(p, "\n"))) p+=strlen("\n");
|
||||
return (p)?p:pBuffer;
|
||||
}
|
||||
|
||||
int CountLine(const char* pBuffer)
|
||||
{
|
||||
int n=0;
|
||||
const char* p = pBuffer;
|
||||
while((p=strstr(p, "\n"))) {
|
||||
p+=strlen("\n");
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int GetLineFor(const char* pBuffer, const char* S)
|
||||
{
|
||||
int n=0;
|
||||
const char* p = pBuffer;
|
||||
const char* end = FindString(pBuffer, S);
|
||||
if(!end)
|
||||
return 0;
|
||||
while((p=strstr(p, "\n"))) {
|
||||
p+=strlen("\n");
|
||||
n++;
|
||||
if(p>=end)
|
||||
return n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int CountString(const char* pBuffer, const char* S)
|
||||
{
|
||||
const char* p = pBuffer;
|
||||
int lS = strlen(S);
|
||||
int n = 0;
|
||||
while((p = strstr(p, S)))
|
||||
{
|
||||
// found an occurence of S
|
||||
// check if good to count, strchr also found '\0' :)
|
||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL))
|
||||
n++;
|
||||
p+=lS;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
const char* FindString(const char* pBuffer, const char* S)
|
||||
{
|
||||
const char* p = pBuffer;
|
||||
int lS = strlen(S);
|
||||
while((p = strstr(p, S)))
|
||||
{
|
||||
// found an occurence of S
|
||||
// check if good to count, strchr also found '\0' :)
|
||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL))
|
||||
return p;
|
||||
p+=lS;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* FindStringNC(char* pBuffer, const char* S)
|
||||
{
|
||||
char* p = pBuffer;
|
||||
int lS = strlen(S);
|
||||
while((p = strstr(p, S)))
|
||||
{
|
||||
// found an occurence of S
|
||||
// check if good to count, strchr also found '\0' :)
|
||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL))
|
||||
return p;
|
||||
p+=lS;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* ResizeIfNeeded(char* pBuffer, int *size, int addsize) {
|
||||
char* p = pBuffer;
|
||||
int newsize = strlen(pBuffer)+addsize+1;
|
||||
if (newsize>*size) {
|
||||
newsize += 100;
|
||||
p = (char*)realloc(pBuffer, newsize);
|
||||
*size=newsize;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
char* Append(char* pBuffer, int* size, const char* S) {
|
||||
char* p =pBuffer;
|
||||
p = ResizeIfNeeded(pBuffer, size, strlen(S));
|
||||
strcat(p, S);
|
||||
return p;
|
||||
}
|
||||
|
||||
int isBlank(char c) {
|
||||
switch(c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case ':':
|
||||
case ',':
|
||||
case ';':
|
||||
case '/':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
char* StrNext(char *pBuffer, const char* S) {
|
||||
if(!pBuffer) return NULL;
|
||||
char *p = strstr(pBuffer, S);
|
||||
return (p)?p:(p+strlen(S));
|
||||
}
|
||||
|
||||
char* NextStr(char* pBuffer) {
|
||||
if(!pBuffer) return NULL;
|
||||
while(isBlank(*pBuffer))
|
||||
++pBuffer;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
char* NextBlank(char* pBuffer) {
|
||||
if(!pBuffer) return NULL;
|
||||
while(!isBlank(*pBuffer))
|
||||
++pBuffer;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
char* NextLine(char* pBuffer) {
|
||||
if(!pBuffer) return NULL;
|
||||
while(*pBuffer && *pBuffer!='\n')
|
||||
++pBuffer;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
const char* GetNextStr(char* pBuffer) {
|
||||
static char buff[100] = {0};
|
||||
buff[0] = '\0';
|
||||
if(!pBuffer) return NULL;
|
||||
char* p1 = NextStr(pBuffer);
|
||||
if(!p1) return buff;
|
||||
char* p2 = NextBlank(p1);
|
||||
if(!p2) return buff;
|
||||
int i=0;
|
||||
while(p1!=p2 && i<99)
|
||||
buff[i++] = *(p1++);
|
||||
buff[i] = '\0';
|
||||
return buff;
|
||||
}
|
||||
|
||||
int CountStringSimple(char* pBuffer, const char* S)
|
||||
{
|
||||
char* p = pBuffer;
|
||||
int lS = strlen(S);
|
||||
int n = 0;
|
||||
while((p = strstr(p, S)))
|
||||
{
|
||||
// found an occurence of S
|
||||
n++;
|
||||
p+=lS;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
char* InplaceReplaceSimple(char* pBuffer, int* size, const char* S, const char* D)
|
||||
{
|
||||
int lS = strlen(S), lD = strlen(D);
|
||||
pBuffer = ResizeIfNeeded(pBuffer, size, (lD-lS)*CountStringSimple(pBuffer, S));
|
||||
char* p = pBuffer;
|
||||
while((p = strstr(p, S)))
|
||||
{
|
||||
// found an occurence of S
|
||||
// move out rest of string
|
||||
memmove(p+lD, p+lS, strlen(p)-lS+1);
|
||||
// replace
|
||||
memcpy(p, D, strlen(D));
|
||||
// next
|
||||
p+=lD;
|
||||
}
|
||||
|
||||
return pBuffer;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef _GL4ES_STRING_UTILS_H_
|
||||
#define _GL4ES_STRING_UTILS_H_
|
||||
|
||||
extern const char* AllSeparators;
|
||||
|
||||
const char* FindString(const char* pBuffer, const char* S);
|
||||
char* FindStringNC(char* pBuffer, const char* S);
|
||||
int CountString(const char* pBuffer, const char* S);
|
||||
char* ResizeIfNeeded(char* pBuffer, int *size, int addsize);
|
||||
char* InplaceReplace(char* pBuffer, int* size, const char* S, const char* D);
|
||||
char* Append(char* pBuffer, int* size, const char* S);
|
||||
char* InplaceInsert(char* pBuffer, const char* S, char* master, int* size);
|
||||
char* GetLine(char* pBuffer, int num);
|
||||
int CountLine(const char* pBuffer);
|
||||
int GetLineFor(const char* pBuffer, const char* S); // get the line number for 1st occurent of S in pBuffer
|
||||
char* StrNext(char *pBuffer, const char* S); // mostly as strstr, but go after the substring if found
|
||||
//"blank" (space, tab, cr, lf,":", ",", ";", ".", "/")
|
||||
char* NextStr(char* pBuffer); // go to next non "blank"
|
||||
char* NextBlank(char* pBuffer); // go to next "blank"
|
||||
char* NextLine(char* pBuffer); // go to next new line (crlf not included)
|
||||
|
||||
const char* GetNextStr(char* pBuffer); // get a (static) copy of next str (until next separator), can be a simple number or separator also
|
||||
|
||||
// those function don't try to be smart with separators...
|
||||
int CountStringSimple(char* pBuffer, const char* S);
|
||||
char* InplaceReplaceSimple(char* pBuffer, int* size, const char* S, const char* D);
|
||||
|
||||
|
||||
#endif // _GL4ES_STRING_UTILS_H_
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue