view modules/string.tp @ 152:a6739206a9e3

Add splitOn and partitionOn to string objects
author Mike Pavone <pavone@retrodev.com>
date Fri, 09 Aug 2013 20:12:04 -0700
parents 3e9cb69e516d
children 6e579a75a0a9
line wrap: on
line source

#{
	llProperty: len withType: uint32_t
	llProperty: bytes withType: uint32_t
	llProperty: data withType: (char ptr)

	llMessage: length withVars: {
		intret <- (obj_int32 ptr)
	} andCode: {
		intret <- make_object: (addr_of: obj_int32_meta) NULL 0
		intret num!: len
		intret
	}

	llMessage: byte_length withVars: {
		intret <- (obj_int32 ptr)
	} andCode: {
		intret <- make_object: (addr_of: obj_int32_meta) NULL 0
		intret num!: bytes
		intret
	}

	llMessage: EQ_ withVars: {
		argb <- (string ptr)
	} andCode: :argb {
		if: len = (argb len) && bytes = (argb bytes) && (not: (memcmp: data (argb data) bytes)) {
			true
		}
	}

	llMessage: NEQ_ withVars: {
		argb <- (string ptr)
	} andCode: :argb {
		if: len != (argb len) || bytes != (argb bytes) || (memcmp: data (argb data) bytes) {
			true
		}
	}

	llMessage: print withVars: {} andCode: {
		fwrite: data 1 bytes stdout
		self
	}

	llMessage: string withVars: {} andCode: {
		self
	}

	llMessage: CAT_ withVars: {
		argbo <- (object ptr)
		argb <- (string ptr)
		out <- (string ptr)
	} andCode: :argbo {
		argb <- mcall: string 1 argbo
		out <- make_object: (addr_of: string_meta) NULL 0
		out bytes!: bytes + (argb bytes)
		out len!: len + (argb len)
		out data!: (GC_MALLOC_ATOMIC: (out bytes) + 1)
		memcpy: (out data) data bytes
		memcpy: (out data) + bytes (argb data) (argb bytes) + 1
		out
	}

	llMessage: byte withVars: {
		index <- (obj_int32 ptr)
		intret <- (obj_int32 ptr)
	} andCode: :index {
		intret <- make_object: (addr_of: obj_int32_meta) NULL 0
		intret num!: (if: (index num) < bytes { data get: (index num) } else: {0})
		intret
	}

	llMessage: int32 withVars: {
		intret <- (obj_int32 ptr)
	} andCode: {
		intret  <- make_object: (addr_of: obj_int32_meta) NULL 0
		intret num!: (atoi: data)
		intret
	}

	llMessage: hash withVars: {
		intret <- (obj_int32 ptr)
		i <- uint32_t
	} andCode: {
		intret <- make_object: (addr_of: obj_int32_meta) NULL 0
		intret num!: 0
		if: bytes {
			intret num!: (data get: 0) * 128
			i <- 0
			while: { i < bytes } do: {
				intret num!: (1000003 * (intret num)) xor (data get: i)
				i <- i + 1
			}
			intret num!: (intret num) xor bytes
		}
		intret
	}

	llMessage: find:else withVars: {
		intret <- obj_int32 ptr
		oneedle <- object ptr
		ifNotFound <- object ptr
		sneedle <- string ptr
		i <- uint32_t
		notFound <- uint32_t
	} andCode: :oneedle :ifNotFound {
		sneedle <- mcall: string 1 oneedle
		i <- 0
		notFound <- 1
		while: { notFound && i + (sneedle bytes) <= bytes} do: {
			if: (memcmp: data + i (sneedle data) (sneedle bytes)) = 0 {
				notFound <- 0
			} else: {
				i <- i + 1
			}
		}
		if: notFound {
			ccall: ifNotFound 0
		} else: {
			intret <- make_object: (addr_of: obj_int32_meta) NULL 0
			intret num!: i
			intret
		}
	}

	llMessage: from:withLength withVars: {
		from <- obj_int32 ptr
		tocopy <- obj_int32 ptr
		ret <- string ptr
		start <- int32_t
		clampedLen <- int32_t
	} andCode: :from :tocopy {
		start <- from num
		if: start < 0 {
			start <- bytes + start
		}
		if: start > bytes {
			start <- bytes
		}
		clampedLen <- tocopy num
		if: start + clampedLen > bytes {
			clampedLen <- bytes - start
		}
		ret <- make_object: (addr_of: string_meta) NULL 0
		ret data!: (GC_MALLOC_ATOMIC: clampedLen + 1)
		memcpy: (ret data) data + start clampedLen
		ret len!: clampedLen
		ret bytes!: clampedLen
		ret
	}

	from <- :start {
		from: start withLength: length
	}

	partitionOn <- :delim {
		pos <- find: delim else: { -1 }
		if: pos >= 0 {
			_before <- from: 0 withLength: pos
			_after <- from: (pos + (delim length))
			#{
				before <- _before
				after <- _after
			}
		} else: {
			_before <- self
			#{
				before <- _before
				after <- ""
			}
		}
	}

	splitOn <- :delim {
		pos <- 0
		pieces <- #[]
		while: {
			pos <- find: delim else: { -1 }
			pos >= 0
		} do: {
			pieces append: (from: 0 withLength: pos)
			self <- from: pos + (delim length)
		}
		pieces append: self
	}

	isInteger? <- { false }
}