Skip to content

Commit

Permalink
Fix more crashes and start working on JSON port
Browse files Browse the repository at this point in the history
  • Loading branch information
UnknownShadow200 committed Dec 7, 2018
1 parent eb1e69b commit 35b6fad
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 15 deletions.
8 changes: 5 additions & 3 deletions src/LScreens.c
Expand Up @@ -24,7 +24,7 @@ CC_NOINLINE static struct LWidget* LScreen_WidgetAt(struct LScreen* s, int x, in
w = s->Widgets[i];
if (w->Hidden) continue;

if (Gui_Contains(w->X, w->Y, w->Width, w->Height, w->X, w->Y)) return w;
if (Gui_Contains(w->X, w->Y, w->Width, w->Height, x, y)) return w;
}
return NULL;
}
Expand Down Expand Up @@ -143,8 +143,10 @@ CC_NOINLINE static void LScreen_Reset(struct LScreen* s) {
s->MouseDown = LScreen_MouseDown;
s->MouseUp = LScreen_MouseUp;
s->MouseMove = LScreen_MouseMove;
s->HoverWidget = LScreen_HoverWidget;
s->UnhoverWidget = LScreen_UnhoverWidget;
s->HoverWidget = LScreen_HoverWidget;
s->UnhoverWidget = LScreen_UnhoverWidget;
s->SelectWidget = LScreen_SelectWidget;
s->UnselectWidget = LScreen_UnselectWidget;

/* reset all widgets mouse state */
for (i = 0; i < s->NumWidgets; i++) {
Expand Down
2 changes: 1 addition & 1 deletion src/LScreens.h
Expand Up @@ -29,7 +29,7 @@ typedef void(*LWidget_Func)(struct LScreen* s, struct LWidget* w);
struct LWidget* OnEnterWidget; /* Default widget to auto-click when Enter is pressed. Can be NULL. */ \
struct LWidget* HoveredWidget; /* Widget the mouse is currently hovering over. */ \
struct LWidget* SelectedWidget; /* Widget mouse last clicked on. */ \
int NumWidgets; /* Number of widgets actually used. */ \
int NumWidgets; /* Number of widgets actually used. */ \
struct LWidget** Widgets; /* Array of pointers to all widgets in the screen. */

struct LScreen { LScreen_Layout };
Expand Down
162 changes: 162 additions & 0 deletions src/LWeb.c
@@ -1,6 +1,168 @@
#include "LWeb.h"
#include "Platform.h"

#define TOKEN_NONE 0
#define TOKEN_NUM 1
#define TOKEN_TRUE 2
#define TOKEN_FALSE 3
#define TOKEN_NULL 4

struct JsonContext {
/* Pointer to current character in JSON stream being inspected. */
char* Cur;
/* Number of characters left to be inspected. */
int Left;
/* Whether there was an error parsing the JSON. */
bool Failed;
/* Callback function invoked on each token read. */
void (*OnToken)(char token);
/* Callback function invoked on each member of an object or array. */
/* NOTE: This only works for 'simple' key-value pairs. */ newarray
void (*OnValue)(char token, String* value);
};
/* new array, new object functions?? */
/* need to push/pop 'CurrentKey' */
/* Consumes n characters from the JSON stream */
#define JsonContext_Consume(ctx, n) ctx->Cur += n; ctx->Left -= n;

static String strTrue = String_FromConst("true");
static String strFalse = String_FromConst("false");
static String strNull = String_FromConst("null");

static bool Json_IsWhitespace(char c) {
return c == '\r' || c == '\n' || c == '\t' || c == ' ';
}

static bool Json_IsNumber(char c) {
return c == '-' || c == '.' || (c >= '0' && c <= '9');
}

static bool Json_ConsumeConstant(struct JsonContext* ctx, String* value) {
int i;
if (value->length > ctx->Left) return false;

for (i = 0; i < value->length; i++) {
if (ctx->Cur[i] != value->buffer[i]) return false;
}

JsonContext_Consume(ctx, value->length);
return true;
}

static int Json_ConsumeToken(struct JsonContext* ctx) {
for (; ctx->Left && Json_IsWhitespace(*ctx->Cur); ) { JsonContext_Consume(ctx, 1); }
if (!ctx->Left) return TOKEN_NONE;

char c = *ctx->Cur;
if (c == '{' || c == '}' || c == '[' || c == ']' || c == ',' || c == '"' || c == ':') {
JsonContext_Consume(ctx, 1); return c;
}

/* number token forms part of value, don't consume it */
if (Json_IsNumber(c)) return TOKEN_NUM;

if (Json_ConsumeConstant(ctx, &strTrue)) return TOKEN_TRUE;
if (Json_ConsumeConstant(ctx, &strFalse)) return TOKEN_FALSE;
if (Json_ConsumeConstant(ctx, &strNull)) return TOKEN_NULL;

/* invalid token */
JsonContext_Consume(ctx, 1);
return TOKEN_NONE;
}

static String Json_ConsumeNumber(struct JsonContext* ctx) {
int len = 0;
for (; ctx->Left && Json_IsNumber(*ctx->Cur); len++) { JsonContext_Consume(ctx, 1); }
return String_Init(ctx->Cur - len, len, len);
}

static void Json_ConsumeObject(struct JsonContext* ctx) {
int token; /* push and pop cur key */

while (true) {
token = Json_ConsumeToken(ctx);
if (token == ',') continue;
if (token == '}') return;

if (token != '"') { ctx->Failed = true; return; }
string key = ParseString(ctx);

token = Json_ConsumeToken(ctx);
if (token != ':') { ctx->Failed = true; return; }

token = Json_ConsumeToken(ctx);
if (token == TOKEN_NONE) { ctx->Failed = true; return; }

members[key] = ParseValue(token, ctx);
}
}

static void Json_ConsumeArray(struct JsonContext* ctx) {
int token;

while (true) {
token = NextToken(ctx);
if (token == ',') continue;
if (token == ']') return;

if (token == TOKEN_NONE) { ctx->Failed = true; return; }
elements.Add(ParseValue(token, ctx));
}
}

static string ParseString(struct JsonContext* ctx) {
int codepoint, h[4];
char c;
StringBuilder s = ctx.strBuffer; s.Length = 0;

for (; ctx->Left;) {
c = *ctx->Cur; JsonContext_Consume(ctx, 1);
if (c == '"') return s.ToString();
if (c != '\\') { s.Append(c); continue; }

/* form of \X */
if (!ctx->Left) break;
c = *ctx->Cur; JsonContext_Consume(ctx, 1);
if (c == '/' || c == '\\' || c == '"') { s.Append(c); continue; }

/* form of \uYYYY */
if (c != 'u' || ctx->Left < 4) break;

if (!PackedCol_Unhex(ctx->Cur[0], &h[0])) break;
if (!PackedCol_Unhex(ctx->Cur[1], &h[1])) break;
if (!PackedCol_Unhex(ctx->Cur[2], &h[2])) break;
if (!PackedCol_Unhex(ctx->Cur[3], &h[3])) break;

codepoint = (h[0] << 12) | (h[1] << 8) | (h[2] << 4) | h[3];
/* don't want control characters in names/software */
if (codepoint >= 32) s.Append((char)codepoint);
JsonContext_Consume(ctx, 4);
}

ctx->Failed = true; return null;
}

static String Json_ConsumeValue(int token, struct JsonContext* ctx) {
switch (token) {
case '{': return ParseObject(ctx);
case '[': return ParseArray(ctx);
case '"': return ParseString(ctx);

case TOKEN_NUM: return Json_ConsumeNumber(ctx);
case TOKEN_TRUE: return strTrue;
case TOKEN_FALSE: return strFalse;
case TOKEN_NULL: break;
}
return String_Empty;
}


static object ParseStream(struct JsonContext* ctx) {
return ParseValue(NextToken(ctx), ctx);
}



static void LWebTask_Reset(struct LWebTask* task) {
task->Completed = false;
task->Working = true;
Expand Down
2 changes: 1 addition & 1 deletion src/LWidgets.c
Expand Up @@ -10,7 +10,7 @@
#define BORDER 1

void LWidget_SetLocation(void* widget, uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset) {
struct Widget* w = widget;
struct LWidget* w = widget;
w->HorAnchor = horAnchor; w->VerAnchor = verAnchor;
w->XOffset = xOffset; w->YOffset = yOffset;
LWidget_CalcPosition(widget);
Expand Down
1 change: 0 additions & 1 deletion src/Launcher.c
Expand Up @@ -335,7 +335,6 @@ static void Launcher_ProcessZipEntry(const String* path, struct Stream* data, st
if (res) {
Launcher_ShowError(res, "decoding terrain.png"); return;
} else {
Drawer2D_SetFontBitmap(&bmp);
Launcher_LoadTextures(&bmp);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Platform.h
Expand Up @@ -206,7 +206,7 @@ ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success);
/* Initalises the platform specific http library state. */
void Http_Init(void);
/* Performs a http request, setting progress as data is received. */
/* NOTE: NOT thread safe - you should always use AsyncDownloader for making requests. */
/* NOTE: NOT thread safe - you should ALWAYS use AsyncDownloader for making requests. */
ReturnCode Http_Do(struct AsyncRequest* req, volatile int* progress);
/* Frees the platform specific http library state. */
ReturnCode Http_Free(void);
Expand Down
2 changes: 1 addition & 1 deletion src/ServerConnection.c
Expand Up @@ -88,7 +88,7 @@ void ServerConnection_CheckAsyncResources(void) {
Chat_Add1("&cError %i when trying to download texture pack", &item.Result);
} else {
int status = item.StatusCode;
if (status == 0 || status == 304) return;
if (status == 200 || status == 304) return;
Chat_Add1("&c%i error when trying to download texture pack", &status);
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/Window.h
Expand Up @@ -2,7 +2,7 @@
#define CC_WINDOW_H
#include "String.h"
#include "Bitmap.h"
/* Abstracts creating and managing a native window.
/* Abstracts creating and managing the native window.
Copyright 2017 ClassicalSharp | Licensed under BSD-3 | Based on OpenTK code
*/

Expand Down Expand Up @@ -31,23 +31,23 @@
OTHER DEALINGS IN THE SOFTWARE.
*/

/* The states a window can be in. */
/* The states the window can be in. */
typedef enum WindowState_ {
WINDOW_STATE_NORMAL, WINDOW_STATE_MINIMISED, WINDOW_STATE_MAXIMISED, WINDOW_STATE_FULLSCREEN
} WindowState;
struct GraphicsMode;

/* Creates a new window of the given size at centre of the screen, with default graphics mode. */
/* Creates the window as the given size at centre of the screen, with default graphics mode. */
void Window_CreateSimple(int width, int height);
/* Creates a new window of the given size at the given position on screen. */
/* Creates the window as the given size at the given position on screen. */
void Window_Create(int x, int y, int width, int height, struct GraphicsMode* mode);
/* Sets the text of the titlebar above the window. */
void Window_SetTitle(const String* title);
/* Gets the text currently on the clipboard. */
/* NOTE: You must have created a window beforehand. (necessary for X11) */
/* NOTE: You MUST have created the window beforehand. (necessary for X11) */
void Window_GetClipboardText(String* value);
/* Sets the text currently on the clipboard. */
/* NOTE: You must have created a window beforehand. (necessary for X11) */
/* NOTE: You MUST have created the window beforehand. (necessary for X11) */
void Window_SetClipboardText(const String* value);
/* TODO: IMPLEMENT void Window_SetIcon(Bitmap* bmp); */

Expand Down Expand Up @@ -100,7 +100,7 @@ void Window_SetScreenCursorPos(int x, int y);
/* Whether the cursor is visible when over this window. */
bool Window_GetCursorVisible(void);
/* Sets whether the cursor is visible when over this window. */
/* NOTE: You must be careful with this! OS typically uses a counter for visibility,
/* NOTE: You MUST BE VERY CAREFUL with this! OS typically uses a counter for visibility,
so setting invisible multiple times means you must then set visible multiple times. */
void Window_SetCursorVisible(bool visible);

Expand Down

0 comments on commit 35b6fad

Please sign in to comment.