Thread overview
How to avoid code duplication?
Apr 01, 2015
Suliman
Apr 01, 2015
Suliman
Apr 01, 2015
Rikki Cattermole
Apr 01, 2015
Suliman
Apr 01, 2015
Rikki Cattermole
April 01, 2015
The situation is next:

I have got the function that get arrays of lognames and logfullname:

void loginsert(string [] lognames, string [] logfullname)
{
	if(logfullname[i].endsWith("txt"))
	{
		auto file = File(logfullname[i], "r");
		foreach (line; file.byLine)
		{
			// long manupulation with strings
		}
	}

}

But now need add supporting passing to function not only txt files, but also zip archives.
The problem that now I see only one way to do adding zip -- add block: if(logfullname[i].endsWith("zip"))
And in it do everything with unpacking content of archive like:

	foreach(ArchiveMember am; zip.directory)
	{
		string file = cast(string)zip.expand(am);
		foreach (line; file.lineSplitter())
			{
				
			}
	}
	
and put inside it some same content that I am doing in "long manupulation with strings".


Maybe there is any better way? But I really can't understand it because auto file = File(logfullname[i], "r"); can't read unpacked content of archive.
April 01, 2015
Maybe there is way to access of element of archive in the same way as to txt file? I looked, but it's seems that constructor accept only path to file. But I can't understand how to set path to unpacked element of archive.
April 01, 2015
On 1/04/2015 6:15 p.m., Suliman wrote:
>
> The situation is next:
>
> I have got the function that get arrays of lognames and logfullname:
>
> void loginsert(string [] lognames, string [] logfullname)
> {
>      if(logfullname[i].endsWith("txt"))
>      {
>          auto file = File(logfullname[i], "r");
>          foreach (line; file.byLine)
>          {
>              // long manupulation with strings
>          }
>      }
>
> }
>
> But now need add supporting passing to function not only txt files, but
> also zip archives.
> The problem that now I see only one way to do adding zip -- add block:
> if(logfullname[i].endsWith("zip"))
> And in it do everything with unpacking content of archive like:
>
>      foreach(ArchiveMember am; zip.directory)
>      {
>          string file = cast(string)zip.expand(am);
>          foreach (line; file.lineSplitter())
>              {
>
>              }
>      }
>
> and put inside it some same content that I am doing in "long
> manupulation with strings".
>
>
> Maybe there is any better way? But I really can't understand it because
> auto file = File(logfullname[i], "r"); can't read unpacked content of
> archive.

Use InputRange!string aka an input range which gives you elements. It can wrap up the behavior for getting the values.
April 01, 2015
Rikki, could you explain? I did not understand where it can help me
April 01, 2015
On 1/04/2015 7:19 p.m., Suliman wrote:
> Rikki, could you explain? I did not understand where it can help me

Here is some example code. While I've only implemented one InputRange!string instance. You would probably have one, for just zip's and another raw text files. Keep in mind it returns only a single line from standard input.

In other words, let the range handle reading a line from a file.

import std.range;
import std.stdio;

class Range : InputRange!string {
	private {
		string buffer;
	}
	
	this() {
		popFront;
	}
	
	@property {
		string front() {
			return buffer;
		}
		
		bool empty() {
			return false;
		}
	}
	
	void popFront() {
		buffer = readln();
	}

	string moveFront() {
		string ret = front();
		popFront();
		return ret;
	}
	
	int opApply(int delegate(string) del) {
		int result;
		
		while(!empty()) {
			result = del(moveFront());
			
			if (result)
				break;
		}
		
		return result;
	}
	
	int opApply(int delegate(size_t, string) del) {
		int result;
		size_t offset;
		
		while(!empty()) {
			result = del(offset, moveFront());
			
			if (result)
				break;
			offset++;
		}
		
		return result;
	}
}

void myfunc(InputRange!string input) {
	foreach(line; input) {
		writeln("GOT [line]: ", line);
	}
}

void main() {
	InputRange!string theRange = new Range();
	myfunc(theRange);
}