Kaynağa Gözat

Merge pull request #23685 from Kanabenki/add-store-csv-line

Add store_csv_line method for File
Rémi Verschelde 6 yıl önce
ebeveyn
işleme
5d00407388

+ 9 - 3
core/bind/core_bind.cpp

@@ -1754,9 +1754,9 @@ String _File::get_line() const {
 	return f->get_line();
 }
 
-Vector<String> _File::get_csv_line(String delim) const {
+Vector<String> _File::get_csv_line(const String &p_delim) const {
 	ERR_FAIL_COND_V(!f, Vector<String>());
-	return f->get_csv_line(delim);
+	return f->get_csv_line(p_delim);
 }
 
 /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
@@ -1853,6 +1853,11 @@ void _File::store_line(const String &p_string) {
 	f->store_line(p_string);
 }
 
+void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+	ERR_FAIL_COND(!f);
+	f->store_csv_line(p_values, p_delim);
+}
+
 void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) {
 
 	ERR_FAIL_COND(!f);
@@ -1936,6 +1941,7 @@ void _File::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_real"), &_File::get_real);
 	ClassDB::bind_method(D_METHOD("get_buffer", "len"), &_File::get_buffer);
 	ClassDB::bind_method(D_METHOD("get_line"), &_File::get_line);
+	ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
 	ClassDB::bind_method(D_METHOD("get_as_text"), &_File::get_as_text);
 	ClassDB::bind_method(D_METHOD("get_md5", "path"), &_File::get_md5);
 	ClassDB::bind_method(D_METHOD("get_sha256", "path"), &_File::get_sha256);
@@ -1943,7 +1949,6 @@ void _File::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_endian_swap", "enable"), &_File::set_endian_swap);
 	ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error);
 	ClassDB::bind_method(D_METHOD("get_var"), &_File::get_var);
-	ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
 
 	ClassDB::bind_method(D_METHOD("store_8", "value"), &_File::store_8);
 	ClassDB::bind_method(D_METHOD("store_16", "value"), &_File::store_16);
@@ -1954,6 +1959,7 @@ void _File::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("store_real", "value"), &_File::store_real);
 	ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &_File::store_buffer);
 	ClassDB::bind_method(D_METHOD("store_line", "line"), &_File::store_line);
+	ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &_File::store_csv_line, DEFVAL(","));
 	ClassDB::bind_method(D_METHOD("store_string", "string"), &_File::store_string);
 	ClassDB::bind_method(D_METHOD("store_var", "value"), &_File::store_var);
 

+ 2 - 2
core/bind/core_bind.h

@@ -455,6 +455,7 @@ public:
 
 	PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
 	String get_line() const;
+	Vector<String> get_csv_line(const String &p_delim = ",") const;
 	String get_as_text() const;
 	String get_md5(const String &p_path) const;
 	String get_sha256(const String &p_path) const;
@@ -480,12 +481,11 @@ public:
 
 	void store_string(const String &p_string);
 	void store_line(const String &p_string);
+	void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
 
 	virtual void store_pascal_string(const String &p_string);
 	virtual String get_pascal_string();
 
-	Vector<String> get_csv_line(String delim = ",") const;
-
 	void store_buffer(const PoolVector<uint8_t> &p_buffer); ///< store an array of bytes
 
 	void store_var(const Variant &p_var);

+ 25 - 3
core/os/file_access.cpp

@@ -346,9 +346,9 @@ String FileAccess::get_line() const {
 	return String::utf8(line.get_data());
 }
 
-Vector<String> FileAccess::get_csv_line(String delim) const {
+Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
 
-	ERR_FAIL_COND_V(delim.length() != 1, Vector<String>());
+	ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>());
 
 	String l;
 	int qc = 0;
@@ -376,7 +376,7 @@ Vector<String> FileAccess::get_csv_line(String delim) const {
 		CharType c = l[i];
 		CharType s[2] = { 0, 0 };
 
-		if (!in_quote && c == delim[0]) {
+		if (!in_quote && c == p_delim[0]) {
 			strings.push_back(current);
 			current = String();
 		} else if (c == '"') {
@@ -525,6 +525,28 @@ void FileAccess::store_line(const String &p_line) {
 	store_8('\n');
 }
 
+void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+
+	ERR_FAIL_COND(p_delim.length() != 1);
+
+	String line = "";
+	int size = p_values.size();
+	for (int i = 0; i < size; ++i) {
+		String value = p_values[i];
+
+		if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n")) {
+			value = "\"" + value.replace("\"", "\"\"") + "\"";
+		}
+		if (i < size - 1) {
+			value += p_delim;
+		}
+
+		line += value;
+	}
+
+	store_line(line);
+}
+
 void FileAccess::store_buffer(const uint8_t *p_src, int p_length) {
 
 	for (int i = 0; i < p_length; i++)

+ 2 - 1
core/os/file_access.h

@@ -112,7 +112,7 @@ public:
 	virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
 	virtual String get_line() const;
 	virtual String get_token() const;
-	virtual Vector<String> get_csv_line(String delim = ",") const;
+	virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
 
 	/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
 	 * It's not about the current CPU type but file formats.
@@ -136,6 +136,7 @@ public:
 
 	virtual void store_string(const String &p_string);
 	virtual void store_line(const String &p_line);
+	virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
 
 	virtual void store_pascal_string(const String &p_string);
 	virtual String get_pascal_string();

+ 12 - 1
doc/classes/File.xml

@@ -100,7 +100,7 @@
 			<argument index="0" name="delim" type="String" default="&quot;,&quot;">
 			</argument>
 			<description>
-				Returns the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma).
+				Returns the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma), it should be one character long.
 			</description>
 		</method>
 		<method name="get_double" qualifiers="const">
@@ -327,6 +327,17 @@
 				Stores the given array of bytes in the file.
 			</description>
 		</method>
+		<method name="store_csv_line">
+			<return type="void">
+			</return>
+			<argument index="0" name="values" type="PoolStringArray" default="&quot;,&quot;">
+			</argument>
+			<argument index="1" name="delim" type="String" default="&quot;,&quot;">
+			</argument>
+			<description>
+				Store the given [PoolStringArray] in the file as a line formatted in the CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma), it should be one character long.
+			</description>
+		</method>
 		<method name="store_double">
 			<return type="void">
 			</return>