www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to avoid code duplication?

reply "Suliman" <evermind live.ru> writes:
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.
Mar 31 2015
next sibling parent "Suliman" <evermind live.ru> writes:
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.
Mar 31 2015
prev sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
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.
Mar 31 2015
parent reply "Suliman" <evermind live.ru> writes:
Rikki, could you explain? I did not understand where it can help 
me
Mar 31 2015
parent Rikki Cattermole <alphaglosined gmail.com> writes:
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); }
Mar 31 2015