News:

*NEW* Current Version on STEAM16.793

Webchat:
Visit the chat



XML

Previous topic - Next topic

MrTAToad

This is a XML system (originally written by "Lymington") from his routine here : http://www.codeproject.com/KB/XML/XMJFileStreaming.aspx

As per usual, some changes were needed - removal of #include files, and in this instance removal of the need to put things into a data segment (the original code could be used by Visual Basic).

It allows reading and writing of XML files.  At the moment, I've only setup interfaces for reading, but the rest is no problem.

This is the test code :

Code (glbasic) Select

LOCAL result$

DEBUG XMJ_GetVersion$()+"\n"
DEBUG XMJ_GetDate$()+"\n"
DEBUG XMJ_ReadFile("test.xml","Order")+"\n"
DEBUG XMJ_GetFirstGroup("ITEM2",1)+"\n"
DEBUG XMJ_GetLastError$()+"\n"
DEBUG XMJ_GetNextGroup("ITEM",1)+"\n"
DEBUG XMJ_GetFirstGroup("Description",2)+"\n"
DEBUG XMJ_GetAttribute$("Description",result$)+"\n"
DEBUG "Result : "+result$+"\n"
DEBUG XMJ_GetFirstGroup("ITEM",1)+"\n"
DEBUG XMJ_GetAttribute$("Quantity",result$)+"\n"
DEBUG "Result : "+result$+"\n"


Current interface system :

Code (glbasic) Select
// --------------------------------- //
// Project: TestXML
// Start: Friday, June 18, 2010
// IDE Version: 8.006

INLINE
}
typedef int size_t;

// C commands
// mem... commands
extern "C" void *memset(void *s, int c, size_t n);
extern "C" void *memcpy(void *dest, const void *src, size_t n);
extern "C" int memcmp(const void *s1, const void *s2, size_t n);
extern "C" void * memmove(void * destination, const void * source, size_t num );

// Memory allocation/freeing commands
extern "C" void *realloc( void * ptr, size_t size );
extern "C" void *malloc ( size_t size );
extern "C" void *calloc(size_t nmemb, size_t size);
extern "C" void free(void *ptr);

// String commands
extern "C" char * strcat ( char * destination, const char * source );
extern "C" int strncmp ( const char * str1, const char * str2, size_t num );
extern "C" size_t strlen(const char *s);
extern "C" char * strcpy ( char * destination, const char * source );
extern "C" char * strncpy ( char * destination, const char * source, size_t num );
extern "C" int strcmp ( const char * str1, const char * str2 );
extern "C" int sprintf ( char * str, const char * format, ... );

// Low level I/O
extern "C" int access(const char *pathname, int mode);
extern "C" int open(const char *pathname, int flags);
extern "C" size_t READ(int fd, void *buf, size_t count);
extern "C" int write(int fd, char *buf, size_t count);
extern "C" int close(int fd);
extern "C" int rename(const char *_old, const char *_new);

// These are used with the open function
#ifdef WIN32
typedef struct __RECT {
long left;
long top;
long right;
long bottom;
} __RECT;

typedef int HDC;

/* Specifiy one of these flags TO define the access mode. */
#define _O_RDONLY 0
#define _O_WRONLY 1
#define _O_RDWR 2

/* Mask FOR access mode bits IN the _open flags. */
#define _O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR)

#define _O_APPEND 0x0008 /* Writes will add TO the END of the file. */

#define _O_RANDOM 0x0010
#define _O_SEQUENTIAL 0x0020
#define _O_TEMPORARY 0x0040 /* Make the file dissappear after closing.
* WARNING: Even IF NOT created by _open! */
#define _O_NOINHERIT 0x0080

#define _O_CREAT 0x0100 /* Create the file IF it does NOT exist. */
#define _O_TRUNC 0x0200 /* Truncate the file IF it does exist. */
#define _O_EXCL 0x0400 /* Open only IF the file does NOT exist. */

#define _O_SHORT_LIVED  0x1000

/* NOTE: Text is the DEFAULT even IF the given _O_TEXT bit is NOT on. */
#define _O_TEXT 0x4000 /* CR-LF IN file becomes LF IN memory. */
#define _O_BINARY 0x8000 /* INPUT AND output is NOT translated. */
#define _O_RAW _O_BINARY

#ifndef _NO_OLDNAMES

/* POSIX/Non-ANSI names FOR increased portability */
#define O_RDONLY _O_RDONLY
#define O_WRONLY _O_WRONLY
#define O_RDWR _O_RDWR
#define O_ACCMODE _O_ACCMODE
#define O_APPEND _O_APPEND
#define O_CREAT _O_CREAT
#define O_TRUNC _O_TRUNC
#define O_EXCL _O_EXCL
#define O_TEXT _O_TEXT
#define O_BINARY _O_BINARY
#define O_TEMPORARY _O_TEMPORARY
#define O_NOINHERIT _O_NOINHERIT
#define O_SEQUENTIAL _O_SEQUENTIAL
#define O_RANDOM _O_RANDOM

#define SM_CXSCREEN 0
#define SM_CYSCREEN 1
#define HWND_BOTTOM ((HWND)1)
#define HWND_NOTOPMOST ((HWND)(-2))
#define HWND_TOP ((HWND)0)
#define HWND_TOPMOST ((HWND)(-1))
#define HWND_DESKTOP (HWND)0
#define HWND_MESSAGE ((HWND)(-3))

#define SWP_DRAWFRAME 0x0020
#define SWP_FRAMECHANGED 0x0020
#define SWP_HIDEWINDOW 0x0080
#define SWP_NOACTIVATE 0x0010
#define SWP_NOCOPYBITS 0x0100
#define SWP_NOMOVE 0x0002
#define SWP_NOSIZE 0x0001
#define SWP_NOREDRAW 0x0008
#define SWP_NOZORDER 0x0004
#define SWP_SHOWWINDOW 0x0040
#define SWP_NOOWNERZORDER 0x0200
#define SWP_NOREPOSITION SWP_NOOWNERZORDER
#define SWP_NOSENDCHANGING 0x0400
#define SWP_DEFERERASE 0x2000
#define SWP_ASYNCWINDOWPOS 0x4000

#define SW_HIDE             0
#define SW_SHOWNORMAL       1
#define SW_SHOWNOACTIVATE   4
#define SW_SHOW             5
#define SW_MINIMIZE         6
#define SW_SHOWNA           8
#define SW_SHOWMAXIMIZED 11
#define SW_MAXIMIZE 12
#define SW_RESTORE 13
#define HORZRES 8
#define VERTRES 10

extern "C" __stdcall int GetSystemMetrics(int);
extern "C" __stdcall int GetWindowRect(HWND hWnd,struct __RECT *lpRect);
extern "C" __stdcall int GetClientRect(HWND hWnd,struct __RECT *lpRect);
extern "C" __stdcall int SetWindowTextA(HWND hWnd,const char *lpString);
extern "C" __stdcall HWND GetDesktopWindow(void);
extern "C" __stdcall int SetWindowPos(HWND hWnd,HWND hWndInsertAfter,int X,int Y,int cx,int cy,int uFlags);
extern "C" __stdcall int EnumDisplaySettingsA(const char*, unsigned int, void*);
extern "C" __stdcall HWND GetForegroundWindow(void);
extern "C" __stdcall int GetLastError(void);
extern "C" __stdcall int GetSystemMetrics(int nIndex);
extern "C" __stdcall HDC GetDC(HWND);
extern "C" __stdcall int GetDeviceCaps(HDC,int);

#endif
#elif _WIN32_CE
/*
* Flag values FOR open(2) AND fcntl(2)
* The kernel adds 1 TO the open modes TO turn it into some
* combination of FREAD AND FWRITE.
*/
#define _FOPEN (-1) /* from sys/file.h, kernel use only */
#define _FREAD 0x0001 /* READ enabled */
#define _FWRITE 0x0002 /* write enabled */
#define _FAPPEND 0x0008 /* append (writes guaranteed at the END) */
#define _FMARK 0x0010 /* internal; mark during gc() */
#define _FDEFER 0x0020 /* internal; defer FOR NEXT gc pass */
#define _FASYNC 0x0040 /* signal pgrp when DATA ready */
#define _FSHLOCK 0x0080 /* BSD flock() shared lock present */
#define _FEXLOCK 0x0100 /* BSD flock() exclusive lock present */
#define _FCREAT 0x0200 /* open with file create */
#define _FTRUNC 0x0400 /* open with truncation */
#define _FEXCL 0x0800 /* error on open IF file exists */
#define _FNBIO 0x1000 /* non blocking I/O (sys5 style) */
#define _FSYNC 0x2000 /* do all writes synchronously */
#define _FNONBLOCK 0x4000 /* non blocking I/O (POSIX style) */
#define _FNDELAY _FNONBLOCK /* non blocking I/O (4.2 style) */
#define _FNOCTTY 0x8000 /* don't assign a ctty on this open */

#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)

#define O_RDONLY 0 /* +1 == FREAD */
#define O_WRONLY 1 /* +1 == FWRITE */
#define O_RDWR 2 /* +1 == FREAD|FWRITE */
#define O_APPEND _FAPPEND
#define O_CREAT _FCREAT
#define O_TRUNC _FTRUNC
#define O_EXCL _FEXCL
/* O_SYNC _FSYNC NOT posix, defined below */
/* O_NDELAY _FNDELAY set IN include/fcntl.h */
/* O_NDELAY _FNBIO set IN 5include/fcntl.h */
#define O_NONBLOCK _FNONBLOCK
#define O_NOCTTY _FNOCTTY
/* FOR machines which care - */
#if defined (_WIN32) || defined (__CYGWIN__)
#define _FBINARY        0x10000
#define _FTEXT          0x20000
#define _FNOINHERIT 0x40000

#define O_BINARY _FBINARY
#define O_TEXT _FTEXT
#define O_NOINHERIT _FNOINHERIT

/* The windows header files define versions with a leading underscore.  */
#define _O_RDONLY O_RDONLY
#define _O_WRONLY O_WRONLY
#define _O_RDWR O_RDWR
#define _O_APPEND O_APPEND
#define _O_CREAT O_CREAT
#define _O_TRUNC O_TRUNC
#define _O_EXCL O_EXCL
#define _O_TEXT O_TEXT
#define _O_BINARY O_BINARY
#define _O_RAW O_BINARY
#define _O_NOINHERIT O_NOINHERIT
#endif

#ifndef _POSIX_SOURCE

#define O_SYNC _FSYNC

#endif
#else
// For all other platforms
#define _O_ACCMODE       00003
#define _O_RDONLY           00
#define _O_WRONLY           01
#define _O_RDWR             02
#define _O_CREAT         00100   /* NOT fcntl */
#define _O_EXCL          00200   /* NOT fcntl */
#define _O_NOCTTY        00400   /* NOT fcntl */
#define _O_TRUNC         01000   /* NOT fcntl */
#define _O_APPEND        02000
#define _O_NONBLOCK      04000   /* NOT fcntl */
#define _O_NDELAY        O_NONBLOCK
#endif

#ifndef IPHONE
// This is for non-windows platforms
extern "C" __stdcall void SDL_WM_SetCaption(const char *,const char *);
#endif

#include "XMJcalls.h"
#include "JPR_GetNxtLne.h"
#include "JPR_GetNxtLne.cpp"
#include "XMJ_rSrc.cpp"

namespace __GLBASIC__ {
ENDINLINE


//! Get the version of XMJ
//\param None
//\\return Version of XMJ being used
FUNCTION XMJ_GetVersion$:
LOCAL temp$

temp$=""

INLINE
char *ptr;

ptr=XMJ_getVersion();
if (ptr)
{
temp_Str.assign(ptr);
}
ENDINLINE

RETURN temp$
ENDFUNCTION

//! Get the date XMJ was written
//\param None
//\\return Date that XMJ was written
FUNCTION XMJ_GetDate$:
LOCAL temp$

temp$=""

INLINE
char *ptr;

ptr=XMJ_getDate();
if (ptr)
{
temp_Str.assign(ptr);
}
ENDINLINE

RETURN temp$
ENDFUNCTION

//! Get last error message
//\param None
//\\return The last error message
FUNCTION XMJ_GetLastError$:
LOCAL temp$

temp$=""

INLINE
char *ptr;

ptr=XMJ_getLastError();
if (ptr)
{
temp_Str.assign(ptr);
}
ENDINLINE

RETURN temp$
ENDFUNCTION

//! Open and read a XML file
//\param fileName$ - Filename to be read
//\param rootName$ - Root name in the file
//\\return > 0 if the file was loaded and the root name was found.  Any other value denotes an error
FUNCTION XMJ_ReadFile%:fileName$,rootName$
INLINE
return XMJ_readFile((char *) fileName_Str.c_str(),(char *) rootName_Str.c_str());
ENDINLINE
ENDFUNCTION

//! Finds the first named group within the higher numbered group & establishes its bounds within that higher group
//\param name$ - Name of group
//\param depth% - Defines depth of search
//\return > 0 if the group name was found.  Any other value denotes an error
FUNCTION XMJ_GetFirstGroup%:name$,depth%
INLINE
return XMJ_getFrstGroup((char *) name_Str.c_str(),(long) depth);
ENDINLINE
ENDFUNCTION

//! Finds the last named group within the higher numbered group & establishes its bounds within that higher group
//\param name$ - Name of group
//\param depth% - Defines depth of search
//\return > 0 if the group name was found.  Any other value denotes an error
FUNCTION XMJ_GetLastGroup%:name$,depth%
INLINE
return XMJ_getLastGroup((char *) name_Str.c_str(),(long) depth);
ENDINLINE
ENDFUNCTION

//! Finds the next named group within the higher numbered group & establishes its bounds within that higher group.
//\param name$ - Name of group
//\param depth% - Defines depth of search
//\return > 0 if the group name was found.  Any other value of denotes an error
FUNCTION XMJ_GetNextGroup%:name$,depth%
INLINE
return XMJ_getNextGroup((char *) name_Str.c_str(),(long) depth);
ENDINLINE
ENDFUNCTION


//! Get the attribute for the current group
//\param attribute$ - Name of attribute
//\param BYREF result$ - Stores the attribute.  Up to 1024 characters will be returned
//\return > 0 if the attribute was found.  Any other value denotes an error
FUNCTION XMJ_GetAttribute$:attribute$,BYREF result$
LOCAL r;

result$=""
INLINE
char buffer[1024]={0};

r=DGNat(XMJ_getAttribute((char *) attribute_Str.c_str(),(char *) &buffer));
if (r==true)
{
result_Str.assign((char *) &buffer);
}
ENDINLINE


RETURN r
ENDFUNCTION

//! Frees the dynamic array & zeroises the 'depth' array & counters.
//\param None
//\return > 0 if the command completed successfully.  Any other value denotes an error
FUNCTION XMJ_Reset%:
INLINE
return XMJ_reset();
ENDINLINE
ENDFUNCTION


And the current project is included.  The good thing about this one is that its multi-platform.  The I/O will need a very slight modification for Linux, and a few other platforms as there is no _O_TEXT value setup for them

[attachment deleted by admin]

MrTAToad

No problem!  It seems to work fine too...

Kitty Hello

for char* (write) you could do:

char* pBuffer = mystring_Str.getbuffer( max_required_length_excluding_null_character );
xml_getwhatever( pBuffer );
mystring_Str.releasebuffer(); // find '\0' character and set the .len member for correct + and LEN operations.

MrTAToad

Ah - that could be better!

MrTAToad

I've now included an interface to all relevant routines - I haven't tried them all though.

The original link does point to a simplistic help document

[attachment deleted by admin]

Hatonastick

#5
This looks just the ticket mate.  Does it also now write XML?  I'm guessing that's a yes.

Anyway attached is a slightly tidied-up version (actually I probably made it worse :P) of the original document which doesn't require registration with CodeProject to download and doesn't contain macros, all converted to PDF form.  I love Open Office. :)

Edit: Not sure why I altered and uploaded the original document as it appears you've already written one.  Sorry. :)

[attachment deleted by admin]
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

MrTAToad

The only downside is that the length of text returned is limited to 256 or so characters - if you increase it, it gets the text from the next attribute  :S


Hatonastick

Oh.  That's not ideal.  Is it a bug or a feature? :)
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

MrTAToad

I suspect it's a feature...

Hatonastick

Not my favourite sort of features those. :)  I was thinking of using this instead of a database system (this would have been a nice alternative because it would also be editable with a text editor in emergencies), but I think I'll probably look into SQLLite or something.  Not a huge deal though.  The project I was going to use it in probably wont ever get done anyway.  =D
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

MrTAToad

The XML system is a trifle limited - but on the plus side it is cross-platform :)

Hatonastick

True, that is a very big plus side, and just because it wont do what I'm after doesn't mean anything.  It's still a very cool library.  :)
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

MrTAToad

Yes, its not bad!

siatek

#13
Hi it's working great im just started on *.TMX (http://www.mapeditor.org/) loader and after few minutes i think that its look's promising ;)


Code (glbasic) Select


65 cowboy_animations 64 64
decorations 1024 128
fog FOG NO_GID 288 1888 160 64
water bubbles PARTICLEEMITTER NO_GID 928 1760 608 32
water bubbles PARTICLEEMITTER NO_GID 1088 1504 288 32
objects 1024 128
NO_NAME KASIA 65 32 1344 
rhino KASIA 65 384 1792 
NO_NAME NO_TYPE 41 352 1472 
NO_NAME NO_TYPE 41 448 1472 
NO_NAME NO_TYPE 41 544 1472 
NO_NAME NO_TYPE 41 768 1344 
NO_NAME NO_TYPE 41 832 1344 
NO_NAME NO_TYPE 56 1120 1632 
NO_NAME NO_TYPE 56 1184 1600 
NO_NAME NO_TYPE 56 1248 1568 
NO_NAME NO_TYPE 56 1312 1536 
NO_NAME NO_TYPE 58 1141 1843 
NO_NAME NO_TYPE 58 1280 1888 
NO_NAME NO_TYPE 58 1425 1840 
NO_NAME NO_TYPE 57 1045 1895 
NO_NAME PARTICLEEMITTER 60 1728 1792 
NO_NAME PARTICLEEMITTER 60 1952 1792 
zones 1024 128
death zone DEATHZONE NO_GID 0 2016 2016 160
NO_NAME WATER NO_GID 928 1792 608 128
NO_NAME WATER NO_GID 1088 1536 288 128
ice ICE NO_GID 288 1760 352 32
collision 1024 128
collision COLLISION NO_GID 0 1888 288 64
NO_NAME COLLISION NO_GID 1216 1728 
collision COLLISION NO_GID 160 1472 576 32
NO_NAME COLLISION NO_GID 1536 1600 
collision COLLISION NO_GID 1568 1792 448 64
NO_NAME COLLISION NO_GID 1216 1600 
collision COLLISION NO_GID 896 1792 32 128
collision COLLISION NO_GID 1536 1792 32 128
collision COLLISION NO_GID 896 1920 672 32
collision COLLISION NO_GID 448 1888 448 64
collision COLLISION NO_GID 736 1344 160 160
collision COLLISION NO_GID 0 1344 160 160
NO_NAME COLLISION NO_GID 160 1344 
NO_NAME COLLISION NO_GID 608 1344 
collision COLLISION NO_GID 320 1792 288 64

glbasic roxx !!!

r0ber7

Hey,

First of all, awesome. I haven't really looked at the code, so forgive me if these questions are irrelevant but it's late and I'm tired. Why the inline C? For parsing XML, all could be done in GLBasic, no? Just wondering, great to see this is on here, might use it in the future.  :good: