cicpoffs/cicpps.cpp

114 lines
5.1 KiB
C++
Raw Normal View History

2020-05-19 02:13:51 +00:00
/* MIT License
*
* Copyright (c) 2020 Adler Neves <adlerosn@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "cicpps.hpp"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cwctype>
#include <vector>
#include <string>
#include <filesystem>
#include <algorithm>
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
namespace fs = std::filesystem;
std::wstring to_wide_string(std::string normal){
return std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(normal);
}
char* clone_string(const char* source){
char* cloned = (char*) calloc(strlen(source)+1, sizeof(char));
strcpy(cloned, source);
return cloned;
}
const char* recursively_search_case_insensitively(std::string remaining, std::string processed="/"){
//fprintf(stderr, "[0] %s => %s\n", processed.c_str(), remaining.c_str());
if(remaining.length()<=0){
return clone_string(processed.c_str());
}
std::string sep = (processed.length()==1) ? "" : "/";
std::size_t first_slash_pos = remaining.find_first_of('/');
std::string thispart(remaining.substr(0, first_slash_pos));
std::string nextRemaining = "";
if(first_slash_pos != std::string::npos)
nextRemaining = remaining.substr(first_slash_pos+1);
//fprintf(stderr, "[1] %s => %s => %s\n", processed.c_str(), thispart.c_str(), nextRemaining.c_str());
if(!fs::exists(fs::path(processed))){ // if processed does not exist, forward as is
return clone_string((processed+sep+remaining).c_str());
} else {
std::string desiredFragment = processed+sep+thispart;
if(fs::exists(fs::path(desiredFragment))){ // if case sensivivity here is correct
return recursively_search_case_insensitively(nextRemaining, desiredFragment);
} else { // if case sensivivity here is incorrect
bool found = false;
std::wstring wpart = to_wide_string(thispart);
std::transform(wpart.begin(), wpart.end(), wpart.begin(), std::towlower);
for(const fs::directory_entry &entry : fs::directory_iterator(processed)){
std::string filename = fs::path(entry.path()).filename();
//fprintf(stderr, "[2] %s\n", filename.c_str());
std::wstring wcandidate = to_wide_string(filename);
std::wstring wcandidatel = wcandidate;
std::transform(wcandidatel.begin(), wcandidatel.end(), wcandidatel.begin(), std::towlower);
if(wpart==wcandidatel){
//fprintf(stderr, "[3] %s --replacing--> %s\n", filename.c_str(), thispart.c_str());
thispart = filename;
found = true;
break;
}
}
if(!found){
//fprintf(stderr, "[4] err: %s\n", (processed+sep+remaining).c_str());
return clone_string((processed+sep+remaining).c_str());
}else{
//fprintf(stderr, "[4] scc: %s\n", (processed+sep+thispart).c_str());
return recursively_search_case_insensitively(nextRemaining, processed+sep+thispart); // remember that we changed 'thispart' in the loop
}
}
}
}
const char* correct_case_sensitivity_for(const char* absolute_mp, const char* relative_cs){
if(absolute_mp==NULL || relative_cs==NULL) return NULL;
const char* relative_cs_nls = relative_cs[0]=='/' ? &relative_cs[1] : relative_cs; // remove leading slash
int absolute_mp_len = strlen(absolute_mp);
int relative_cs_nls_len = strlen(relative_cs_nls);
char* full_relative_path = (char*) calloc(absolute_mp_len+relative_cs_nls_len+2, sizeof(char));
strcpy(full_relative_path, absolute_mp);
full_relative_path[absolute_mp_len] = '/';
strcpy(&full_relative_path[absolute_mp_len+1], relative_cs_nls);
if(fs::exists(fs::path(full_relative_path))){
return full_relative_path;
} else {
const char* full_absolute_fixed_path = recursively_search_case_insensitively(&full_relative_path[1]);
free((void*) full_relative_path);
//fprintf(stderr, "[5] scc: %s\n", full_absolute_fixed_path);
return full_absolute_fixed_path;
}
}