ObjFW  Documentation

/*
 * Copyright (c) 2008 - 2009
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "config.h"

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#import <objc/objc-api.h>
#ifdef __objc_INCLUDE_GNU
#define SEL_NAME(x) sel_get_name(x)
#else
#import <objc/runtime.h>
#define SEL_NAME(x) sel_getName(x)
#endif

#import "OFExceptions.h"
#import "OFTCPSocket.h"

#ifndef _WIN32
#include <errno.h>
#define GET_ERR	     errno
#define GET_SOCK_ERR errno
#define ERRFMT	     "Error string was: %s"
#define ERRPARAM     strerror(err)
#else
#include <windows.h>
#define GET_ERR	     GetLastError()
#define GET_SOCK_ERR WSAGetLastError()
#define ERRFMT	     "Error code was: %d"
#define ERRPARAM     err
#endif

#ifndef HAVE_ASPRINTF
#import "asprintf.h"
#endif

@implementation OFAllocFailedException
+ (Class)class
{
	return self;
}

- (OFString*)string
{
	return @"Allocating an object failed!";
}
@end

@implementation OFException
+ newWithClass: (Class)class_
{
	return [[self alloc] initWithClass: class_];
}

- initWithClass: (Class)class_
{
	self = [super init];

	class = class_;

	return self;
}

- (void)dealloc
{
	[string release];

	[super dealloc];
}

- (Class)inClass
{
	return class;
}

- (OFString*)string
{
	return string;
}
@end

@implementation OFNoMemException
+ newWithClass: (Class)class_
       andSize: (size_t)size
{
	return [[self alloc] initWithClass: class_
				   andSize: size];
}

- initWithClass: (Class)class_
	andSize: (size_t)size
{
	self = [super initWithClass: class_];

	req_size = size;

	return self;
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Could not allocate %zu bytes in class %s!",
			    req_size, [class name]];

	return string;
}

- (size_t)requestedSize
{
	return req_size;
}
@end

@implementation OFMemNotPartOfObjException
+ newWithClass: (Class)class_
    andPointer: (void*)ptr
{
	return [[self alloc] initWithClass: class_
				andPointer: ptr];
}

- initWithClass: (Class)class_
     andPointer: (void*)ptr
{
	self = [super initWithClass: class_];

	pointer = ptr;

	return self;
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Memory at %p was not allocated as part of object "
			    @"of class %s, thus the memory allocation was not "
			    @"changed! It is also possible that there was an "
			    @"attempt to free the same memory twice.",
			    pointer, [class name]];

	return string;
}

- (void*)pointer
{
	return pointer;
}
@end

@implementation OFNotImplementedException
+ newWithClass: (Class)class_
   andSelector: (SEL)selector_
{
	return [[self alloc] initWithClass: class_
			       andSelector: selector_];
}

- initWithClass: (Class)class_
    andSelector: (SEL)selector_
{
	self = [super initWithClass: class_];

	selector = selector_;

	return self;
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The method %s of class %s is not or not fully "
			    @"implemented!",
			    SEL_NAME(selector), [class name]];

	return string;
}
@end

@implementation OFOutOfRangeException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Value out of range in class %s!",
			    [class name]];

	return string;
}
@end

@implementation OFInvalidArgumentException
+ newWithClass: (Class)class_
   andSelector: (SEL)selector_
{
	return [[self alloc] initWithClass: class_
			       andSelector: selector_];
}

- initWithClass: (Class)class_
    andSelector: (SEL)selector_
{
	self = [super initWithClass: class_];

	selector = selector_;

	return self;
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The argument for method %s of class %s is "
	    		    @"invalid!",
			    SEL_NAME(selector), [class name]];

	return string;
}
@end

@implementation OFInvalidEncodingException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The encoding is invalid for class %s!",
			    [class name]];

	return string;
}
@end

@implementation OFInvalidFormatException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The format is invalid for class %s!",
			    [class name]];

	return string;
}
@end

@implementation OFInitializationFailedException
- (OFString*)cString
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Initialization failed for class %s!",
			    [class name]];

	return string;
}
@end

@implementation OFOpenFileFailedException
+ newWithClass: (Class)class_
       andPath: (OFString*)path_
       andMode: (OFString*)mode_
{
	return [[self alloc] initWithClass: class_
				   andPath: path_
				   andMode: mode_];
}

- initWithClass: (Class)class_
	andPath: (OFString*)path_
	andMode: (OFString*)mode_
{
	self = [super initWithClass: class_];

	path = [path_ retain];
	mode = [mode_ retain];
	err = GET_ERR;

	return self;
}

- (void)dealloc
{
	[path release];
	[mode release];

	[super dealloc];
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Failed to open file %s with mode %s in class %s! "
			    ERRFMT,
			    [path cString], [mode cString], [self name],
			    ERRPARAM];

	return string;
}

- (int)errNo
{
	return err;
}

- (OFString*)path
{
	return path;
}

- (OFString*)mode
{
	return mode;
}
@end

@implementation OFReadOrWriteFailedException
+ newWithClass: (Class)class_
       andSize: (size_t)size
     andNItems: (size_t)nitems
{
	return [[self alloc] initWithClass: class_
				   andSize: size
				 andNItems: nitems];
}

+ newWithClass: (Class)class_
       andSize: (size_t)size
{
	return [[self alloc] initWithClass: class_
				   andSize: size];
}

- initWithClass: (Class)class_
	andSize: (size_t)size
      andNItems: (size_t)nitems
{
	self = [super initWithClass: class_];

	req_size = size;
	req_items = nitems;
	has_items = YES;

	if (class_ == [OFTCPSocket class])
		err = GET_SOCK_ERR;
	else
		err = GET_ERR;

	return self;
}

- initWithClass: (Class)class_
	andSize: (size_t)size
{
	self = [super initWithClass: class_];

	req_size = size;
	req_items = 0;
	has_items = NO;

	if (class_ == [OFTCPSocket class])
		err = GET_SOCK_ERR;
	else
		err = GET_ERR;

	return self;
}

- (int)errNo
{
	return err;
}

- (size_t)requestedSize
{
	return req_size;
}

- (size_t)requestedItems
{
	return req_items;
}

- (BOOL)hasNItems
{
	return has_items;
}
@end

@implementation OFReadFailedException
- (OFString*)string
{
	if (string != nil)
		return string;;

	if (has_items)
		string = [[OFMutableString alloc]
		    initWithFormat: @"Failed to read %zu items of size %zu in "
				    @"class %s! " ERRFMT,
				    req_items, req_size, [class name],
				    ERRPARAM];
	else
		string = [[OFMutableString alloc]
		    initWithFormat: @"Failed to read %zu bytes in class %s! "
				    ERRFMT,
				    req_size, [class name], ERRPARAM];

	return string;
}
@end

@implementation OFWriteFailedException
- (OFString*)string
{
	if (string != nil)
		return string;

	if (has_items)
		string = [[OFMutableString alloc]
		    initWithFormat: @"Failed to write %zu items of size %zu in "
				    @"class %s! " ERRFMT,
				    req_items, req_size, [class name],
				    ERRPARAM];
	else
		string = [[OFMutableString alloc]
		    initWithFormat: @"Failed to write %zu bytes in class %s! "
				    ERRFMT,
				    req_size, [class name], ERRPARAM];

	return string;
}
@end

@implementation OFSetOptionFailedException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Setting an option in class %s failed!",
			    [class name]];

	return string;
}
@end

@implementation OFNotConnectedException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The socket of type %s is not connected or bound!",
			    [class name]];

	return string;
}
@end

@implementation OFAlreadyConnectedException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The socket of type %s is already connected or "
			    @"bound and thus can't be connected or bound "
			    @"again!",
			    [class name]];

	return string;
}
@end

@implementation OFAddressTranslationFailedException
+ newWithClass: (Class)class_
       andNode: (OFString*)node_
    andService: (OFString*)service_
{
	return [[self alloc] initWithClass: class_
				   andNode: node_
				andService: service_];
}

- initWithClass: (Class)class_
	andNode: (OFString*)node_
     andService: (OFString*)service_
{
	self = [super initWithClass: class_];

	node = [node_ retain];
	service = [service_ retain];
	err = GET_SOCK_ERR;

	return self;
}

- (void)dealloc
{
	[node release];
	[service release];

	[super dealloc];
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The service %s on %s could not be translated to "
			    @"an address in class %s. This means that either "
			    @"the node was not found, there is no such service "
			    @"on the node, there was a problem with the name "
			    @"server, there was a problem with your network "
			    @"connection or you specified an invalid node or "
			    @"service. " ERRFMT,
			    [service cString], [node cString], [class name],
			    ERRPARAM];

	return string;
}

- (int)errNo
{
	return err;
}

- (OFString*)node
{
	return node;
}

- (OFString*)service
{
	return service;
}
@end

@implementation OFConnectionFailedException
+ newWithClass: (Class)class_
       andNode: (OFString*)node_
    andService: (OFString*)service_
{
	return [[self alloc] initWithClass: class_
				   andNode: node_
				andService: service_];
}

- initWithClass: (Class)class_
	andNode: (OFString*)node_
     andService: (OFString*)service_
{
	self = [super initWithClass: class_];

	node	= [node_ retain];
	service	= [service_ retain];
	err	= GET_SOCK_ERR;

	return self;
}

- (void)dealloc
{
	[node release];
	[service release];

	[super dealloc];
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"A connection to service %s on node %s could not "
			    @"be established in class %s! " ERRFMT,
			    [node cString], [service cString], [class name],
			    ERRPARAM];

	return string;
}

- (int)errNo
{
	return err;
}

- (OFString*)node
{
	return node;
}

- (OFString*)service
{
	return service;
}
@end

@implementation OFBindFailedException
+ newWithClass: (Class)class_
       andNode: (OFString*)node_
    andService: (OFString*)service_
     andFamily: (int)family_
{
	return [[self alloc] initWithClass: class_
				   andNode: node_
				andService: service_
				 andFamily: family_];
}

- initWithClass: (Class)class_
	andNode: (OFString*)node_
     andService: (OFString*)service_
      andFamily: (int)family_
{
	self = [super initWithClass: class_];

	node	= [node_ retain];
	service	= [service_ retain];
	family	= family_;
	err	= GET_SOCK_ERR;

	return self;
}

- (void)dealloc
{
	[node release];
	[service release];

	[super dealloc];
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Binding service %s on node %s using family %d "
			    @"failed in class %s! " ERRFMT,
			    [service cString], [node cString], family,
			    [class name], ERRPARAM];

	return string;
}

- (int)errNo
{
	return err;
}

- (OFString*)node
{
	return node;
}

- (OFString*)service
{
	return service;
}

- (int)family
{
	return family;
}
@end

@implementation OFListenFailedException
+ newWithClass: (Class)class_
    andBackLog: (int)backlog_
{
	return [[self alloc] initWithClass: class_
				andBackLog: backlog_];
}

- initWithClass: (Class)class_
     andBackLog: (int)backlog_
{
	self = [super initWithClass: class_];

	backlog = backlog_;
	err = GET_SOCK_ERR;

	return self;
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Failed to listen in socket of type %s with a "
			    @"back log of %d! " ERRFMT,
			    [class name], backlog, ERRPARAM];

	return string;
}

- (int)errNo
{
	return err;
}

- (int)backLog
{
	return backlog;
}
@end

@implementation OFAcceptFailedException
- initWithClass: (Class)class_
{
	self = [super initWithClass: class_];

	err = GET_SOCK_ERR;

	return self;
}

- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Failed to accept connection in socket of type "
			    @"%s! " ERRFMT,
			    [class name], ERRPARAM];

	return string;
}

- (int)errNo
{
	return err;
}
@end

@implementation OFThreadJoinFailedException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"Joining a thread of class %s failed! Most "
			    @"likely, another thread already waits for the "
			    @"thread to join.",
			    [class name]];

	return string;
}
@end

@implementation OFThreadCanceledException
- (OFString*)string
{
	if (string != nil)
		return string;

	string = [[OFMutableString alloc]
	    initWithFormat: @"The requested action cannot be performed because "
			    @"the thread of class %s was canceled!",
			    [class name]];

	return string;
}
@end