/*
* Copyright (c) 2013, 2016, Jonathan Schleifer <js@webkeks.org>
*
* https://heap.zone/git/?p=objweb.git
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#import "OWTemplate.h"
#import "OWTemplateMissingException.h"
static OFDictionary *templates = nil;
@implementation OWTemplate
@synthesize content = _content;
+ (void)initialize
{
void *pool;
OFFileManager *fileManager;
OFArray *files;
OFMutableDictionary *tmp;
if (self != [OWTemplate class])
return;
pool = objc_autoreleasePoolPush();
fileManager = [OFFileManager defaultManager];
files = [fileManager contentsOfDirectoryAtPath: @"templates"];
tmp = [OFMutableDictionary dictionaryWithCapacity: [files count]];
for (OFString *file in files) {
OFString *name, *path;
OWTemplate *template;
if (![file hasSuffix: @".html"])
continue;
name = [file stringByDeletingPathExtension];
path = [@"templates" stringByAppendingPathComponent: file];
template = [[[OWTemplate alloc] init] autorelease];
template->_content = [[OFString alloc]
initWithContentsOfFile: path];
[tmp setObject: template
forKey: name];
}
[tmp makeImmutable];
templates = [tmp retain];
objc_autoreleasePoolPop(pool);
}
+ (instancetype)templateForName: (OFString*)name
{
OWTemplate *template = [templates objectForKey: name];
if (template == nil)
@throw [OWTemplateMissingException exceptionWithName: name];
return template;
}
- (void)dealloc
{
[_content release];
[super dealloc];
}
- (OFString*)contentWithVariables: (OFDictionary*)variables
{
OFMutableString *ret = [OFMutableString string];
void *pool = objc_autoreleasePoolPush();
size_t i, last;
if ([variables count] == 0)
return [self content];
i = [_content rangeOfString: @"${"].location;
last = 0;
while (i < _content.length) {
OFString *name, *value;
size_t end;
[ret appendString:
[_content substringWithRange: of_range(last, i - last)]];
end = [_content
rangeOfString: @"}"
options: 0
range: of_range(i, _content.length - i)].location;
name = [_content
substringWithRange: of_range(i + 2, end - i - 2)];
value = [[variables objectForKey: name] description];
if (![name hasPrefix: @"="])
value = [value stringByXMLEscaping];
if (value == nil)
value = @"";
[ret appendString: value];
last = end + 1;
i = [_content
rangeOfString: @"${"
options: 0
range: of_range(end, _content.length - end)].location;
}
[ret appendString: [_content substringWithRange:
of_range(last, _content.length - last)]];
[ret makeImmutable];
objc_autoreleasePoolPop(pool);
return ret;
}
@end
@implementation OFStream (OWTemplate)
- (void)writeTemplate: (OFString*)name
{
[self writeString: [[OWTemplate templateForName: name] content]];
}
- (void)writeTemplate: (OFString*)name
variables: (OFDictionary*)variables
{
[self writeString: [[OWTemplate templateForName: name]
contentWithVariables: variables]];
}
@end