/* Copyright (C) 2003-2013 Runtime Revolution Ltd.
 
 This file is part of LiveCode.
 
 LiveCode is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License v3 as published by the Free
 Software Foundation.
 
 LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 along with LiveCode.  If not see <http://www.gnu.org/licenses/>.  */

/*  
This library consists of the operations on bytes included in the standard library of LiveCode Builder.
*/

module com.livecode.byte

use com.livecode.foreign

public foreign handler MCByteEvalNumberOfBytesIn(in Target as Data, out Count as LCUIndex) returns nothing binds to "<builtin>"

public foreign handler MCByteEvalOffsetOfBytes(in IsLast as CBool, in Needle as Data, in Target as Data, out Offset as LCUIndex) returns nothing binds to "<builtin>"
public foreign handler MCByteEvalOffsetOfBytesBefore(in IsLast as CBool, in Needle as Data, in Before as LCIndex, in Target as Data, out Offset as LCUIndex) returns nothing binds to "<builtin>"
public foreign handler MCByteEvalOffsetOfBytesAfter(in IsLast as CBool, in Needle as Data, in After as LCIndex, in Target as Data, out Offset as LCUIndex) returns nothing binds to "<builtin>"

public foreign handler MCByteEvalIsAmongTheBytesOf(in Needle as Data, in Target as Data, out Value as CBool) returns nothing binds to "<builtin>"

public foreign handler MCByteEvalContainsBytes(in Target as Data, in Needle as Data, out Value as CBool) returns nothing binds to "<builtin>"
public foreign handler MCByteEvalIsInBytes(in Needle as Data, in Target as Data, out Value as CBool) returns nothing binds to "<builtin>"
public foreign handler MCByteEvalBeginsWithBytes(in Target as Data, in Needle as Data, out Value as CBool) returns nothing binds to "<builtin>"
public foreign handler MCByteEvalEndsWithBytes(in Target as Data, in Needle as Data, out Value as CBool) returns nothing binds to "<builtin>"

public foreign handler MCByteFetchByteOf(in Index as LCIndex, in Target as Data, out Value as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteStoreByteOf(in Value as Data, in Index as LCIndex, inout Target as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteFetchByteRangeOf(in Start as LCIndex, in Finish as LCIndex, in Target as Data, out Value as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteStoreByteRangeOf(in Value as Data, in Start as LCIndex, in Finish as LCIndex, inout Target as Data) returns nothing binds to "<builtin>"

public foreign handler MCByteRepeatForEachByte(inout Iterator as optional Pointer, out Iterand as Data, in Container as Data) returns CBool binds to "<builtin>"

public foreign handler MCByteFetchFirstByteOf(in Target as Data, out Value as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteStoreFirstByteOf(in Value as Data, inout Target as Data) returns nothing binds to "<builtin>"

public foreign handler MCByteFetchLastByteOf(in Target as Data, out Value as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteStoreLastByteOf(in Value as Data, inout Target as Data) returns nothing binds to "<builtin>"

public foreign handler MCByteExecDeleteByteOf(in Index as LCIndex, inout Target as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteExecDeleteByteRangeOf(in Start as LCIndex, in Finish as LCIndex, inout Target as Data) returns nothing binds to "<builtin>"

public foreign handler MCByteExecDeleteLastByteOf(inout Target as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteExecDeleteFirstByteOf(inout Target as Data) returns nothing binds to "<builtin>"

public foreign handler MCDataExecRandomBytes(in Count as LCUIndex, out Value as Data) returns nothing binds to "<builtin>"

public foreign handler MCByteEvalByteWithCode(in Value as LCUInt, out Result as Data) returns nothing binds to "<builtin>"
public foreign handler MCByteEvalCodeOfByte(in Target as Data, out Result as LCUInt) returns nothing binds to "<builtin>"

--

/*
Summary:            Counts the number of bytes in <Target>.

Target: 			An expression which evaluates to binary data.

Returns: 			The number of bytes in <Target>

Description:

Tags: Binary
*/

syntax CountBytesOf is prefix operator with precedence 1
	"the" "number" "of" "bytes" "in" <Target: Expression>
begin
	MCByteEvalNumberOfBytesIn(Target, output)
end syntax

--

/*

Summary:            Finds the first or last occurrence of <Needle> within <Target>

Needle: 			An expression which evaluates to binary data.
Target: 			An expression which evaluates to binary data.

Returns: 			Returns the offset of <Needle> in <Target>.

Description:
The first (respectively last) offset of <Needle> in <Target> is number of bytes between the first byte of <Target> and the first (respectively last) occurrence of <Needle>. If neither first or last is specified, then the first offset is found. If <Needle> does not occur in <Target>, then the output is 0.

Tags: Binary
*/

syntax ByteOffset is prefix operator with precedence 1
    "the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "offset" "of" <Needle: Expression> "in" <Target: Expression>
begin
    MCByteEvalOffsetOfBytes(IsLast, Needle, Target, output)
end syntax
syntax ByteIndex is prefix operator with precedence 1
    "the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "index" "of" <Needle: Expression> "in" <Target: Expression>
begin
    MCByteEvalOffsetOfBytes(IsLast, Needle, Target, output)
end syntax

/*

Summary:            Finds the first or last occurrence of <Needle> after a specified index in <Target>

Needle: 			An expression which evaluates to binary data.
Target: 			An expression which evaluates to binary data.
After:              An expression which evaluates to a valid integer index of Target.

Returns: 			Returns the offset of <Needle> after index <After> in <Target>.
                    
Description:
The first (respectively last) offset of <Needle> in <Target> is number of bytes between byte <After> of <Target> and the first (respectively last) occurrence of <Needle> after <After>. If neither first or last is specified, then the first offset is found. If <Needle> does not occur after <After> in <Target>, then the output is 0.

Tags: Binary
*/
syntax ByteOffsetAfter is prefix operator with precedence 1
	"the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "offset" "of" <Needle: Expression> "after" <After: Expression> "in" <Target: Expression>
begin
	MCByteEvalOffsetOfBytesAfter(IsLast, Needle, After, Target, output)
end syntax
syntax ByteIndexAfter is prefix operator with precedence 1
	"the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "index" "of" <Needle: Expression> "after" <After: Expression> "in" <Target: Expression>
begin
	MCByteEvalOffsetOfBytesAfter(IsLast, Needle, After, Target, output)
end syntax

/*

Summary:            Finds the first or last occurrence of <Needle> before a specified index in <Target>.

Needle: 			An expression which evaluates to binary data.
Target: 			An expression which evaluates to binary data.
Before:              An expression which evaluates to a valid integer index of Target.

Returns: 			Returns the offset of <Needle> before index <Before> in <Target>.
                    
Description:
The first (respectively last) offset of <Needle> in <Target> is number of bytes between the first byte of <Target> and the first (respectively last) occurrence of <Needle> before <Before>. If neither first or last is specified, then the last offset is found. If <Needle> does not occur before <Before> in <Target>, then the output is 0.

Tags: Binary
*/
syntax ByteOffsetBefore is prefix operator with precedence 1
    "the" ( "first" <IsFirst=true> | "last" <IsFirst=false> | <IsFirst=false> ) "offset" "of" <Needle: Expression> "before" <Before: Expression> "in" <Target: Expression>
begin
    MCByteEvalOffsetOfBytesBefore(IsFirst, Needle, Before, Target, output)
end syntax
syntax ByteIndexBefore is prefix operator with precedence 1
    "the" ( "first" <IsFirst=true> | "last" <IsFirst=false> | <IsFirst=false> ) "index" "of" <Needle: Expression> "before" <Before: Expression> "in" <Target: Expression>
begin
    MCByteEvalOffsetOfBytesBefore(IsFirst, Needle, Before, Target, output)
end syntax

/*
Summary:            Determines whether <Needle> is in <Target>.
Needle: 			An expression which evaluates to a single byte of binary data.
Target: 			An expression which evaluates to binary data.

Returns: 			True if <Needle> is among the bytes of <Target>, and false otherwise.

Description:
>*Note:* It is an error if <Needle> evaluates to data consisting of more than one byte.

Tags: Binary
*/

syntax ByteIsInData is neutral binary operator with precedence 1
    <Needle: Expression> "is" "in" <Target: Expression>
begin
    MCByteEvalIsInBytes(Needle, Target, output)
end syntax

--

/*
Summary:            Determines whether <Needle> contains <Target>.
Needle: 			An expression which evaluates to binary data.
Target: 			An expression which evaluates to binary data.

Returns: 			True if the bytes of <Needle> occur as a subsequence of the bytes of <Target>, and false otherwise.

Description:
>*Note:* Since the empty data is a subsequence of every sequence of bytes, every sequence of bytes contains the empty data.

Tags: Binary
*/

syntax ContainsBytes is neutral binary operator with precedence 1
    <Target: Expression> "contains" <Needle: Expression>
begin
    MCByteEvalContainsBytes(Target, Needle, output)
end syntax

/*
Summary:            Determines whether <Target> begins with <Needle>.
Needle: 			An expression which evaluates to binary data.
Target: 			An expression which evaluates to binary data.

Returns: 			True if the bytes of <Needle> occur as an initial subsequence of the bytes of <Target>, and false otherwise.

Description:
>*Note:* Since the empty data is an initial subsequence of every sequence of bytes, every sequence of bytes begins with the empty data.

Tags: Binary
*/

syntax BeginsWithBytes is neutral binary operator with precedence 1
    <Target: Expression> "begins" "with" <Needle: Expression>
begin
    MCByteEvalBeginsWithBytes(Target, Needle, output)
end syntax

/*
Summary:            Determines whether <Target> ends with <Needle>.
Needle: 			An expression which evaluates to binary data.
Target: 			An expression which evaluates to binary data.

Returns: 			True if the bytes of <Needle> occur as a final subsequence of the bytes of <Target>, and false otherwise.

Description:
>*Note:* Since the empty data is a final subsequence of every sequence of bytes, every sequence of bytes ends with the empty data.

Tags: Binary
*/

syntax EndsWithBytes is neutral binary operator with precedence 1
    <Target: Expression> "ends" "with" <Needle: Expression>
begin
    MCByteEvalEndsWithBytes(Target, Needle, output)
end syntax

--

/*

Summary:            Designates the byte of data at index <Index> in <Target>.
Index: 				An expression which evaluates to a valid integer index of <Target>.
Target:				An expression which evaluates to binary data.

Description:
Either locates the byte at the given index for use as the target container of another operation, or evaluates the byte at the given index as the source of another operation.

>*Note:* It is an error if <Index> is out of range.

Tags: Binary
*/

syntax SingletonByteOf is prefix operator with precedence 1
	"byte" <Index: Expression> "of" <Target: Expression>
begin
	MCByteFetchByteOf(Index, Target, output)
	MCByteStoreByteOf(input, Index, Target)
end syntax

/*

Summary:            Designates the bytes of data between indices <Start> and <Finish> in <Target>.

Start:              An expression which evaluates to a valid integer index of <Target>.
Finish:             An expression which evaluates to a valid integer index of <Target>.
Target:             An expression which evaluates to binary data.

Description:
Either locates the bytes between the given indices for use as the target container of another operation, or evaluates the bytes at the given indices as the source of another operation.

>*Note:* It is an error if either <Start> or <Finish> are out of range.

Tags: Binary
*/

syntax RangeByteOf is prefix operator with precedence 1
	"byte" <Start: Expression> "to" <Finish: Expression> "of" <Target: Expression>
begin
	MCByteFetchByteRangeOf(Start, Finish, Target, output)
	MCByteStoreByteRangeOf(input, Start, Finish, Target)
end syntax

/*

Summary:            Designates the first byte of data in <Target>.
Target:				An expression which evaluates to binary data.

Description:
Either locates the first byte for use as the target container of another operation, or evaluates the first byte as the source of another operation.

>*Note:* It is an error if <Target> is empty.

Tags: Binary
*/

syntax FirstByteOf is prefix operator with precedence 1
	"the" "first" "byte" "of" <Target: Expression>
begin
	MCByteFetchFirstByteOf(Target, output)
	MCByteStoreFirstByteOf(input, Target)
end syntax

/*

Summary:            Designates the first byte of data in <Target>.
Target:				An expression which evaluates to binary data.

Description:
Either locates the first byte for use as the target container of another operation, or evaluates the first byte as the source of another operation.

>*Note:* It is an error if <Target> is empty.

Tags: Binary
*/

syntax LastByteOf is prefix operator with precedence 1
	"the" "last" "byte" "of" <Target: Expression>
begin
	MCByteFetchLastByteOf(Target, output)
	MCByteStoreLastByteOf(input, Target)
end syntax

--

/*

Summary:            Deletes the byte of data at index <Index> in <Target>.
Index: 				An expression which evaluates to a valid integer index of <Target>.
Target:				A container of binary data.

Description:
Replaces the byte at the given index with the empty data.

>*Note:* It is an error if <Index> is out of range.

Tags: Binary
*/

syntax DeleteSingletonByteOf is statement
	"delete" "byte" <Index: Expression> "of" <Target: Expression>
begin
	MCByteExecDeleteByteOf(Index, Target)
end syntax

/*

Summary:            Deletes the bytes of data between indices <Start> and <Finish> in <Target>.

Start:              An expression which evaluates to a valid integer index of <Target>.
Finish:             An expression which evaluates to a valid integer index of <Target>.
Target:             A container of binary data.

Description:
Replaces the bytes between the given indices with the empty data.

>*Note:* It is an error if either <Start> or <Finish> are out of range.

Tags: Binary
*/

syntax DeleteRangeByteOf is statement
	"delete" "byte" <Start: Expression> "to" <Finish: Expression> "of" <Target: Expression>
begin
	MCByteExecDeleteByteRangeOf(Start, Finish, Target)
end syntax

/*

Summary:            Deletes the first byte in <Target>.
Target:				A binary data container.

Description:
Replaces the first byte in <Target> with the empty data.

>*Note:* It is an error if <Target> is the empty data.

Tags: Binary
*/

syntax DeleteFirstByteOf is statement
	"delete" "the" "first" "byte" "of" <Target: Expression>
begin
	MCByteExecDeleteFirstByteOf(Target)
end syntax


/*

Summary:            Deletes the last byte in <Target>.
Target:				A binary data container.

Description:
Replaces the last byte in <Target> with the empty data.

>*Note:* It is an error if <Target> is the empty data.

Tags: Binary
*/

syntax DeleteLastByteOf is statement
	"delete" "the" "last" "byte" "of" <Target: Expression>
begin
	MCByteExecDeleteLastByteOf(Target)
end syntax

--

/*
Summary:        Repeat over the bytes of some data
Iterand:        A container of binary data.

Description:
Use repeat for each to perform an operation on each byte of some data. On each iteration, the <Iterand> will contain the next char of the string being iterated over.

Tags: Binary, Control structures
*/

syntax RepeatForEachByte is iterator
    "byte" <Iterand: Expression>
begin
    MCByteRepeatForEachByte(iterator, Iterand, container)
end syntax

--

/*
Summary:	Generate random data
Count:		Expression evaluating to the number of bytes to generate

Description:
Generates the requested number of bytes of cryptographic-quality
random data.

Tags: Binary, Random

*/
syntax RandomBytes is postfix operator with precedence 5
	<Count : Expression> "random" "bytes"
begin
	MCDataExecRandomBytes(Count, output)
end syntax

----------------------------------------------------------------
-- Conversion between bytes and numbers
----------------------------------------------------------------

/*
Summary:	Create a 1-byte data value from a number

Value:		The value for the new data value

Description:
Returns a byte of binary data, created using the given value.  The
<Value> must be between 0 and 255 (inclusive).

Tags: Binary
*/
syntax ByteWithCode is prefix operator with precedence 2
	"the" "byte" "with" "code" <Value: Expression>
begin
	MCByteEvalByteWithCode(Value, output)
end syntax

/*
Summary:	Get the numeric value of a single byte.

Target:	A 1-byte binary data value.

Description:
Returns the numeric representation of a single byte of binary data.

Tags: Binary
*/
syntax CodeOfByte is prefix operator with precedence 2
	"the" "code" "of" <Target: Expression>
begin
	MCByteEvalCodeOfByte(Target, output)
end syntax

end module
