<commit_before>import net/[Socket, Address, DNS, Exceptions]
import io/[Reader, Writer]
import berkeley into socket
import text/Buffer

/**
    A stream based socket interface.
 */
StreamSocket: class extends Socket {
    remote: SocketAddress

    /**
       Create a new socket to a given remote address

       :param remote: The address of the host to eventually connect to.
     */
    init: func ~addr(=remote) {
        super(remote family(), SocketType STREAM, 0)
    }

    /**
       Create a new socket to a given remote address with a specific
       file descriptor.

       :param remote: The address of the host to eventually connect to.
     */
    init: func ~addrDescriptor(=remote, .descriptor) {
        super(remote family(), SocketType STREAM, 0, descriptor)
    }

    /**
       Create a new socket to a given hostname and port number

       :param host: The hostname, for example 'localhost', or 'www.example.org'
       :param port: The port, for example 8080, or 80.
     */
    init: func ~hostAndPort(host: String, port: Int) {
        init(host, port, SocketFamily UNSPEC)
    }


    init: func ~family(host: String, port: Int, family: Int) {
        ip := DNS resolveOne(host, SocketType STREAM, family)
        init(SocketAddress new(ip, port))
    }

    /**
       Attempt to connect this socket to the remote host.

       :throws: A SocketError if something went wrong
     */
    connect: func {
        if(socket connect(descriptor, remote addr(), remote length()) == -1) {
            SocketError new() throw()
        }
    }

    /**
       :return: A reader that reads data from this socket
     */
    reader: func -> StreamSocketReader {
        return StreamSocketReader new(this)
    }

    /**
       :return: A writer that writes data to this socket
     */
    writer: func -> StreamSocketWriter {
        return StreamSocketWriter new(this)
    }

    /**
       Send data through this socket
       :param data: The data to be sent
       :param length: The length of the data to be sent
       :param flags: Send flags

       :return: The number of bytes sent
     */
    send: func ~withLength(data: String, length: SizeT, flags: Int) -> Int {
        bytesSent := socket send(descriptor, data, length, flags)
        if(bytesSent == -1) {
            SocketError new() throw()
        }
        return bytesSent
    }

    /**
       Send a string through this socket
       :param data: The string to be sent
       :param flags: Send flags

       :return: The number of bytes sent
     */
    send: func ~withFlags(data: String, flags: Int) -> Int {
        send(data, data length(), flags)
    }

    /**
       Send a string through this socket
       :param flags: Send flags

       :return: The number of bytes sent
     */
    send: func(data: String) -> Int { send(data, 0) }

    /**
       Send a byte through this socket
       :param byte: The byte to send
       :param flags: Send flags
     */
    sendByte: func ~withFlags(byte: Char, flags: Int) {
        if(socket send(descriptor, byte&, Char size, flags) == -1) {
            SocketError new() throw()
        }
    }<commit_msg>added resend functionality to socket send<commit_after>import net/[Socket, Address, DNS, Exceptions]
import io/[Reader, Writer]
import berkeley into socket
import text/Buffer

/**
    A stream based socket interface.
 */
StreamSocket: class extends Socket {
    remote: SocketAddress

    /**
       Create a new socket to a given remote address

       :param remote: The address of the host to eventually connect to.
     */
    init: func ~addr(=remote) {
        super(remote family(), SocketType STREAM, 0)
    }

    /**
       Create a new socket to a given remote address with a specific
       file descriptor.

       :param remote: The address of the host to eventually connect to.
     */
    init: func ~addrDescriptor(=remote, .descriptor) {
        super(remote family(), SocketType STREAM, 0, descriptor)
    }

    /**
       Create a new socket to a given hostname and port number

       :param host: The hostname, for example 'localhost', or 'www.example.org'
       :param port: The port, for example 8080, or 80.
     */
    init: func ~hostAndPort(host: String, port: Int) {
        init(host, port, SocketFamily UNSPEC)
    }


    init: func ~family(host: String, port: Int, family: Int) {
        ip := DNS resolveOne(host, SocketType STREAM, family)
        init(SocketAddress new(ip, port))
    }

    /**
       Attempt to connect this socket to the remote host.

       :throws: A SocketError if something went wrong
     */
    connect: func {
        if(socket connect(descriptor, remote addr(), remote length()) == -1) {
            SocketError new() throw()
        }
    }

    /**
       :return: A reader that reads data from this socket
     */
    reader: func -> StreamSocketReader {
        return StreamSocketReader new(this)
    }

    /**
       :return: A writer that writes data to this socket
     */
    writer: func -> StreamSocketWriter {
        return StreamSocketWriter new(this)
    }

    /**
       Send data through this socket
       :param data: The data to be sent
       :param length: The length of the data to be sent
       :param flags: Send flags
       :param resend: Attempt to resend any data left unsent

       :return: The number of bytes sent
     */
    send: func ~withLength(data: String, length: SizeT, flags: Int, resend: Bool) -> Int {
        bytesSent := socket send(descriptor, data, length, flags)

        if (resend)
            while(bytesSent < length && bytesSent != -1) {
                dataSubstring := data substring(bytesSent)
                bytesSent += socket send(descriptor, dataSubstring, dataSubstring length(), flags)
            }
        
        if(bytesSent == -1)
            SocketError new() throw()

        return bytesSent
    }

    /**
       Send a string through this socket
       :param data: The string to be sent
       :param flags: Send flags
       :param resend: Attempt to resend any data left unsent

       :return: The number of bytes sent
     */
    send: func ~withFlags(data: String, flags: Int, resend: Bool) -> Int {
        send(data, data length(), flags, resend)
    }

    /**
       Send a string through this socket
       :param data: The string to be sent
       :param resend: Attempt to resend any data left unsent      

       :return: The number of bytes sent
     */
    send: func ~withResend(data: String, resend: Bool) -> Int { send(data, 0, resend) }
    
    /**
       Send a string through this socket with resend attempted for unsent data
       :param data: The string to be sent

       :return: The number of bytes sent
     */
    send: func(data: String) -> Int { send(data, true) }

    /**
       Send a byte through this socket
       :param byte: The byte to send
       :param flags: Send flags
     */
    sendByte: func ~withFlags(byte: Char, flags: Int) {
        if(socket send(descriptor, byte&, Char size, flags) == -1) {
            SocketError new() throw()
        }
    }
{'fraction_non_alphanumeric': 0.09515765765765766, 'fraction_numerical': 0.003519144144144144, 'mean_word_length': 2.1662210338680925, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2193702', 'n_tokens_mistral': 2004, 'n_tokens_neox': 1919, 'n_words': 779}