44#include " env.h"
55#include " env-inl.h"
66#include " string_bytes.h"
7+ #include " string_search.h"
78#include " util.h"
89#include " util-inl.h"
910#include " v8-profiler.h"
@@ -854,87 +855,156 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
854855}
855856
856857
857- int32_t IndexOf (const char * haystack,
858- size_t h_length,
859- const char * needle,
860- size_t n_length) {
861- CHECK_GE (h_length, n_length);
862- // TODO(trevnorris): Implement Boyer-Moore string search algorithm.
863- for (size_t i = 0 ; i < h_length - n_length + 1 ; i++) {
864- if (haystack[i] == needle[0 ]) {
865- if (memcmp (haystack + i, needle, n_length) == 0 )
866- return i;
867- }
868- }
869- return -1 ;
870- }
871-
872-
873858void IndexOfString (const FunctionCallbackInfo<Value>& args) {
874859 ASSERT (args[1 ]->IsString ());
875860 ASSERT (args[2 ]->IsNumber ());
876861
862+ enum encoding enc = ParseEncoding (args.GetIsolate (),
863+ args[3 ],
864+ UTF8);
865+
877866 THROW_AND_RETURN_UNLESS_BUFFER (Environment::GetCurrent (args), args[0 ]);
878867 SPREAD_ARG (args[0 ], ts_obj);
879868
880- node::Utf8Value str (args.GetIsolate (), args[1 ]);
881- int32_t offset_i32 = args[2 ]->Int32Value ();
882- uint32_t offset;
869+ Local<String> needle = args[1 ].As <String>();
870+ const char * haystack = ts_obj_data;
871+ const size_t haystack_length = ts_obj_length;
872+ const size_t needle_length = needle->Utf8Length ();
873+
874+
875+ if (needle_length == 0 || haystack_length == 0 ) {
876+ return args.GetReturnValue ().Set (-1 );
877+ }
878+
879+ int64_t offset_i64 = args[2 ]->IntegerValue ();
880+ size_t offset = 0 ;
883881
884- if (offset_i32 < 0 ) {
885- if (offset_i32 + static_cast <int32_t >(ts_obj_length ) < 0 )
882+ if (offset_i64 < 0 ) {
883+ if (offset_i64 + static_cast <int64_t >(haystack_length ) < 0 ) {
886884 offset = 0 ;
887- else
888- offset = static_cast <uint32_t >(ts_obj_length + offset_i32);
885+ } else {
886+ offset = static_cast <size_t >(haystack_length + offset_i64);
887+ }
889888 } else {
890- offset = static_cast <uint32_t >(offset_i32 );
889+ offset = static_cast <size_t >(offset_i64 );
891890 }
892891
893- if (str.length () == 0 ||
894- ts_obj_length == 0 ||
895- (offset != 0 && str.length () + offset <= str.length ()) ||
896- str.length () + offset > ts_obj_length)
892+ if (haystack_length < offset || needle_length + offset > haystack_length) {
897893 return args.GetReturnValue ().Set (-1 );
894+ }
898895
899- int32_t r =
900- IndexOf (ts_obj_data + offset, ts_obj_length - offset, *str, str.length ());
901- args.GetReturnValue ().Set (r == -1 ? -1 : static_cast <int32_t >(r + offset));
902- }
896+ size_t result = haystack_length;
897+
898+ if (enc == UCS2) {
899+ String::Value needle_value (needle);
900+ if (*needle_value == nullptr )
901+ return args.GetReturnValue ().Set (-1 );
902+
903+ if (haystack_length < 2 || needle_value.length () < 1 ) {
904+ return args.GetReturnValue ().Set (-1 );
905+ }
906+
907+ result = SearchString (reinterpret_cast <const uint16_t *>(haystack),
908+ haystack_length / 2 ,
909+ reinterpret_cast <const uint16_t *>(*needle_value),
910+ needle_value.length (),
911+ offset / 2 );
912+ result *= 2 ;
913+ } else if (enc == UTF8) {
914+ String::Utf8Value needle_value (needle);
915+ if (*needle_value == nullptr )
916+ return args.GetReturnValue ().Set (-1 );
917+
918+ result = SearchString (reinterpret_cast <const uint8_t *>(haystack),
919+ haystack_length,
920+ reinterpret_cast <const uint8_t *>(*needle_value),
921+ needle_length,
922+ offset);
923+ } else if (enc == BINARY) {
924+ uint8_t * needle_data = static_cast <uint8_t *>(malloc (needle_length));
925+ if (needle_data == nullptr ) {
926+ return args.GetReturnValue ().Set (-1 );
927+ }
928+ needle->WriteOneByte (
929+ needle_data, 0 , needle_length, String::NO_NULL_TERMINATION);
930+
931+ result = SearchString (reinterpret_cast <const uint8_t *>(haystack),
932+ haystack_length,
933+ needle_data,
934+ needle_length,
935+ offset);
936+ free (needle_data);
937+ }
903938
939+ args.GetReturnValue ().Set (
940+ result == haystack_length ? -1 : static_cast <int >(result));
941+ }
904942
905943void IndexOfBuffer (const FunctionCallbackInfo<Value>& args) {
906944 ASSERT (args[1 ]->IsObject ());
907945 ASSERT (args[2 ]->IsNumber ());
908946
947+ enum encoding enc = ParseEncoding (args.GetIsolate (),
948+ args[3 ],
949+ UTF8);
950+
909951 THROW_AND_RETURN_UNLESS_BUFFER (Environment::GetCurrent (args), args[0 ]);
910952 SPREAD_ARG (args[0 ], ts_obj);
911953 SPREAD_ARG (args[1 ], buf);
912- const int32_t offset_i32 = args[2 ]->Int32Value ();
913- uint32_t offset;
914954
915955 if (buf_length > 0 )
916956 CHECK_NE (buf_data, nullptr );
917957
918- if (offset_i32 < 0 ) {
919- if (offset_i32 + static_cast <int32_t >(ts_obj_length) < 0 )
958+ const char * haystack = ts_obj_data;
959+ const size_t haystack_length = ts_obj_length;
960+ const char * needle = buf_data;
961+ const size_t needle_length = buf_length;
962+
963+ if (needle_length == 0 || haystack_length == 0 ) {
964+ return args.GetReturnValue ().Set (-1 );
965+ }
966+
967+ int64_t offset_i64 = args[2 ]->IntegerValue ();
968+ size_t offset = 0 ;
969+
970+ if (offset_i64 < 0 ) {
971+ if (offset_i64 + static_cast <int64_t >(haystack_length) < 0 )
920972 offset = 0 ;
921973 else
922- offset = static_cast <uint32_t >(ts_obj_length + offset_i32 );
974+ offset = static_cast <size_t >(haystack_length + offset_i64 );
923975 } else {
924- offset = static_cast <uint32_t >(offset_i32 );
976+ offset = static_cast <size_t >(offset_i64 );
925977 }
926978
927- if (buf_length == 0 ||
928- ts_obj_length == 0 ||
929- (offset != 0 && buf_length + offset <= buf_length) ||
930- buf_length + offset > ts_obj_length)
979+ if (haystack_length < offset || needle_length + offset > haystack_length) {
931980 return args.GetReturnValue ().Set (-1 );
981+ }
932982
933- int32_t r =
934- IndexOf (ts_obj_data + offset, ts_obj_length - offset, buf_data, buf_length);
935- args.GetReturnValue ().Set (r == -1 ? -1 : static_cast <int32_t >(r + offset));
936- }
983+ size_t result = haystack_length;
937984
985+ if (enc == UCS2) {
986+ if (haystack_length < 2 || needle_length < 2 ) {
987+ return args.GetReturnValue ().Set (-1 );
988+ }
989+ result = SearchString (
990+ reinterpret_cast <const uint16_t *>(haystack),
991+ haystack_length / 2 ,
992+ reinterpret_cast <const uint16_t *>(needle),
993+ needle_length / 2 ,
994+ offset / 2 );
995+ result *= 2 ;
996+ } else {
997+ result = SearchString (
998+ reinterpret_cast <const uint8_t *>(haystack),
999+ haystack_length,
1000+ reinterpret_cast <const uint8_t *>(needle),
1001+ needle_length,
1002+ offset);
1003+ }
1004+
1005+ args.GetReturnValue ().Set (
1006+ result == haystack_length ? -1 : static_cast <int >(result));
1007+ }
9381008
9391009void IndexOfNumber (const FunctionCallbackInfo<Value>& args) {
9401010 ASSERT (args[1 ]->IsNumber ());
@@ -944,25 +1014,25 @@ void IndexOfNumber(const FunctionCallbackInfo<Value>& args) {
9441014 SPREAD_ARG (args[0 ], ts_obj);
9451015
9461016 uint32_t needle = args[1 ]->Uint32Value ();
947- int32_t offset_i32 = args[2 ]->Int32Value ();
948- uint32_t offset;
1017+ int64_t offset_i64 = args[2 ]->IntegerValue ();
1018+ size_t offset;
9491019
950- if (offset_i32 < 0 ) {
951- if (offset_i32 + static_cast <int32_t >(ts_obj_length) < 0 )
1020+ if (offset_i64 < 0 ) {
1021+ if (offset_i64 + static_cast <int64_t >(ts_obj_length) < 0 )
9521022 offset = 0 ;
9531023 else
954- offset = static_cast <uint32_t >(ts_obj_length + offset_i32 );
1024+ offset = static_cast <size_t >(ts_obj_length + offset_i64 );
9551025 } else {
956- offset = static_cast <uint32_t >(offset_i32 );
1026+ offset = static_cast <size_t >(offset_i64 );
9571027 }
9581028
9591029 if (ts_obj_length == 0 || offset + 1 > ts_obj_length)
9601030 return args.GetReturnValue ().Set (-1 );
9611031
9621032 void * ptr = memchr (ts_obj_data + offset, needle, ts_obj_length - offset);
9631033 char * ptr_char = static_cast <char *>(ptr);
964- args.GetReturnValue ().Set (
965- ptr ? static_cast < int32_t >(ptr_char - ts_obj_data) : -1 );
1034+ args.GetReturnValue ().Set (ptr ? static_cast < int >(ptr_char - ts_obj_data)
1035+ : -1 );
9661036}
9671037
9681038
0 commit comments