c65gm/lib/string.c65

397 lines
9.6 KiB
Text

//------------------------------------------------------------------------
// String library
//
// Author: Mattias Hansson
// Copyright (c) : 2005 Mattias Hansson
// License: GNU GPL 2
// Language: 65CM v0.4+
// Dependencies:
// ZP usage: $fb-$fe
//
// External functions:
// lib_string_strlen
// lib_string_strchr
// lib_string_strcpy
// lib_string_stpcpy
// lib_string_strncpy
// lib_string_strcmp
// lib_string_memset
// lib_string_strcat
// lib_string_strncat
//
// Internal function:
//
//
// Note: Several of the lib-functions are combined to save space, where
// this can be done at a fairly small speed penalty.
//
//------------------------------------------------------------------------
#IFNDEF __LIB_STRING
#DEFINE __LIB_STRING = 1
GOTO lib_string_skip
//Makes it possible for all modules that needs NULL
//to define the constant
#IFNDEF NULL
#DEFINE NULL = 0
#IFEND
WORD lib_string_strptr1 @ $fb
WORD lib_string_strptr2 @ $fd
WORD lib_string_length
//just aliases for the mem* functions
WORD lib_string_ptr1 @ $fb
WORD lib_string_ptr2 @ $fd
WORD lib_string_temp
//-----------------------------------------------------------
// lib_string_strlen
//
// Purpose: Returns the string length of a null-terminated
// string in memory.
//
// Params:
// lib_string_strptr1 - pointer to string to measure
// lib_string_length - returns the length of the string
//
// lib_string_strchr
//
// Purpose: Returns pointer to where char lib_string_sl_matchchar
// first occurs in string at lib_string_strptr1.
// Returns NULL if not found.
//-----------------------------------------------------------
BYTE lib_string_sl_matchchar
FUNC lib_string_strlen ( lib_string_strptr1 out:lib_string_length )
LET lib_string_sl_matchchar = 0
FUNC lib_string_strchr ( io:lib_string_strptr1 lib_string_sl_matchchar )
BYTE char
LET lib_string_length = 0
PEEK lib_string_strptr1 -> char
WHILE char
IF char == lib_string_sl_matchchar
SUBEND
ENDIF
INC lib_string_strptr1
INC lib_string_length
PEEK lib_string_strptr1 -> char
WEND
LET lib_string_strptr1 = NULL
FEND
//-----------------------------------------------------------
// lib_string_strcpy
//
// Purpose: Copies the null-terminated string at
// lib_string_strptr1 to lib_string_strptr2
//
// lib_string_stpcpy
//
// Purpose: Same as strcpy but returns a pointer to the
// end of the copy in lib_string_strptr2
//
// lib_string_strncpy
//
// Purpose: Copies the null-terminated string at
// lib_string_strptr1 to lib_string_strptr2, but
// stops after lib_string_length chars regardless
// of if the full string is copied
//
// Note: Dont send in 0 (zero) into lib_string_length.
//-----------------------------------------------------------
FUNC lib_string_stpcpy ( lib_string_strptr1 io:lib_string_strptr2 )
FUNC lib_string_strcpy ( lib_string_strptr1 lib_string_strptr2 )
LET lib_string_length = 0
FUNC lib_string_strncpy ( lib_string_strptr1 lib_string_strptr2 lib_string_length )
BYTE char
LET char = $ff
WHILE char
PEEK lib_string_strptr1 -> char
POKE lib_string_strptr2 , char
INC lib_string_strptr1
INC lib_string_strptr2
DEC lib_string_length
IF lib_string_length == 0
BREAK
ENDIF
WEND
FEND
//-----------------------------------------------------------
// lib_string_memset
//
// Purpose: Sets lib_string_length bytes starting at
// lib_string_ptr1 to the value lib_string_memset_value
//
//-----------------------------------------------------------
BYTE lib_string_memset_value
FUNC lib_string_memset ( lib_string_ptr1 lib_string_memset_value lib_string_length )
ADD lib_string_ptr1 + lib_string_length -> lib_string_ptr2
DEC lib_string_ptr2
WHILE lib_string_ptr2 >= lib_string_ptr1
POKE lib_string_ptr2 , lib_string_memset_value
DEC lib_string_ptr2
WEND
FEND
//-----------------------------------------------------------
// lib_string_strcmp
//
// purpose: Compare two strings.
// Returns 2 if str1 is less than str2
// 1 if str1 is greater than str2
// 0 if they are equal.
//-----------------------------------------------------------
BYTE lib_string_strcmp_result
FUNC lib_string_strcmp ( lib_string_strptr1 lib_string_strptr2 out:lib_string_strcmp_result )
BYTE val1
BYTE val2
LET lib_string_strcmp_result = 0
PEEK lib_string_strptr1 -> val1
PEEK lib_string_strptr2 -> val2
WHILE val1 == val2
INC lib_string_strptr1
INC lib_string_strptr2
PEEK lib_string_strptr1 -> val1
PEEK lib_string_strptr2 -> val2
IF val1 == 0
BREAK
ENDIF
IF val2 == 0
BREAK
ENDIF
WEND
IF val1 < val2
LET lib_string_strcmp_result = 2
ENDIF
IF val1 > val2
LET lib_string_strcmp_result = 1
ENDIF
FEND
//-----------------------------------------------------------
// lib_string_strstr
//
// purpose:
// Locate the position of one string in another.
// Returns a pointer to the location of the
// substring. (or NULL if not found)
//-----------------------------------------------------------
WORD lib_string_strstr_return
FUNC lib_string_strstr ( lib_string_strptr1 lib_string_strptr2 out:lib_string_strstr_return )
LET lib_string_strstr_return = NULL
WORD strlen1
WORD strlen2
WORD substartpos
WORD mainlastpos
BYTE mainval
BYTE subval
WORD strptr1firstmatch
BYTE innerloop
//Ugly hack: Since "lib_string_strptr1" is used internally in strlen we remember the value in a temp variable
LET lib_string_temp = lib_string_strptr1
CALL lib_string_strlen ( lib_string_strptr1 strlen1 )
CALL lib_string_strlen ( lib_string_strptr2 strlen2 )
//Ugly hack: Since "lib_string_strptr1" is used internally in strlen we restore the value from a temp variable
LET lib_string_strptr1 = lib_string_temp
IF strlen1 == 0
SUBEND
ENDIF
IF strlen2 == 0
SUBEND
ENDIF
IF strlen2 > strlen1
SUBEND
ENDIF
SUBT strlen1 - strlen2 -> mainlastpos
ADD lib_string_strptr1 + mainlastpos -> mainlastpos
LET substartpos = lib_string_strptr2
LET innerloop = 0
PEEK lib_string_strptr2 -> subval
WHILE lib_string_strptr1 <= mainlastpos
PEEK lib_string_strptr1 -> mainval
IF mainval = subval
LET strptr1firstmatch = lib_string_strptr1
LET innerloop = 1
ENDIF
WHILE mainval = subval
INC lib_string_strptr1
INC lib_string_strptr2
PEEK lib_string_strptr1 -> mainval
PEEK lib_string_strptr2 -> subval
IF subval = 0
//This is the match! We found substr!
LET lib_string_strstr_return = strptr1firstmatch
SUBEND
ENDIF
WEND
IF innerloop != 0
LET innerloop = 0
LET lib_string_strptr1 = strptr1firstmatch
LET lib_string_strptr2 = substartpos
PEEK lib_string_strptr2 -> subval
ENDIF
INC lib_string_strptr1
WEND
FEND
//-----------------------------------------------------------
// lib_string_strcat
//
// purpose:
// To concatenate two strings.
// Appends lib_string_strptr1 to the
// end of lib_string_strptr2 (overwritng
// the terminating NULL character).
//
// lib_string_strncat
//
// purpose:
// very similar to strcat except at most
// lib_string_sc_copymaxchars are
// copied from the source. result is
// always NULL-terminated.
// (i.e. result string is at most
// length( lib_string_strptr1 ) +
// lib_string_sc_copymaxchars + 1
//
// Note:
// Be sure that memory after NULL
// in lib_string_strptr2 is avaliable
// for writing (so you don't overwrite
// something else lying there, or you
// may get some very unexpected
// results.
//-----------------------------------------------------------
WORD lib_string_sc_copymaxchars
FUNC lib_string_strcat ( lib_string_strptr1 lib_string_strptr2 )
LET lib_string_sc_copymaxchars = $ffff
FUNC lib_string_strncat ( lib_string_strptr1 lib_string_strptr2 lib_string_sc_copymaxchars )
BYTE char
//first find end of string2
PEEK lib_string_strptr2 -> char
WHILE char
INC lib_string_strptr2
PEEK lib_string_strptr2 -> char
WEND
PEEK lib_string_strptr1 -> char
POKE lib_string_strptr2 , char
WHILE char
PEEK lib_string_strptr1 -> char
POKE lib_string_strptr2 , char
INC lib_string_strptr1
INC lib_string_strptr2
DEC lib_string_sc_copymaxchars
IF lib_string_sc_copymaxchars == 0
POKE lib_string_strptr2 , 0
SUBEND
ENDIF
WEND
FEND
//-----------------------------------------------------------
// lib_string_memcmp
//
// Purpose:
// Compare two memory areas.
//
//-----------------------------------------------------------
BYTE lib_string_mc_res
FUNC lib_string_memcmp ( lib_string_ptr1 lib_string_ptr2 lib_string_length out:lib_string_mc_res )
BYTE b1
BYTE b2
LET lib_string_mc_res = 1
WHILE lib_string_length
PEEK lib_string_ptr1 -> b1
PEEK lib_string_ptr2 -> b2
IF b1 != b2
SUBEND
ENDIF
INC lib_string_ptr1
INC lib_string_ptr2
DEC lib_string_length
WEND
LET lib_string_mc_res = 0
FEND
//-----------------------------------------------------------
// lib_string_memcpy
//
// Purpose:
// Copy contants of a memory area to another memory area
//-----------------------------------------------------------
FUNC lib_string_memcpy ( lib_string_ptr1 lib_string_ptr2 lib_string_length )
BYTE btemp
WHILE lib_string_length
PEEK lib_string_ptr1 -> btemp
POKE lib_string_ptr2 , btemp
INC lib_string_ptr1
INC lib_string_ptr2
DEC lib_string_length
WEND
FEND
LABEL lib_string_skip
#IFEND