1 // Written in the D programming language. 2 3 /** This module is used to manipulate _path strings. 4 5 Authors: 6 Lars Tandle Kyllingstad, 7 $(WEB digitalmars.com, Walter Bright), 8 Grzegorz Adam Hankiewicz, 9 Thomas Kühne, 10 $(WEB erdani.org, Andrei Alexandrescu) 11 Copyright: 12 Copyright (c) 2000-2014, the authors. All rights reserved. 13 License: 14 $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0) 15 Source: 16 $(SARGONSRC src/sargon/_path/_setext.d) 17 */ 18 19 module sargon.path.setext; 20 21 import std.path; 22 23 import std.range; 24 import std.traits : isSomeChar; 25 import std.utf : byChar; 26 27 import sargon.path.stripext; 28 29 /** Algorithm that accepts a _path as an InputRange and a file extension as an InputRange, 30 and returns an InputRange that produces a char string containing the _path given 31 by $(D path), but where 32 the extension has been set to $(D ext). 33 34 If the filename already has an extension, it is replaced. If not, the 35 extension is simply appended to the filename. Including a leading dot 36 in $(D ext) is optional. 37 38 If the extension is empty, this function produces the equivalent of 39 $(LREF stripExtension) applied to path. 40 41 The algorithm is lazy, does not allocate, does not throw, and is pure. 42 */ 43 auto setExt(R1, R2)(R1 path, R2 ext) 44 if (isInputRange!R1 && isSomeChar!(ElementType!R1) && 45 isInputRange!R2 && isSomeChar!(ElementType!R2)) 46 { 47 return chain(path.stripExt().byChar(), 48 "."[0 .. 1 - cast(size_t)(ext.empty || ext.front() == '.')].byChar(), 49 ext.byChar()); 50 } 51 52 /// 53 unittest 54 { 55 import std.algorithm : copy; 56 import std.array : appender; 57 58 auto buf = appender!(char[])(); 59 60 "file".setExt("ext").copy(&buf); 61 assert(buf.data == "file.ext"); 62 } 63 64 unittest 65 { 66 import std.internal.scopebuffer; 67 import std.stdio; 68 import std.path; 69 import std.array; 70 import std.algorithm; 71 import std.typetuple : TypeTuple; 72 import std.conv : to; 73 74 void test(C1,C2)(const(C1)[] file, const(C2)[] ext, string expectedResult) 75 { 76 char[10] tmpbuf = void; 77 auto buf = ScopeBuffer!char(tmpbuf); 78 scope(exit) buf.free(); 79 80 buf.length = 0; 81 file.setExt(ext).byChar().copy(&buf); 82 assert(buf[] == expectedResult); 83 } 84 85 auto testData = [ 86 ["file", "ext", "file.ext"], 87 ["file", ".ext", "file.ext"], 88 ["file.", ".ext", "file.ext"], 89 ["file.", "ext", "file.ext"], 90 ["file.old", "new", "file.new"], 91 ["file", "", "file"], 92 ["file.exe", "", "file"] 93 ]; 94 95 foreach (S1; TypeTuple!(string, wstring, dstring)) 96 { 97 foreach (S2; TypeTuple!(string, wstring, dstring)) 98 { 99 foreach (testCase; testData) 100 { 101 test(testCase[0].to!S1, testCase[1].to!S2, testCase[2]); 102 } 103 } 104 } 105 106 auto abuf = appender!(char[])(); 107 "file".setExt("ext").copy(&abuf); 108 assert(abuf.data == "file.ext"); 109 } 110 111 112