Skip to content

Commit

Permalink
Implemented Validator::GetInverse(), SetInverse() and Is Inversed() w…
Browse files Browse the repository at this point in the history
…ith tests.

Modified Validator::Validate() to support the new 'inverse' attribute.
Created new TestValidator.* unit tests for the new 'inverse' attribute.
For issue #49.
  • Loading branch information
end2endzone committed Aug 4, 2020
1 parent 9c01ec2 commit 3be678e
Show file tree
Hide file tree
Showing 3 changed files with 383 additions and 15 deletions.
22 changes: 22 additions & 0 deletions include/shellanything/Validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,25 @@ namespace shellanything
/// </summary>
void SetFileExists(const std::string & iFileExists);

/// <summary>
/// Getter for the 'inserve' parameter.
/// </summary>
const std::string & GetInserve() const;

/// <summary>
/// Setter for the 'inserve' parameter.
/// </summary>
void SetInserve(const std::string & iInserve);

/// <summary>
/// Returns true if the given attribute name is in the list of inversed attributes.
/// The accepted attribute names matches the list of attributes of <validity> or <visibility> elements in a Configuration File.
/// See the 'User Manual' for details.
/// </summary>
/// <param name="name">The name of the attribute. The name is case sensitive.</param>
/// <returns>Returns true if the given attribute name is in the list of inversed attributes. Returns false otherwise.</returns>
bool IsInversed(const char * name) const;

/// <summary>
/// Validate the given context against a set of constraints.
/// The possible constraints includes a minimum/maximum number of files/directories selected,
Expand All @@ -102,6 +121,8 @@ namespace shellanything
/// ...
/// Note: this function is used to enable or disable a menu.
/// </summary>
/// <param name="iContext">The context used for validating.</param>
/// <returns>Returns true if the given context is valid against the set of constraints. Returns false otherwise.</returns>
bool Validate(const Context & iContext) const;

private:
Expand All @@ -110,6 +131,7 @@ namespace shellanything
std::string mProperties;
std::string mFileExtensions;
std::string mFileExists;
std::string mInverse;
};

} //namespace shellanything
Expand Down
114 changes: 101 additions & 13 deletions src/Validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,83 @@ namespace shellanything
mFileExists = iFileExists;
}

bool Validator::Validate(const Context & iContext) const
const std::string & Validator::GetInserve() const
{
return mInverse;
}

void Validator::SetInserve(const std::string & iInserve)
{
mInverse = iInserve;
}

bool Validator::IsInversed(const char * name) const
{
if (iContext.GetNumFiles() > mMaxFiles)
return false; //too many files selected
if (name == NULL)
return false;
if (name[0] == '\0')
return false;

size_t name_length = std::string(name).size();
size_t search_index = 0;
size_t pos = mInverse.find(name, search_index);
while( pos != std::string::npos)
{
// The name of the attribute was found.

// To prevent finding attribute 'foo' from attribute 'foobar',
// The end of the attribute should match the end of the mInverse string or
// followed by a ';' character.
char next = '\0';
if (pos + name_length < mInverse.size())
next = mInverse[pos + name_length];

if (next == '\0' || next == ';')
{
// Good. Keep looking

// To prevent finding attribute 'bar' from attribute 'foobar',
// The beginning of the attribute should match the beginning of the mInverse string or
// the previous character must be a ';' character.
if (pos == 0)
return true; // We have a match!

char previous = ';';
if (pos >= 1)
previous = mInverse[pos - 1];

if (previous == ';')
return true; // We have a match!
}

if (iContext.GetNumDirectories() > mMaxDirectories)
// This is not the attribute we are looking for.
// Move the searched position at the next possible offset
// and search again.
search_index += name_length;
pos = mInverse.find(name, search_index);
}

return false;
}

bool Validator::Validate(const Context & iContext) const
{
bool maxfiles_inversed = IsInversed("maxfiles");
if (!maxfiles_inversed && iContext.GetNumFiles() > mMaxFiles)
return false; //too many files selected
if (maxfiles_inversed && iContext.GetNumFiles() <= mMaxFiles)
return false; //too many files selected

bool maxfolders_inversed = IsInversed("maxfolders");
if (!maxfolders_inversed && iContext.GetNumDirectories() > mMaxDirectories)
return false; //too many directories selected
if (maxfolders_inversed && iContext.GetNumDirectories() <= mMaxDirectories)
return false; //too many directories selected

//validate properties
PropertyManager & pmgr = PropertyManager::GetInstance();
const std::string properties = pmgr.Expand(mProperties);
bool properties_inversed = IsInversed("properties");
if (!properties.empty())
{
//split
Expand All @@ -153,16 +219,32 @@ namespace shellanything
for(size_t i=0; i<property_list.size(); i++)
{
const std::string & p = property_list[i];
if (!pmgr.HasProperty(p))
return false; //missing property
const std::string & p_value = pmgr.GetProperty(p);
if (p_value.empty())
return false; //empty

if (!properties_inversed)
{
if (!pmgr.HasProperty(p))
return false; //missing property
const std::string & p_value = pmgr.GetProperty(p);
if (p_value.empty())
return false; //empty
}
else
{
// properties_inversed=true
if (pmgr.HasProperty(p))
{
const std::string & p_value = pmgr.GetProperty(p);
if (!p_value.empty())
return false; //not empty
}
}

}
}

//validate file extentions
const std::string file_extensions = pmgr.Expand(mFileExtensions);
bool fileextensions_inversed = IsInversed("fileextensions");
if (!file_extensions.empty())
{
//split
Expand All @@ -178,13 +260,16 @@ namespace shellanything

//each file extension must be part of accepted_file_extensions
bool found = HasValue(accepted_file_extensions, current_file_extension);
if (!found)
if (!fileextensions_inversed && !found)
return false; //current file extension is not accepted
if (fileextensions_inversed && found)
return false; //current file extension is not accepted
}
}

//validate file/directory exists
const std::string file_exists = pmgr.Expand(mFileExists);
bool exists_inversed = IsInversed("exists");
if (!file_exists.empty())
{
//split
Expand All @@ -194,9 +279,12 @@ namespace shellanything
for(size_t i=0; i<mandatory_files.size(); i++)
{
const std::string & element = mandatory_files[i];
bool isFile = ra::filesystem::FileExistsUtf8(element.c_str());
bool isDir = ra::filesystem::DirectoryExistsUtf8(element.c_str());
if (!isFile && !isDir)
bool element_exists = false;
element_exists |= ra::filesystem::FileExistsUtf8(element.c_str());
element_exists |= ra::filesystem::DirectoryExistsUtf8(element.c_str());
if (!exists_inversed && !element_exists)
return false; //mandatory file/directory not found
if (exists_inversed && element_exists)
return false; //mandatory file/directory not found
}
}
Expand Down
Loading

0 comments on commit 3be678e

Please sign in to comment.